Class: Puppet::Transaction::Report

Inherits:
Object
  • Object
show all
Extended by:
Indirector
Includes:
Util::PsychSupport
Defined in:
lib/puppet/transaction/report.rb

Overview

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

  • Logs - are the output that each change produces.

  • Metrics - are all of the numerical data involved in the transaction.

Use 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.

  • Time: Keeps track of how long things took.

    • Total: Total time for the configuration run

    • File:

    • Exec:

    • User:

    • Group:

    • Config Retrieval: How long the configuration took to retrieve

    • Service:

    • Package:

  • Resources: Keeps track of the following stats:

    • Total: The total number of resources being managed

    • Skipped: How many resources were skipped, because of either tagging or scheduling restrictions

    • Scheduled: How many resources met any scheduling restrictions

    • Out of Sync: How many resources were out of sync

    • Applied: How many resources were attempted to be fixed

    • Failed: How many resources were not successfully fixed

    • Restarted: How many resources were restarted because their dependencies changed

    • Failed Restarts: How many resources could not be restarted

  • Changes: The total number of changes in the transaction.

Defined Under Namespace

Classes: Json, Msgpack, Processor, Rest, Yaml

Constant Summary collapse

STATES_FOR_EXCLUSION_FROM_REPORT =
[:failed, :failed_to_restart, :out_of_sync, :skipped].freeze
TOTAL =
"total"

Constants included from Indirector

Indirector::BadNameRegexp

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Indirector

configure_routes, indirects

Methods included from Util::PsychSupport

#encode_with, #init_with

Constructor Details

#initialize(configuration_version = nil, environment = nil, transaction_uuid = nil, job_id = nil, start_time = Time.now) ⇒ Report

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Report.



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/puppet/transaction/report.rb', line 227

def initialize(configuration_version = nil, environment = nil, transaction_uuid = nil, job_id = nil, start_time = Time.now)
  @metrics = {}
  @logs = []
  @resource_statuses = {}
  @external_times ||= {}
  @host = Puppet[:node_name_value]
  @time = start_time
  @report_format = 12
  @puppet_version = Puppet.version
  @configuration_version = configuration_version
  @transaction_uuid = transaction_uuid
  @code_id = nil
  @job_id = job_id
  @catalog_uuid = nil
  @cached_catalog_status = nil
  @server_used = nil
  @environment = environment
  @status = 'failed' # assume failed until the report is finalized
  @noop = Puppet[:noop]
  @noop_pending = false
  @corrective_change = false
  @transaction_completed = false
end

Instance Attribute Details

#cached_catalog_statusString

Whether a cached catalog was used in the run, and if so, the reason that it was used. or ‘on_failure’

Returns:

  • (String)

    One of the values: ‘not_used’, ‘explicitly_requested’,



67
68
69
# File 'lib/puppet/transaction/report.rb', line 67

def cached_catalog_status
  @cached_catalog_status
end

#catalog_uuidObject

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



62
63
64
# File 'lib/puppet/transaction/report.rb', line 62

def catalog_uuid
  @catalog_uuid
end

#code_idObject

The id of the code input to the compiler.



56
57
58
# File 'lib/puppet/transaction/report.rb', line 56

def code_id
  @code_id
end

#configuration_version???

TODO:

Uncertain what this is?

The version of the configuration

Returns:

  • (???)

    the configuration version



49
50
51
# File 'lib/puppet/transaction/report.rb', line 49

def configuration_version
  @configuration_version
end

#corrective_changeObject (readonly)



133
134
135
# File 'lib/puppet/transaction/report.rb', line 133

def corrective_change
  @corrective_change
end

#environmentString

The name of the environment the host is in

Returns:

  • (String)

    the environment name



79
80
81
# File 'lib/puppet/transaction/report.rb', line 79

def environment
  @environment
end

#hostString

The host name for which the report is generated

Returns:

  • (String)

    the host name



75
76
77
# File 'lib/puppet/transaction/report.rb', line 75

def host
  @host
end

#initial_environmentString

The name of the environment the agent initially started in

Returns:

  • (String)

    the environment name



83
84
85
# File 'lib/puppet/transaction/report.rb', line 83

def initial_environment
  @initial_environment
end

#job_idObject

The id of the job responsible for this run.



59
60
61
# File 'lib/puppet/transaction/report.rb', line 59

