module Vault::Usage # Client for the `Vault::Usage` HTTP API. class Client attr_reader :url # Raised if a non-UTC time is used with the client. class InvalidTimeError < Exception end # Instantiate a client. # # @param url [String] The URL to connect to. Include the username and # password to use when connecting. def initialize(url = nil) @url = url || ENV['VAULT_USAGE_URL'] end # Report that usage of a product, by a user or app, started at a # particular time. # # @param event_id [String] A UUID that uniquely identifies the usage # event. # @param product_name [String] The name of the product that was used, such # as `platform:dyno:logical` or `addon:memcache:100mb`. # @param consumer_hid [String] The Heroku ID, such as `app1234@heroku.com` # or `user1234@heroku.com`, that represents the user or app that used # the specified product. # @param start_time [Time] The beginning of the usage period, always in # UTC. # @param detail [Hash] Optionally, additional details to store with the # event. Keys must be of type `Symbol` and values may only be of type # `String`, `Fixnum`, `Bignum`, `Float`, `TrueClass`, `FalseClass` or # `NilClass`. # @raise [InvalidTimeError] Raised if a non-UTC start time is provided. # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an # unsuccessful HTTP status code. def open_usage_event(event_id, product_name, consumer_hid, start_time, detail=nil) unless start_time.zone.eql?('UTC') raise InvalidTimeError.new('Start time must be in UTC.') end path = "/products/#{product_name}/usage/#{consumer_hid}" + "/events/#{event_id}/open/#{iso_format(start_time)}" unless detail.nil? headers = {'Content-Type' => 'application/json'} body = MultiJson.dump(detail) end connection = Excon.new(@url) connection.put(path: path, headers: headers, body: body, expects: [201]) end # Report that usage of a product, by a user or app, stopped at a # particular time. # # @param event_id [String] A UUID that uniquely identifies the usage # event. # @param product_name [String] The name of the product that was used, such # as `platform:dyno:logical` or `addon:memcache:100mb`. # @param consumer_hid [String] The Heroku ID, such as `app1234@heroku.com` # or `user1234@heroku.com`, that represents the user or app that used # the specified product. # @param stop_time [Time] The end of the usage period, always in UTC. # @raise [InvalidTimeError] Raised if a non-UTC stop time is provided. # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an # unsuccessful HTTP status code. def close_usage_event(event_id, product_name, consumer_hid, stop_time) unless stop_time.zone.eql?('UTC') raise InvalidTimeError.new('Stop time must be in UTC.') end path = "/products/#{product_name}/usage/#{consumer_hid}" + "/events/#{event_id}/close/#{iso_format(stop_time)}" connection = Excon.new(@url) connection.put(path: path, expects: [201]) end # Report that usage of a product, by a user or app, started at a # particular time. # # @param event_id [String] A UUID that uniquely identifies the usage # event. # @param product_name [String] The name of the product that was used, such # as `platform:dyno:logical` or `addon:memcache:100mb`. # @param consumer_hid [String] The Heroku ID, such as `app1234@heroku.com` # or `user1234@heroku.com`, that represents the user or app that used # the specified product. # @param start_time [Time] The beginning of the usage period, always in # UTC. # @param stop_time [Time] The end of the usage period, always in UTC. # @param detail [Hash] Optionally, additional details to store with the # event. Keys must be of type `Symbol` and values may only be of type # `String`, `Fixnum`, `Bignum`, `Float`, `TrueClass`, `FalseClass` or # `NilClass`. # @raise [InvalidTimeError] Raised if a non-UTC start time is provided. # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an # unsuccessful HTTP status code. def open_close_usage_event(event_id, product_name, consumer_hid, start_time, stop_time, detail=nil) unless start_time.zone.eql?('UTC') raise InvalidTimeError.new('Start time must be in UTC.') end unless stop_time.zone.eql?('UTC') raise InvalidTimeError.new('Stop time must be in UTC.') end path = "/products/#{product_name}/usage/#{consumer_hid}" + "/events/#{event_id}/open/#{iso_format(start_time)}" + "/close/#{iso_format(stop_time)}" unless detail.nil? headers = {'Content-Type' => 'application/json'} body = MultiJson.dump(detail) end connection = Excon.new(@url) connection.put(path: path, headers: headers, body: body, expects: [201]) end # Request a single usage event. # # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an # unsuccessful HTTP status code. # @return [Array] A single usage event, matching the following format: # # ```json # {id: '', # product: '', # consumer: '', # start_time: '', # stop_time: '', # detail: {: , # : } # } # def usage_for_event(event_id) path = "/usage_events/#{event_id}" connection = Excon.new(@url) response = connection.get(path: path, expects: [200]) event = MultiJson.load(response.body, {symbolize_keys: true}) event.each do |key, value| event[key] = parse_date(value) if date?(value) end end # Get the usage events for the apps owned by the specified user during the # specified period. # # @param user_hid [String] The user HID, such as `user1234@heroku.com`, to # fetch usage data for. # @param start_time [Time] The beginning of the usage period, always in # UTC, within which events must overlap to be included in usage data. # @param stop_time [Time] The end of the usage period, always in UTC, # within which events must overlap to be included in usage data. # @param exclude [Array] Optionally, a list of product names, such as # `['platform:dyno:physical', 'addon:memcache:100mb']`, to be excluded # from usage data. # @param callback_url [String] The URL vault-usage will callback after generating # usage events JSON # @param snapshot [Boolean] Whether or not to return only events that were open # at the start_time # @raise [InvalidTimeError] Raised if a non-UTC start or stop time is # provided. # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an # unsuccessful HTTP status code. # @return [Array] A list of usage events for the specified user, matching # the following format: # # ``` # [{id: '', # product: '', # consumer: '', # start_time: