class ChefHandlerLrc::LrcResourceReporter

Attributes

log_level[RW]
uploader[RW]

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 5
def initialize(*args)
  @total_up_to_date     = 0
  @total_skipped        = 0
  @total_updated        = 0
  @total_failed         = 0
  @total_restarted      = 0
  @total_failed_restart = 0
  @all_resources        = []
  super
end

Public Instance Methods

chef_log() click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 177
def chef_log
  message = 'chef-client run'
  if @status == 'success' && exception.nil?
    level = 'notice'
  else
    message += " (#{exception.class} #{exception.message})"
    level = 'err'
  end

  { 'log' => {
    'sources'  => { 'source' => "chef-client #{Chef::VERSION}" },
    'messages' => { 'message' => message },
    'level'    => level,
  } }
end
filter_logs(logs) click to toggle source

currently we support only three log levels:

'debug' means do not filter,
'notice' updated resources and errors
'error' means only errors
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 198
def filter_logs(logs)
  logs.select { |log| ['err','notice'].include? log['log']['level'] }
end
format_message(message, resource) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 153
def format_message(message, resource)
  case resource.resource_name.to_s
  when 'template', 'cookbook_file'
    unless resource.diff.nil?
      message += ' with diff ' + resource.diff.gsub('\\n', "\n")
    end
  when 'package'
    message += " package in #{resource.version}" unless resource.version.nil?
  else
    message = resource.source_line.to_s + ' with action ' + resource.action.to_s
  end
  message
end
post_reporting_data() click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 72
def post_reporting_data
  if reporting_enabled?
    run_data = prepare_run_data
    Chef::Log.info('Sending resource update report to report API ...')
    Chef::Log.debug run_data.inspect
    begin
      Chef::Log.debug('Sending data to report API ...')
      if uploader
        uploader.lrc_request('/report', 'report' => run_data)
      else
        Chef::Log.error 'No uploader registered for LRC reporting, skipping report upload'
      end
    rescue => e
      Chef::Log.error "Sending failed with #{e.class} #{e.message}"
      Chef::Log.error e.backtrace.join("\n")
    end
  else
    Chef::Log.debug('Reporting disabled, skipping report upload')
  end
end
prepare_run_data() click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 93
def prepare_run_data
  run_data                = {}
  run_data['host']        = node_name.downcase
  run_data['reported_at'] = end_time.to_s
  run_data['status']      = resources_per_status

  run_data['metrics'] = {
    'resources' => { 'total' => @total_res_count },
    'time'      => resources_per_time,
  }

  run_data['logs'] = filter_logs(resources_logs + [chef_log])
  run_data
end
resource_bypassed(*) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 68
def resource_bypassed(*)
  @why_run = true
end
resource_completed(new_resource) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 61
def resource_completed(new_resource)
  return unless @pending_update && !nested_resource?(new_resource)
  @pending_update.finish
  @updated_resources << @pending_update
  @pending_update = nil
end
resource_current_state_loaded(new_resource, action, current_resource) click to toggle source
Calls superclass method
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 34
def resource_current_state_loaded(new_resource, action, current_resource)
  super
  @all_resources.push @pending_update unless @pending_update.nil?
end
resource_failed(new_resource, action, exception) click to toggle source
Calls superclass method
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 55
def resource_failed(new_resource, action, exception)
  @total_failed         += 1
  @total_failed_restart += 1 if action.to_s == 'restart'
  super
end
resource_level(resource) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 167
def resource_level(resource)
  if !resource.exception.nil?
    'err'
  elsif resource.new_resource.updated
    'notice'
  else
    'debug'
  end
end
resource_skipped(resource, action, conditional) click to toggle source
Calls superclass method
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 44
def resource_skipped(resource, action, conditional)
  @total_skipped += 1
  super
end
resource_up_to_date(new_resource, action) click to toggle source
Calls superclass method
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 39
def resource_up_to_date(new_resource, action)
  @total_up_to_date += 1
  super
end
resource_updated(new_resource, action) click to toggle source
Calls superclass method
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 49
def resource_updated(new_resource, action)
  @total_updated   += 1
  @total_restarted += 1 if action.to_s == 'restart'
  super
end
resources_logs() click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 138
def resources_logs
  @all_resources.map do |resource|
    action  = resource.new_resource.action
    message = action.is_a?(Array) ? action.first.to_s : action.to_s
    message = format_message(message, resource.new_resource)
    message += " (#{resource.exception.class} #{resource.exception.message})" unless resource.exception.nil?
    level   =  resource_level(resource)
    { 'log' => {
      'sources'  => { 'source' => resource.new_resource.to_s },
      'messages' => { 'message' => message },
      'level'    => level,
    } }
  end
end
resources_per_status() click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 108
def resources_per_status
  if Chef::Config.why_run
    {
      'applied'         => 0,
      'restarted'       => 0,
      'failed'          => 0,
      'failed_restarts' => 0,
      'skipped'         => @total_skipped,
      'pending'         => @total_updated + @total_restarted + @total_failed + @total_failed_restart,
    }
  else
    {
      'applied'         => @total_updated,
      'restarted'       => @total_restarted,
      'failed'          => @total_failed,
      'failed_restarts' => @total_failed_restart,
      'skipped'         => @total_skipped,
      'pending'         => 0,
    }
  end
end
resources_per_time() click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 130
def resources_per_time
  @run_status.all_resources.each_with_object({}) do |resource, memo|
    name = resource.resource_name.to_s
    time = resource.elapsed_time || 0
    memo[name] = memo[name] ? memo[name] + time : time
  end
end
run_completed(_node) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 20
def run_completed(_node)
  @status = 'success'
  post_reporting_data
end
run_failed(exception) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 25
def run_failed(exception)
  @exception = exception
  @status    = 'failure'
  # If we failed before we received the run_started callback, there's not much we can do
  # in terms of reporting
  return unless @run_status
  post_reporting_data
end
run_started(run_status) click to toggle source
# File lib/lbn_report_chef/lrc_resource_reporter.rb, line 16
def run_started(run_status)
  @run_status = run_status
end