def job_id
  @job_id
end

#logsArray<Puppet::Util::Log> (readonly)

A list of log messages.

Returns:



96
97
98
# File 'lib/puppet/transaction/report.rb', line 96

def logs
  @logs
end

#metricsHash<{String => Object}> (readonly)

TODO:

Uncertain if all values are numbers - now marked as Object.

A hash of metric name to metric value.

Returns:

  • (Hash<{String => Object}>)

    A map of metric name to value.



102
103
104
# File 'lib/puppet/transaction/report.rb', line 102

def metrics
  @metrics
end

#noopBoolean (readonly)

Whether the puppet run was started in noop mode

Returns:

  • (Boolean)


128
129
130
# File 'lib/puppet/transaction/report.rb', line 128

def noop
  @noop
end

#noop_pendingBoolean

Whether there are changes that we decided not to apply because of noop

Returns:

  • (Boolean)


88
89
90
# File 'lib/puppet/transaction/report.rb', line 88

def noop_pending
  @noop_pending
end

#puppet_versionString (readonly)

Returns The Puppet version in String form.

Returns:

  • (String)

    The Puppet version in String form.

See Also:

  • version()


117
118
119
# File 'lib/puppet/transaction/report.rb', line 117

def puppet_version
  @puppet_version
end

#report_formatInteger (readonly)

Returns 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.

