class DatadogChefEvents
helper class for sending events about chef runs
Attributes
Public Class Methods
# File lib/chef/handler/datadog_chef_events.rb, line 16 def initialize @hostname = nil @run_status = nil @failure_notfications = nil @alert_type = '' @event_priority = '' @event_title = '' # TODO: refactor how event_body is constructed in the class methods # handling of the event_body is a bit clunky and depends on the order of # method calls @event_body = '' end
Public Instance Methods
Emit Chef
event to Datadog
@param dog [Dogapi::Client] Dogapi Client to be used
# File lib/chef/handler/datadog_chef_events.rb, line 69 def emit_to_datadog(dog) @event_body = '' build_event_data begin evt = dog.emit_event(Dogapi::Event.new(@event_body, msg_title: @event_title, event_type: 'config_management.run', event_object: @hostname, alert_type: @alert_type, priority: @event_priority, source_type_name: 'chef', tags: @tags ), host: @hostname) # FIXME: nice-to-have: abstract format of return value away a bit # in dogapi directly. See https://github.com/DataDog/dogapi-rb/issues/18 if evt.length < 2 Chef::Log.warn("Unexpected response from Datadog Event API: #{evt}") else # [http_response_code, {"event" => {"url" => "...", ...}}] # 2xx means ok if evt[0].to_i / 100 != 2 Chef::Log.warn("Could not submit event to Datadog (HTTP call failed): #{evt[0]}") else Chef::Log.debug("Successfully submitted Chef event to Datadog for #{@hostname} at #{evt[1]['event']['url']}") end end rescue StandardError => e Chef::Log.warn("Could not determine whether Chef event was successfully submitted to Datadog: #{evt}. Error:\n#{e}") end end
set the failure notification list
@param failure_notifications [Array] set of datadog notification handles @return [DatadogChefTags] instance reference to self enabling method chaining
# File lib/chef/handler/datadog_chef_events.rb, line 52 def with_failure_notifications(failure_notifications) @failure_notifications = failure_notifications self end
set the target hostname (chef node name)
@param hostname [String] hostname to use for the handler report @return [DatadogChefTags] instance reference to self enabling method chaining
# File lib/chef/handler/datadog_chef_events.rb, line 34 def with_hostname(hostname) @hostname = hostname self end
set the chef run status used for the report
@param run_status [Chef::RunStatus] current chef run status @return [DatadogChefTags] instance reference to self enabling method chaining
# File lib/chef/handler/datadog_chef_events.rb, line 43 def with_run_status(run_status) @run_status = run_status self end
Private Instance Methods
Marshal the Event data for submission
# File lib/chef/handler/datadog_chef_events.rb, line 135 def build_event_data # bail early in case of a compiletime failure # OPTIMIZE: Use better inspectors to handle failure scenarios, refactor needed. if compile_error? @alert_type = 'error' @event_title = "Chef failed during compile phase on #{@hostname} " @event_priority = 'normal' @event_body = 'Chef was unable to complete a run, an error during compilation may have occurred.' else run_time = pluralize(@run_status.elapsed_time, 'second') # This is the first line of the Event body, the rest is appended here. @event_body = "Chef updated #{@run_status.updated_resources.length} resources out of #{@run_status.all_resources.length} resources total." # Update resource list, truncated when failed to 5 # update will add to the event_body update_resource_list if @run_status.success? @alert_type = 'success' @event_priority = 'low' @event_title = "Chef completed in #{run_time} on #{@hostname} " else @alert_type = 'error' @event_priority = 'normal' @event_title = "Chef failed in #{run_time} on #{@hostname} " if @failure_notifications handles = @failure_notifications # convert the notification handle array to a string @event_body << "\nAlerting: #{handles.join(' ')}\n" end @event_body << "\n$$$\n#{@run_status.formatted_exception}\n$$$\n" @event_body << "\n$$$\n#{@run_status.backtrace.join("\n")}\n$$$\n" end end end
# File lib/chef/handler/datadog_chef_events.rb, line 103 def pluralize(number, noun) case number when 0..1 "less than 1 #{noun}" else "#{number.round} #{noun}s" end rescue Chef::Log.warn("Cannot make #{number} more legible") "#{number} #{noun}s" end
Compose a list of resources updated during a run.
# File lib/chef/handler/datadog_chef_events.rb, line 116 def update_resource_list # No resources updated? return unless @run_status.updated_resources.length.to_i > 0 if @run_status.failed? # Shorten the list when there is a failure for stacktrace debugging report_resources = @run_status.updated_resources.last(5) else report_resources = @run_status.updated_resources end @event_body = "\n$$$\n" report_resources.each do |r| @event_body << "- #{r} (#{r.defined_at})\n" end @event_body << "\n$$$\n" end