class Report

This class is used to report what happens on a client. There are two types of data in a report; Logs and Metrics.

Use {Puppet::Reports} class to create a new custom report type. This class is indirectly used as a source of data to report in such a registered report.

##Metrics There are three types of metrics in each report, and each type of metric has one or more values.

@api public

Constants

STATES_FOR_EXCLUSION_FROM_REPORT
TOTAL

Attributes

cached_catalog_status[RW]

Whether a cached catalog was used in the run, and if so, the reason that it was used. @return [String] One of the values: 'not_used', 'explicitly_requested', or 'on_failure'

catalog_uuid[RW]

A master generated catalog uuid, useful for connecting a single catalog to multiple reports.

code_id[RW]

The id of the code input to the compiler.

configuration_version[RW]

The version of the configuration @todo Uncertain what this is? @return [???] the configuration version

corrective_change[R]

@!attribute [r] corrective_change

@return [Boolean] true if the report contains any events and resources that had
   corrective changes, including noop corrective changes.
environment[RW]

The name of the environment the host is in @return [String] the environment name

host[RW]

The host name for which the report is generated @return [String] the host name

initial_environment[RW]

The name of the environment the agent initially started in @return [String] the environment name

job_id[RW]

The id of the job responsible for this run.

logs[R]

A list of log messages. @return [Array<Puppet::Util::Log>] logged messages

metrics[R]

A hash of metric name to metric value. @return [Hash<{String => Object}>] A map of metric name to value. @todo Uncertain if all values are numbers - now marked as Object.

noop[R]

Whether the puppet run was started in noop mode @return [Boolean]

noop_pending[RW]

Whether there are changes that we decided not to apply because of noop @return [Boolean]

puppet_version[R]

@return [String] The Puppet version in String form. @see Puppet::version()

report_format[R]

@return [Integer] report format version number. This value is constant for

a given version of Puppet; it is incremented when a new release of Puppet
changes the API for the various objects that make up a report.
resource_statuses[R]

A hash with a map from resource to status @return [Hash{String => Puppet::Resource::Status}] Resource name to status.

resources_failed_to_generate[RW]

@return [Boolean] true if one or more resources attempted to generate

resources and failed
server_used[RW]

Contains the name and port of the server that was successfully contacted @return [String] a string of the format 'servername:port'

status[R]

The status of the client run is an enumeration: 'failed', 'changed' or 'unchanged' @return [String] the status of the run - one of the values 'failed', 'changed', or 'unchanged'

time[R]

The time when the report data was generated. @return [Time] A time object indicating when the report data was generated

transaction_completed[RW]

@return [Boolean] true if the transaction completed it's evaluate

transaction_uuid[RW]

An agent generated transaction uuid, useful for connecting catalog and report @return [String] uuid

Public Class Methods

from_data_hash(data) click to toggle source
    # File lib/puppet/transaction/report.rb
145 def self.from_data_hash(data)
146   obj = self.allocate
147   obj.initialize_from_hash(data)
148   obj
149 end
new(configuration_version=nil, environment=nil, transaction_uuid=nil, job_id=nil, start_time=Time.now) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
226 def initialize(configuration_version=nil, environment=nil, transaction_uuid=nil, job_id=nil, start_time=Time.now)
227   @metrics = {}
228   @logs = []
229   @resource_statuses = {}
230   @external_times ||= {}
231   @host = Puppet[:node_name_value]
232   @time = start_time
233   @report_format = 12
234   @puppet_version = Puppet.version
235   @configuration_version = configuration_version
236   @transaction_uuid = transaction_uuid
237   @code_id = nil
238   @job_id = job_id
239   @catalog_uuid = nil
240   @cached_catalog_status = nil
241   @server_used = nil
242   @environment = environment
243   @status = 'failed' # assume failed until the report is finalized
244   @noop = Puppet[:noop]
245   @noop_pending = false
246   @corrective_change = false
247   @transaction_completed = false
248 end

Public Instance Methods

<<(msg) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
156 def <<(msg)
157   @logs << msg
158   self
159 end
add_metric(name, hash) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
171 def add_metric(name, hash)
172   metric = Puppet::Util::Metric.new(name)
173 
174   hash.each do |metric_name, value|
175     metric.newvalue(metric_name, value)
176   end
177 
178   @metrics[metric.name] = metric
179   metric
180 end
add_resource_status(status) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
183 def add_resource_status(status)
184   @resource_statuses[status.resource] = status
185 end
add_times(name, value, accumulate = true) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
162 def add_times(name, value, accumulate = true)
163   if @external_times[name] && accumulate
164     @external_times[name] += value
165   else
166     @external_times[name] = value
167   end
168 end
as_logging_destination(&block) click to toggle source
    # File lib/puppet/transaction/report.rb
151 def as_logging_destination(&block)
152   Puppet::Util::Log.with_destination(self, &block)
153 end
calculate_resource_statuses() click to toggle source
    # File lib/puppet/transaction/report.rb