Returns:

  • (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.



123
124
125
# File 'lib/puppet/transaction/report.rb', line 123

def report_format
  @report_format
end

#resource_statusesHash{String => Puppet::Resource::Status} (readonly)

A hash with a map from resource to status

Returns:



92
93
94
# File 'lib/puppet/transaction/report.rb', line 92

def resource_statuses
  @resource_statuses
end

#resources_failed_to_generateBoolean

Returns true if one or more resources attempted to generate resources and failed.

Returns:

  • (Boolean)

    true if one or more resources attempted to generate resources and failed



138
139
140
# File 'lib/puppet/transaction/report.rb', line 138

def resources_failed_to_generate
  @resources_failed_to_generate
end

#server_usedString

Contains the name and port of the server that was successfully contacted

Returns:

  • (String)

    a string of the format ‘servername:port’



71
72
73
# File 'lib/puppet/transaction/report.rb', line 71

def server_used
  @server_used
end

#statusString (readonly)

The status of the client run is an enumeration: ‘failed’, ‘changed’ or ‘unchanged’

Returns:

  • (String)

    the status of the run - one of the values ‘failed’, ‘changed’, or ‘unchanged’



112
113
114
# File 'lib/puppet/transaction/report.rb', line 112

def status
  @status
end

#timeTime (readonly)

The time when the report data was generated.

Returns:

  • (Time)

    A time object indicating when the report data was generated



107
108
109
# File 'lib/puppet/transaction/report.rb', line 107

def time
  @time
end

#transaction_completedBoolean

Returns true if the transaction completed it’s evaluate.

Returns:

  • (Boolean)

    true if the transaction completed it’s evaluate



142
143
144
# File 'lib/puppet/transaction/report.rb', line 142

def transaction_completed
  @transaction_completed
end

#transaction_uuidString

An agent generated transaction uuid, useful for connecting catalog and report

Returns:

  • (String)

    uuid



53
54
55
# File 'lib/puppet/transaction/report.rb', line 53

def transaction_uuid
  @transaction_uuid
end

Class Method Details

.from_data_hash(data) ⇒ Object



146
147
148
149
150
# File 'lib/puppet/transaction/report.rb', line 146

def self.from_data_hash(data)
  obj = allocate
  obj.initialize_from_hash(data)
  obj
end

Instance Method Details

#<<(msg) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



157
158
159
160
# File 'lib/puppet/transaction/report.rb', line 157

def <<(msg)
  @logs << msg
  self
end

#add_metric(name, hash) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



172
173
174
175
176
177
178
179
180
181
# File 'lib/puppet/transaction/report.rb', line 172

def add_metric(name, hash)
  metric = Puppet::Util::Metric.new(name)

  hash.each do |metric_name, value|
    metric.newvalue(metric_name, value)
  end

  @metrics[metric.name] = metric
  metric
end

#add_resource_status(status) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



184
185
186
# File 'lib/puppet/transaction/report.rb', line 184

def add_resource_status(status)
  @resource_statuses[status.resource] = status
end

#add_times(name, value, accumulate = true) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



163
164
165
166
167
168
169
# File 'lib/puppet/transaction/report.rb', line 163

def add_times(name, value, accumulate = true)
  if @external_times[name] && accumulate
    @external_times[name] += value
  else
    @external_times[name] = value
  end
end

#as_logging_destination(&block) ⇒ Object



152
153
154
# File 'lib/puppet/transaction/report.rb', line 152

def as_logging_destination(&block)
  Puppet::Util::Log.with_destination(self, &block)
end

#calculate_resource_statusesObject



325
326
327
328
329
330
331
332
# File 'lib/puppet/transaction/report.rb', line 325

def calculate_resource_statuses
  resource_statuses = if Puppet[:exclude_unchanged_resources]
                        @resource_statuses.reject { |_key, rs| resource_unchanged?(rs) }
                      else
                        @resource_statuses
                      end
  resource_statuses.transform_values { |rs| rs.nil? ? nil : rs.to_data_hash }
end

#compute_status(resource_metrics, change_metric) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/puppet/transaction/report.rb', line 189

def compute_status(resource_metrics, change_metric)
  if resources_failed_to_generate ||
     !transaction_completed ||
     (resource_metrics["failed"] || 0) > 0 ||
     (resource_metrics["failed_to_restart"] || 0) > 0
    'failed'
  elsif change_metric > 0
    'changed'
  else
    'unchanged'
  end
end

#exit_statusInteger

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

Returns:

  • (Integer)

    A bitmask where 0x2 is set if there are changes, and 0x4 is set of there are failures.



440
441
442
443
444
445
446
447
448
449
450
451
452
# File 'lib/puppet/transaction/report.rb', line 440

def exit_status
  status = 0
  if @metrics["changes"] && @metrics["changes"][TOTAL] &&
     @metrics["resources"] && @metrics["resources"]["failed"] &&
     @metrics["resources"]["failed_to_restart"]
    status |= 2 if @metrics["changes"][TOTAL] > 0
    status |= 4 if @metrics["resources"]["failed"] > 0
    status |= 4 if @metrics["resources"]["failed_to_restart"] > 0
  else
    status = -1
  end
  status
end

#finalize_reportObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/puppet/transaction/report.rb', line 213

def finalize_report
  prune_internal_data
  calculate_report_corrective_change

  resource_metrics = add_metric(:resources, calculate_resource_metrics)
  add_metric(:time, calculate_time_metrics)
  change_metric = calculate_change_metric
  add_metric(:changes, { TOTAL => change_metric })
  add_metric(:events, calculate_event_metrics)
  @status = compute_status(resource_metrics, change_metric)
  @noop_pending = @resource_statuses.any? { |_name, res| has_noop_events?(res) }
end

#has_noop_events?(resource) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


203
204
205
# File 'lib/puppet/transaction/report.rb', line 203

def has_noop_events?(resource)
  resource.events.any? { |event| event.status == 'noop' }
end

#initialize_from_hash(data) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/puppet/transaction/report.rb', line 252

def initialize_from_hash(data)
  @puppet_version = data['puppet_version']
  @report_format = data['report_format']
  @configuration_version = data['configuration_version']
  @transaction_uuid = data['transaction_uuid']
  @environment = data['environment']
  @status = data['status']
  @transaction_completed = data['transaction_completed']
  @noop = data['noop']
  @noop_pending = data['noop_pending']
  @host = data['host']
  @time = data['time']
  @corrective_change = data['corrective_change']

  if data['server_used']
    @server_used = data['server_used']
  elsif data['master_used']
    @server_used = data['master_used']
  end

  if data['catalog_uuid']
    @catalog_uuid = data['catalog_uuid']
  end

  if data['job_id']
    @job_id = data['job_id']
  end

  if data['code_id']
    @code_id = data['code_id']
  end

  if data['cached_catalog_status']
    @cached_catalog_status = data['cached_catalog_status']
  end

  if @time.is_a? String
    @time = Time.parse(@time)
  end

  @metrics = {}
  data['metrics'].each do |name, hash|
    # Older versions contain tags that causes Psych to create instances directly
    @metrics[name] = hash.is_a?(Puppet::Util::Metric) ? hash : Puppet::Util::Metric.from_data_hash(hash)
  end

  @logs = data['logs'].map do |record|
    # Older versions contain tags that causes Psych to create instances directly
    record.is_a?(Puppet::Util::Log) ? record : Puppet::Util::Log.from_data_hash(record)
  end

  @resource_statuses = {}
  data['resource_statuses'].map do |key, rs|
    @resource_statuses[key] =
      if rs == Puppet::Resource::EMPTY_HASH
        nil
      elsif rs.is_a?(Puppet::Resource::Status)
        # Older versions contain tags that causes Psych to create instances
        # directly
        rs
      else
        Puppet::Resource::Status.from_data_hash(rs)
      end
  end
end

#nameString

Returns the host name.

Returns:

  • (String)

    the host name



365
366
367
# File 'lib/puppet/transaction/report.rb', line 365

def name
  host
end

#prune_internal_dataObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



208
209
210
# File 'lib/puppet/transaction/report.rb', line 208

def prune_internal_data
  resource_statuses.delete_if { |_name, res| res.resource_type == 'Whit' }
end

#raw_summaryHash<{String => Object}>

Provides a raw hash summary of this report.

Returns:

  • (Hash<{String => Object}>)

    A hash with metrics key to value map



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'lib/puppet/transaction/report.rb', line 405

def raw_summary
  report = {
    "version" => {
      "config" => configuration_version,
      "puppet" => Puppet.version
    },
    "application" => {
      "run_mode" => Puppet.run_mode.name.to_s,
      "initial_environment" => initial_environment,
      "converged_environment" => environment
    }
  }

  @metrics.each do |_name, metric|
    key = metric.name.to_s
    report[key] = {}
    metric.values.each do |metric_name, _label, value|
      report[key][metric_name.to_s] = value
    end
    report[key][TOTAL] = 0 unless key == "time" or report[key].include?(TOTAL)
  end
  (report["time"] ||= {})["last_run"] = Time.now.tv_sec
  report
end

#resource_unchanged?(rs) ⇒ Boolean

Returns:

  • (Boolean)


318
319
320
321
322
323
# File 'lib/puppet/transaction/report.rb', line 318

def resource_unchanged?(rs)
  STATES_FOR_EXCLUSION_FROM_REPORT.each do |state|
    return false if rs.send(state)
  end
  true
end

#summaryString

Note:

This is intended for debugging purposes

Provide a human readable textual summary of this report.

Returns:

  • (String)

    A string with a textual summary of this report.



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/puppet/transaction/report.rb', line 374

def summary
  report = raw_summary

  ret = ''.dup
  report.keys.sort_by(&:to_s).each do |key|
    ret += "#{Puppet::Util::Metric.labelize(key)}:\n"

    report[key].keys.sort { |a, b|
      # sort by label
      if a == TOTAL
        1
      elsif b == TOTAL
        -1
      else
        report[key][a].to_s <=> report[key][b].to_s
      end
    }.each do |label|
      value = report[key][label]
      next if value == 0

      value = "%0.2f" % value if value.is_a?(Float)
      ret += "   %15s %s\n" % [Puppet::Util::Metric.labelize(label) + ":", value]
    end
  end
  ret
end

#to_data_hashObject



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/puppet/transaction/report.rb', line 334

def to_data_hash
  hash = {
    'host' => @host,
    'time' => @time.iso8601(9),
    'configuration_version' => @configuration_version,
    'transaction_uuid' => @transaction_uuid,
    'report_format' => @report_format,
    'puppet_version' => @puppet_version,
    'status' => @status,
    'transaction_completed' => @transaction_completed,
    'noop' => @noop,
    'noop_pending' => @noop_pending,
    'environment' => @environment,
    'logs' => @logs.map(&:to_data_hash),
    'metrics' => @metrics.transform_values(&:to_data_hash),
    'resource_statuses' => calculate_resource_statuses,
    'corrective_change' => @corrective_change,
  }

  # The following is include only when set
  hash['server_used'] = @server_used unless @server_used.nil?
  hash['catalog_uuid'] = @catalog_uuid unless @catalog_uuid.nil?
  hash['code_id'] = @code_id unless @code_id.nil?
  hash['job_id'] = @job_id unless @job_id.nil?
  hash['cached_catalog_status'] = @cached_catalog_status unless @cached_catalog_status.nil?
  hash
end