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

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
143 def self.from_data_hash(data)
144   obj = self.allocate
145   obj.initialize_from_hash(data)
146   obj
147 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
224 def initialize(configuration_version=nil, environment=nil, transaction_uuid=nil, job_id=nil, start_time=Time.now)
225   @metrics = {}
226   @logs = []
227   @resource_statuses = {}
228   @external_times ||= {}
229   @host = Puppet[:node_name_value]
230   @time = start_time
231   @report_format = 12
232   @puppet_version = Puppet.version
233   @configuration_version = configuration_version
234   @transaction_uuid = transaction_uuid
235   @code_id = nil
236   @job_id = job_id
237   @catalog_uuid = nil
238   @cached_catalog_status = nil
239   @server_used = nil
240   @environment = environment
241   @status = 'failed' # assume failed until the report is finalized
242   @noop = Puppet[:noop]
243   @noop_pending = false
244   @corrective_change = false
245   @transaction_completed = false
246 end

Public Instance Methods

<<(msg) click to toggle source

@api private

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

@api private

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

@api private

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

@api private

    # File lib/puppet/transaction/report.rb
160 def add_times(name, value, accumulate = true)
161   if @external_times[name] && accumulate
162     @external_times[name] += value
163   else
164     @external_times[name] = value
165   end
166 end
as_logging_destination(&block) click to toggle source
    # File lib/puppet/transaction/report.rb
149 def as_logging_destination(&block)
150   Puppet::Util::Log.with_destination(self, &block)
151 end
compute_status(resource_metrics, change_metric) click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
186 def compute_status(resource_metrics, change_metric)
187   if resources_failed_to_generate ||
188      !transaction_completed ||
189      (resource_metrics["failed"] || 0) > 0 ||
190      (resource_metrics["failed_to_restart"] || 0) > 0
191     'failed'
192   elsif change_metric > 0
193     'changed'
194   else
195     'unchanged'
196   end
197 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
416 def exit_status
417   status = 0
418   if @metrics["changes"] && @metrics["changes"][TOTAL] &&
419       @metrics["resources"] && @metrics["resources"]["failed"] &&
420       @metrics["resources"]["failed_to_restart"]
421     status |= 2 if @metrics["changes"][TOTAL] > 0
422     status |= 4 if @metrics["resources"]["failed"] > 0
423     status |= 4 if @metrics["resources"]["failed_to_restart"] > 0
424   else
425     status = -1
426   end
427   status
428 end
finalize_report() click to toggle source

@api private

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

@api private

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

@api private

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

@return [String] the host name @api public

    # File lib/puppet/transaction/report.rb
342 def name
343   host
344 end
prune_internal_data() click to toggle source

@api private

    # File lib/puppet/transaction/report.rb
205 def prune_internal_data
206   resource_statuses.delete_if {|name,res| res.resource_type == 'Whit'}
207 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
381 def raw_summary
382   report = {
383     "version" => {
384       "config" => configuration_version,
385       "puppet" => Puppet.version
386     },
387     "application" => {
388       "run_mode" => Puppet.run_mode.name.to_s,
389       "initial_environment" => initial_environment,
390       "converged_environment" => environment
391     }
392   }
393 
394   @metrics.each do |name, metric|
395     key = metric.name.to_s
396     report[key] = {}
397     metric.values.each do |metric_name, label, value|
398       report[key][metric_name.to_s] = value
399     end
400     report[key][TOTAL] = 0 unless key == "time" or report[key].include?(TOTAL)
401   end
402   (report["time"] ||= {})["last_run"] = Time.now.tv_sec
403   report
404 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
351 def summary
352   report = raw_summary
353 
354   ret = ""
355   report.keys.sort_by(&:to_s).each do |key|
356     ret += "#{Puppet::Util::Metric.labelize(key)}:\n"
357 
358     report[key].keys.sort { |a,b|
359       # sort by label
360       if a == TOTAL
361         1
362       elsif b == TOTAL
363         -1
364       else
365         report[key][a].to_s <=> report[key][b].to_s
366       end
367     }.each do |label|
368       value = report[key][label]
369       next if value == 0
370       value = "%0.2f" % value if value.is_a?(Float)
371       ret += "   %15s %s\n" % [Puppet::Util::Metric.labelize(label) + ":", value]
372     end
373   end
374   ret
375 end
to_data_hash() click to toggle source
    # File lib/puppet/transaction/report.rb
311 def to_data_hash
312   hash = {
313     'host' => @host,
314     'time' => @time.iso8601(9),
315     'configuration_version' => @configuration_version,
316     'transaction_uuid' => @transaction_uuid,
317     'report_format' => @report_format,
318     'puppet_version' => @puppet_version,
319     'status' => @status,
320     'transaction_completed' => @transaction_completed,
321     'noop' => @noop,
322     'noop_pending' => @noop_pending,
323     'environment' => @environment,
324     'logs' => @logs.map { |log| log.to_data_hash },
325     'metrics' => Hash[@metrics.map { |key, metric| [key, metric.to_data_hash] }],
326     'resource_statuses' => Hash[@resource_statuses.map { |key, rs| [key, rs.nil? ? nil : rs.to_data_hash] }],
327     'corrective_change' => @corrective_change,
328   }
329 
330   # The following is include only when set
331   hash['server_used'] = @server_used unless @server_used.nil?
332   hash['catalog_uuid'] = @catalog_uuid unless @catalog_uuid.nil?
333   hash['code_id'] = @code_id unless @code_id.nil?
334   hash['job_id'] = @job_id unless @job_id.nil?
335   hash['cached_catalog_status'] = @cached_catalog_status unless @cached_catalog_status.nil?
336   hash
337 end

Private Instance Methods

calculate_change_metric() click to toggle source
    # File lib/puppet/transaction/report.rb
439 def calculate_change_metric
440   resource_statuses.map { |name, status| status.change_count || 0 }.inject(0) { |a,b| a+b }
441 end
calculate_event_metrics() click to toggle source
    # File lib/puppet/transaction/report.rb
443 def calculate_event_metrics
444   metrics = Hash.new(0)
445   %w{total failure success}.each { |m| metrics[m] = 0 }
446   resource_statuses.each do |name, status|
447     metrics[TOTAL] += status.events.length
448     status.events.each do |event|
449       metrics[event.status] += 1
450     end
451   end
452 
453   metrics
454 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
433 def calculate_report_corrective_change
434   @corrective_change = resource_statuses.any? do |name, status|
435     status.corrective_change
436   end
437 end
calculate_resource_metrics() click to toggle source
    # File lib/puppet/transaction/report.rb
456 def calculate_resource_metrics
457   metrics = {}
458   metrics[TOTAL] = resource_statuses.length
459 
460   # force every resource key in the report to be present
461   # even if no resources is in this given state
462   Puppet::Resource::Status::STATES.each do |state|
463     metrics[state.to_s] = 0
464   end
465 
466   resource_statuses.each do |name, status|
467     Puppet::Resource::Status::STATES.each do |state|
468       metrics[state.to_s] += 1 if status.send(state)
469     end
470   end
471 
472   metrics
473 end
calculate_time_metrics() click to toggle source
    # File lib/puppet/transaction/report.rb
475 def calculate_time_metrics
476   metrics = Hash.new(0)
477   resource_statuses.each do |name, status|
478     metrics[status.resource_type.downcase] += status.evaluation_time if status.evaluation_time
479   end
480 
481   @external_times.each do |name, value|
482     metrics[name.to_s.downcase] = value
483   end
484 
485   metrics
486 end