320 def calculate_resource_statuses
321   resource_statuses = if Puppet[:exclude_unchanged_resources]
322                         @resource_statuses.reject { |_key, rs| resource_unchanged?(rs) }
323                       else
324                         @resource_statuses
325                       end
326   Hash[resource_statuses.map { |key, rs| [key, rs.nil? ? nil : rs.to_data_hash] }]
327 end
compute_status(resource_metrics, change_metric) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
188 def compute_status(resource_metrics, change_metric)
189   if resources_failed_to_generate ||
190      !transaction_completed ||
191      (resource_metrics["failed"] || 0) > 0 ||
192      (resource_metrics["failed_to_restart"] || 0) > 0
193     'failed'
194   elsif change_metric > 0
195     'changed'
196   else
197     'unchanged'
198   end
199 end
exit_status() click to toggle source

Computes a single number that represents the report's status. The computation is based on the contents of this report's metrics. The resulting number is a bitmask where individual bits represent the presence of different metrics.

  • 0x2 set if there are changes

  • 0x4 set if there are resource failures or resources that failed to restart

@return [Integer] A bitmask where 0x2 is set if there are changes, and 0x4 is set of there are failures. @api public

    # File lib/puppet/transaction/report.rb
434 def exit_status
435   status = 0
436   if @metrics["changes"] && @metrics["changes"][TOTAL] &&
437       @metrics["resources"] && @metrics["resources"]["failed"] &&
438       @metrics["resources"]["failed_to_restart"]
439     status |= 2 if @metrics["changes"][TOTAL] > 0
440     status |= 4 if @metrics["resources"]["failed"] > 0
441     status |= 4 if @metrics["resources"]["failed_to_restart"] > 0
442   else
443     status = -1
444   end
445   status
446 end
finalize_report() click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
212 def finalize_report
213   prune_internal_data
214   calculate_report_corrective_change
215 
216   resource_metrics = add_metric(:resources, calculate_resource_metrics)
217   add_metric(:time, calculate_time_metrics)
218   change_metric = calculate_change_metric
219   add_metric(:changes, {TOTAL => change_metric})
220   add_metric(:events, calculate_event_metrics)
221   @status = compute_status(resource_metrics, change_metric)
222   @noop_pending = @resource_statuses.any? { |name,res| has_noop_events?(res) }
223 end
has_noop_events?(resource) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
202 def has_noop_events?(resource)
203   resource.events.any? { |event| event.status == 'noop' }
204 end
initialize_from_hash(data) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
251 def initialize_from_hash(data)
252   @puppet_version = data['puppet_version']
253   @report_format = data['report_format']
254   @configuration_version = data['configuration_version']
255   @transaction_uuid = data['transaction_uuid']
256   @environment = data['environment']
257   @status = data['status']
258   @transaction_completed = data['transaction_completed']
259   @noop = data['noop']
260   @noop_pending = data['noop_pending']
261   @host = data['host']
262   @time = data['time']
263   @corrective_change = data['corrective_change']
264 
265   if data['server_used']
266     @server_used = data['server_used']
267   elsif data['master_used']
268     @server_used = data['master_used']
269   end
270 
271   if data['catalog_uuid']
272     @catalog_uuid = data['catalog_uuid']
273   end
274 
275   if data['job_id']
276     @job_id = data['job_id']
277   end
278 
279   if data['code_id']
280     @code_id = data['code_id']
281   end
282 
283   if data['cached_catalog_status']
284     @cached_catalog_status = data['cached_catalog_status']
285   end
286 
287   if @time.is_a? String
288     @time = Time.parse(@time)
289   end
290 
291   @metrics = {}
292   data['metrics'].each do |name, hash|
293     # Older versions contain tags that causes Psych to create instances directly
294     @metrics[name] = hash.is_a?(Puppet::Util::Metric) ? hash : Puppet::Util::Metric.from_data_hash(hash)
295   end
296 
297   @logs = data['logs'].map do |record|
298     # Older versions contain tags that causes Psych to create instances directly
299     record.is_a?(Puppet::Util::Log) ? record : Puppet::Util::Log.from_data_hash(record)
300   end
301 
302   @resource_statuses = {}
303   data['resource_statuses'].map do |key, rs|
304     @resource_statuses[key] = if rs == Puppet::Resource::EMPTY_HASH
305       nil
306     else
307       # Older versions contain tags that causes Psych to create instances directly
308       rs.is_a?(Puppet::Resource::Status) ? rs : Puppet::Resource::Status.from_data_hash(rs)
309     end
310   end
311 end
name() click to toggle source

@return [String] the host name @api public

    # File lib/puppet/transaction/report.rb
360 def name
361   host
362 end
prune_internal_data() click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
207 def prune_internal_data
208   resource_statuses.delete_if {|name,res| res.resource_type == 'Whit'}
209 end
raw_summary() click to toggle source

Provides a raw hash summary of this report. @return [Hash<{String => Object}>] A hash with metrics key to value map @api public

    # File lib/puppet/transaction/report.rb
