# frozen_string_literal: true module Pagerduty # Trigger incidents via the PagerDuty Events API version 1. # # @see https://v2.developer.pagerduty.com/docs/events-api PagerDuty Events # API V1 documentation # # @see Pagerduty.build # # @see Pagerduty::EventsApiV1::Incident # class EventsApiV1 # Rather than using this directly, use the {Pagerduty.build} method to # construct an instance. # # @option config [String] integration_key Authentication key for connecting # to PagerDuty. A UUID expressed as a 32-digit hexadecimal number. # Integration keys are generated by creating a new service, or creating a # new integration for an existing service in PagerDuty, and can be found # on a service's Integrations tab. This option is required. # # @option config [String] http_proxy.host The DNS name or IP address of the # proxy host. If nil or unprovided an HTTP proxy will not be used. # # @option config [String] http_proxy.port The TCP port to use to access the # proxy. # # @option config [String] http_proxy.username username if authorization is # required to use the proxy. # # @option config [String] http_proxy.password password if authorization is # required to use the proxy. # # @see Pagerduty.build # def initialize(config) @config = config end # Send PagerDuty a trigger event to report a new or ongoing problem. # # @example Trigger an incident # incident = pagerduty.trigger( # "" # ) # # @example Trigger an incident, providing more context and details # incident = pagerduty.trigger( # "FAILURE for production/HTTP on machine srv01.acme.com", # client: "Sample Monitoring Service", # client_url: "https://monitoring.service.com", # contexts: [ # { # type: "link", # href: "http://acme.pagerduty.com", # text: "View the incident on PagerDuty", # }, # { # type: "image", # src: "https://chart.googleapis.com/chart.png", # } # ], # details: { # ping_time: "1500ms", # load_avg: 0.75, # }, # ) # # @param [String] description A short description of the problem that led to # this trigger. This field (or a truncated version) will be used when # generating phone calls, SMS messages and alert emails. It will also # appear on the incidents tables in the PagerDuty UI. The maximum length # is 1024 characters. # # @option options [String] client The name of the monitoring client that is # triggering this event. # # @option options [String] client_url The URL of the monitoring client that # is triggering this event. # # @option options [Array] contexts An array of objects. Contexts to be # included with the incident trigger such as links to graphs or images. # # @option options [Hash] details An arbitrary hash containing any data you'd # like included in the incident log. # # @return [Pagerduty::EventsApiV1::Incident] The triggered incident. # # @raise [PagerdutyException] If PagerDuty responds with a status that is # not "success" # def trigger(description, options = {}) config = @config.merge(incident_key: options[:incident_key]) options = options.reject { |key| key == :incident_key } Incident.new(config).trigger(description, options) end # @param [String] incident_key Identifies the incident to which # this trigger event should be applied. If there's no open (i.e. # unresolved) incident with this key, a new one will be created. If # there's already an open incident with a matching key, this event will be # appended to that incident's log. The event key provides an easy way to # "de-dup" problem reports. If this field isn't provided, PagerDuty will # automatically open a new incident with a unique key. The maximum length # is 255 characters. # # @return [Pagerduty::EventsApiV1::Incident] The incident referenced by the # key. # # @raise [ArgumentError] If incident_key is nil # def incident(incident_key) raise ArgumentError, "incident_key is nil" if incident_key.nil? Incident.new(@config.merge(incident_key: incident_key)) end class Incident attr_reader :incident_key # @option (see Pagerduty::EventsApiV1#initialize) # # @option config [String] incident_key Identifies the incident to which # this trigger event should be applied. If there's no open # (i.e. unresolved) incident with this key, a new one will be created. # If there's already an open incident with a matching key, this event # will be appended to that incident's log. The event key provides an # easy way to "de-dup" problem reports. If this field isn't provided, # PagerDuty will automatically open a new incident with a unique key. # The maximum length is 255 characters. # def initialize(config) @integration_key = config.fetch(:integration_key) do raise ArgumentError "integration_key not provided" end @incident_key = config[:incident_key] @transport = Pagerduty::HttpTransport.new( path: "/generic/2010-04-15/create_event.json", proxy: config[:http_proxy], ) end # Send PagerDuty a trigger event to report a new or ongoing problem. When # PagerDuty receives a trigger event, it will either open a new incident, # or add a new trigger log entry to an existing incident, depending on the # provided incident_key. # # @example Trigger or update an incident # incident.trigger( # "" # ) # # @example Trigger or update an incident, providing more context # incident.trigger( # "FAILURE for production/HTTP on machine srv01.acme.com", # client: "Sample Monitoring Service", # client_url: "https://monitoring.service.com", # contexts: [ # { # type: "link", # href: "http://acme.pagerduty.com", # text: "View the incident on PagerDuty", # }, # { # type: "image", # src: "https://chart.googleapis.com/chart.png", # } # ], # details: { # ping_time: "1500ms", # load_avg: 0.75, # }, # ) # # @param (see Pagerduty::EventsApiV1#trigger) # @option (see Pagerduty::EventsApiV1#trigger) def trigger(description, options = {}) if options.key?(:incident_key) raise ArgumentError, "incident_key provided" end options = options.merge(description: description) options[:incident_key] = @incident_key unless @incident_key.nil? response = api_call("trigger", options) @incident_key = response["incident_key"] self end # Acknowledge the referenced incident. While an incident is acknowledged, # it won't generate any additional notifications, even if it receives new # trigger events. Send PagerDuty an acknowledge event when you know # someone is presently working on the problem. # # @example Acknowledge the incident # incident.acknowledge # # @example Acknowledge, providing a description and extra details # incident.acknowledge( # "Engineers are investigating the incident", # { # ping_time: "1700ms", # load_avg: 0.71, # } # ) # # @param [String] description Text that will appear in the incident's log # associated with this event. # # @param [Hash] details An arbitrary hash containing any data you'd like # included in the incident log. # # @return [Pagerduty::EventsApiV1::Incident] self # # @raise [PagerdutyException] If PagerDuty responds with a status that is # not "success" # def acknowledge(description = nil, details = nil) modify_incident("acknowledge", description, details) end # Resolve the referenced incident. Once an incident is resolved, it won't # generate any additional notifications. New trigger events with the same # incident_key as a resolved incident won't re-open the incident. Instead, # a new incident will be created. Send PagerDuty a resolve event when the # problem that caused the initial trigger event has been fixed. # # @example Resolve the incident # incident.resolve # # @example Resolve, providing a description and extra details # incident.resolve( # "A fix has been deployed and the service has recovered", # { # ping_time: "130ms", # load_avg: 0.23, # } # ) # # @param [String] description Text that will appear in the incident's log # associated with this event. # # @param [Hash] details An arbitrary hash containing any data you'd like # included in the incident log. # # @return [Pagerduty::EventsApiV1::Incident] self # # @raise [PagerdutyException] If PagerDuty responds with a status that is # not "success" # def resolve(description = nil, details = nil) modify_incident("resolve", description, details) end private def modify_incident(event_type, description, details) options = { incident_key: incident_key } options[:description] = description if description options[:details] = details if details api_call(event_type, options) self end def api_call(event_type, args) args = args.merge( service_key: @integration_key, event_type: event_type, ) response = @transport.send_payload(args) unless response["status"] == "success" raise PagerdutyException.new(self, response, response["message"]) end response end end end end