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.
-
*Logs* - are the output that each change produces.
-
*Metrics* - are all of the numerical data involved in the transaction.
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.
-
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.
@api public
Constants
- STATES_FOR_EXCLUSION_FROM_REPORT
- TOTAL
Attributes
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'
A master generated catalog uuid, useful for connecting a single catalog to multiple reports.
The id of the code input to the compiler.
The version of the configuration @todo Uncertain what this is? @return [???] the configuration version
@!attribute [r] corrective_change
@return [Boolean] true if the report contains any events and resources that had corrective changes, including noop corrective changes.
The name of the environment the host is in @return [String] the environment name
The host name for which the report is generated @return [String] the host name
The name of the environment the agent initially started in @return [String] the environment name
The id of the job responsible for this run.
A list of log messages. @return [Array<Puppet::Util::Log>] logged messages
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.
Whether the puppet run was started in noop mode @return [Boolean]
Whether there are changes that we decided not to apply because of noop @return [Boolean]
@return [String] The Puppet version in String form. @see Puppet::version()
@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.
A hash with a map from resource to status @return [Hash{String => Puppet::Resource::Status}] Resource name to status.
@return [Boolean] true if one or more resources attempted to generate
resources and failed
Contains the name and port of the server that was successfully contacted @return [String] a string of the format 'servername:port'
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'
The time when the report data was generated. @return [Time] A time object indicating when the report data was generated
@return [Boolean] true if the transaction completed it's evaluate
An agent generated transaction uuid, useful for connecting catalog and report @return [String] uuid
Public Class Methods
# 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
@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
@api private
# File lib/puppet/transaction/report.rb 156 def <<(msg) 157 @logs << msg 158 self 159 end
@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
@api private
# File lib/puppet/transaction/report.rb 183 def add_resource_status(status) 184 @resource_statuses[status.resource] = status 185 end
@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
# File lib/puppet/transaction/report.rb 151 def as_logging_destination(&block) 152 Puppet::Util::Log.with_destination(self, &block) 153 end
# 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
@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
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
@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
@api private
# File lib/puppet/transaction/report.rb 202 def has_noop_events?(resource) 203 resource.events.any? { |event| event.status == 'noop' } 204 end
@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
@return [String] the host name @api public
# File lib/puppet/transaction/report.rb 360 def name 361 host 362 end
@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
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
# 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
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
# 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
# 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
# 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
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
# 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
# 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