399 def raw_summary
400   report = {
401     "version" => {
402       "config" => configuration_version,
403       "puppet" => Puppet.version
404     },
405     "application" => {
406       "run_mode" => Puppet.run_mode.name.to_s,
407       "initial_environment" => initial_environment,
408       "converged_environment" => environment
409     }
410   }
411 
412   @metrics.each do |name, metric|
413     key = metric.name.to_s
414     report[key] = {}
415     metric.values.each do |metric_name, label, value|
416       report[key][metric_name.to_s] = value
417     end
418     report[key][TOTAL] = 0 unless key == "time" or report[key].include?(TOTAL)
419   end
420   (report["time"] ||= {})["last_run"] = Time.now.tv_sec
421   report
422 end
resource_unchanged?(rs) click to toggle source
    # File lib/puppet/transaction/report.rb
313 def resource_unchanged?(rs)
314   STATES_FOR_EXCLUSION_FROM_REPORT.each do |state|
315     return false if rs.send(state)
316   end
317   true
318 end
summary() click to toggle source

Provide a human readable textual summary of this report. @note This is intended for debugging purposes @return [String] A string with a textual summary of this report. @api public

    # File lib/puppet/transaction/report.rb
369 def summary
370   report = raw_summary
371 
372   ret = String.new
373   report.keys.sort_by(&:to_s).each do |key|
374     ret += "#{Puppet::Util::Metric.labelize(key)}:\n"
375 
376     report[key].keys.sort { |a,b|
377       # sort by label
378       if a == TOTAL
379         1
380       elsif b == TOTAL
381         -1
382       else
383         report[key][a].to_s <=> report[key][b].to_s
384       end
385     }.each do |label|
386       value = report[key][label]
387       next if value == 0
388       value = "%0.2f" % value if value.is_a?(Float)
389       ret += "   %15s %s\n" % [Puppet::Util::Metric.labelize(label) + ":", value]
390     end
391   end
392   ret
393 end
to_data_hash() click to toggle source
    # File lib/puppet/transaction/report.rb
329 def to_data_hash
330   hash = {
331     'host' => @host,
332     'time' => @time.iso8601(9),
333     'configuration_version' => @configuration_version,
334     'transaction_uuid' => @transaction_uuid,
335     'report_format' => @report_format,
336     'puppet_version' => @puppet_version,
337     'status' => @status,
338     'transaction_completed' => @transaction_completed,
339     'noop' => @noop,
340     'noop_pending' => @noop_pending,
341     'environment' => @environment,
342     'logs' => @logs.map { |log| log.to_data_hash },
343     'metrics' => Hash[@metrics.map { |key, metric| [key, metric.to_data_hash] }],
344     'resource_statuses' => calculate_resource_statuses,
345     'corrective_change' => @corrective_change,
346   }
347 
348   # The following is include only when set
349   hash['server_used'] = @server_used unless @server_used.nil?
350   hash['catalog_uuid'] = @catalog_uuid unless @catalog_uuid.nil?
351   hash['code_id'] = @code_id unless @code_id.nil?
352   hash['job_id'] = @job_id unless @job_id.nil?
353   hash['cached_catalog_status'] = @cached_catalog_status unless @cached_catalog_status.nil?
354   hash
355 end

Private Instance Methods

calculate_change_metric() click to toggle source
    # File lib/puppet/transaction/report.rb
457 def calculate_change_metric
458   resource_statuses.map { |name, status| status.change_count || 0 }.inject(0) { |a,b| a+b }
459 end
calculate_event_metrics() click to toggle source
    # File lib/puppet/transaction/report.rb
461 def calculate_event_metrics
462   metrics = Hash.new(0)
463   %w{total failure success}.each { |m| metrics[m] = 0 }
464   resource_statuses.each do |name, status|
465     metrics[TOTAL] += status.events.length
466     status.events.each do |event|
467       metrics[event.status] += 1
468     end
469   end
470 
471   metrics
472 end
calculate_report_corrective_change() click to toggle source

Mark the report as corrective, if there are any resource_status marked corrective.

    # File lib/puppet/transaction/report.rb
451 def calculate_report_corrective_change
452   @corrective_change = resource_statuses.any? do |name, status|
453     status.corrective_change
454   end
455 end
calculate_resource_metrics() click to toggle source
    # File lib/puppet/transaction/report.rb
474 def calculate_resource_metrics
475   metrics = {}
476   metrics[TOTAL] = resource_statuses.length
477 
478   # force every resource key in the report to be present
479   # even if no resources is in this given state
480   Puppet::Resource::Status::STATES.each do |state|
481     metrics[state.to_s] = 0
482   end
483 
484   resource_statuses.each do |name, status|
485     Puppet::Resource::Status::STATES.each do |state|
486       metrics[state.to_s] += 1 if status.send(state)
487     end
488   end
489 
490   metrics
491 end
calculate_time_metrics() click to toggle source
    # File lib/puppet/transaction/report.rb
493 def calculate_time_metrics
494   metrics = Hash.new(0)
495   resource_statuses.each do |name, status|
496     metrics[status.resource_type.downcase] += status.evaluation_time if status.evaluation_time
497   end
498 
499   @external_times.each do |name, value|
500     metrics[name.to_s.downcase] = value
501   end
502 
503   metrics
504 end