Class: ChefHandlerLrc::LrcResourceReporter

Inherits:
Chef::ResourceReporter
  • Object
show all
Defined in:
lib/lbn_report_chef/lrc_resource_reporter.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ LrcResourceReporter

Returns a new instance of LrcResourceReporter.



5
6
7
8
9
10
11
12
13
14
# 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

Instance Attribute Details

#log_levelObject

Returns the value of attribute log_level.



3
4
5
# File 'lib/lbn_report_chef/lrc_resource_reporter.rb', line 3

def log_level
  @log_level
end

#uploaderObject

Returns the value of attribute uploader.



3
4
5
# File 'lib/lbn_report_chef/lrc_resource_reporter.rb', line 3

def uploader
  @uploader
end

Instance Method Details

#chef_logObject



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# 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) ⇒ Object

currently we support only three log levels:

'debug' means do not filter,
'notice' updated resources and errors
'error' means only errors


198
199
200
# 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) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
# 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_dataObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 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_dataObject



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 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_bypassedObject



68
69
70
# File 'lib/lbn_report_chef/lrc_resource_reporter.rb', line 68

def resource_bypassed(*)
  @why_run = true
end

#resource_completed(new_resource) ⇒ Object



61
62
63
64
65
66
# 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) ⇒ Object



34
35
36
37
# 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) ⇒ Object



55
56
57
58
59
# 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) ⇒ Object



167
168
169
170
171
172
173
174
175
# 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) ⇒ Object



44
45
46
47
# 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) ⇒ Object



39
40
41
42
# 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) ⇒ Object



49
50
51
52
53
# 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_logsObject



138
139
140
141
142
143
144
145
146
147
148
149
150
151
# 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_statusObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# 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_timeObject



130
131
132
133
134
135
136
# 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) ⇒ Object



20
21
22
23
# File 'lib/lbn_report_chef/lrc_resource_reporter.rb', line 20

def run_completed(_node)
  @status = 'success'
  post_reporting_data
end

#run_failed(exception) ⇒ Object



25
26
27
28
29
30
31
32
# 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) ⇒ Object



16
17
18
# File 'lib/lbn_report_chef/lrc_resource_reporter.rb', line 16

def run_started(run_status)
  @run_status = run_status
end