Created
January 28, 2016 10:52
-
-
Save JoeButler99/9a3e200ef5b950e48682 to your computer and use it in GitHub Desktop.
Puppet run analyser: parsing last_run_report.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
''' | |
@author: joebutler99 | |
@about: | |
This script can analyse a puppet last report to give | |
detailed analysis of where the execution time is spent | |
Puppet enterprise stores this file (by default) in: /var/opt/lib/pe-puppet/state/last_run_report.yaml | |
@examples: | |
$ python puppet_last_run_report_analyser.py -h | |
usage: puppet_last_run_report_analyser.py [-h] -f FILENAME [-l LIMITROWS] | |
Puppet last_run_report.yaml analyser | |
optional arguments: | |
-h, --help show this help message and exit | |
-f FILENAME The location of the report file to analyse | |
-l LIMITROWS, --limit-results LIMITROWS | |
Set row limit for the results table. | |
$ python puppet_last_run_report_analyser.py -f last_run_report.yaml -l 5 | |
Resource Type Time Taken | |
--------------- ------------ | |
Selmodule 11.0498 | |
File 7.40753 | |
Exec 7.34574 | |
Service 5.02793 | |
Package 1.60277 | |
Containment Time Taken | |
------------------------------- ------------ | |
Aproject::Selinux 12.6255 | |
Aproject::Splunk::Agent 5.28557 | |
Pe_mcollective::Server::Plugins 3.57463 | |
Aproject::Tripwire::Client 0.962972 | |
Base 0.877463 | |
Manifest Time Taken | |
----------------------------------------------------------------------------------- ------------ | |
/etc/puppetlabs/puppet/environments/pprod/modules/selinux/manifests/module.pp 12.3087 | |
/etc/puppetlabs/puppet/environments/pprod/modules/splunk/manifests/input/monitor.pp 5.05627 | |
3.92938 | |
/etc/puppetlabs/puppet/environments/pprod/modules/base/manifests/init.pp 1.68767 | |
/etc/puppetlabs/puppet/environments/pprod/modules/aproject/manifests/tripwire.pp 0.962324 | |
Resource Title Time Taken | |
---------------------- ------------ | |
Selmodule[httpd_1] 1.89811 | |
Selmodule[nrpe_sudo_1] 1.84505 | |
Selmodule[logrotate_1] 1.83417 | |
Selmodule[nrpe_sudo_2] 1.82795 | |
Selmodule[sshd] 1.8242 | |
@requirements: | |
These should all be available in pip, and work with python 2.7 | |
PyYAML | |
tabulate | |
''' | |
import yaml | |
import os.path | |
from tabulate import tabulate | |
from argparse import ArgumentParser, ArgumentTypeError | |
import operator | |
class ReportParser: | |
def __init__(self,params): | |
self.params = params | |
self.limit = self.params.limitrows # Max results per table | |
self.results = {"resource_name" : {}, "manifest" : {}, | |
"containment" : {}, "resource_type" : {}} | |
def _add_time_to_group(self,group,name,elapsed_time): | |
if self.results[group].has_key(name): | |
self.results[group][name] += elapsed_time | |
else: | |
self.results[group][name] = elapsed_time | |
def _add_resource_times_to_result(self,report): | |
for resource_name , resource_details in report['resource_statuses'].iteritems(): | |
if not resource_details.has_key('evaluation_time'): | |
#print resource_name | |
continue | |
self._add_time_to_group("resource_name", resource_name,resource_details['evaluation_time'] ) | |
self._add_time_to_group("manifest", resource_details['file'],resource_details['evaluation_time'] ) | |
try: # There are disctint types of containment path | |
c = resource_details['containment_path'][1] | |
except: | |
c = resource_details['containment_path'][0] | |
self._add_time_to_group("containment", c, resource_details['evaluation_time']) | |
self._add_time_to_group("resource_type",resource_details["resource_type"], resource_details['evaluation_time']) | |
def _display_results(self): | |
sorted_resource_names = sorted(self.results["resource_name"].items(), key=operator.itemgetter(1),reverse=True) | |
sorted_manifests = sorted(self.results["manifest"].items(), key=operator.itemgetter(1),reverse=True) | |
sorted_containment = sorted(self.results["containment"].items(), key=operator.itemgetter(1),reverse=True) | |
sorted_resource_type = sorted(self.results["resource_type"].items(), key=operator.itemgetter(1),reverse=True) | |
print tabulate(sorted_resource_type[:self.limit],headers=['Resource Type','Time Taken']) + "\n" | |
print tabulate(sorted_containment[:self.limit],headers=['Containment','Time Taken']) + "\n" | |
print tabulate(sorted_manifests[:self.limit],headers=['Manifest','Time Taken']) + "\n" | |
print tabulate(sorted_resource_names[:self.limit],headers=['Resource Title','Time Taken']) + "\n" | |
def run(self): | |
with open(self.params.filename,'r') as f: | |
report = yaml.load(f) | |
self._add_resource_times_to_result(report) | |
self._display_results() | |
class CLIParser: | |
def check_valid_file(self,filename): | |
if os.path.isfile(os.path.expanduser(filename)): | |
return filename | |
else: | |
raise ArgumentTypeError("\n\n{0} is not a valid file.\n".format(filename)) | |
def get_params(self): | |
parser = ArgumentParser(description='Puppet last_run_report.yaml analyser') | |
parser.add_argument("-f", required=True, action='store', dest="filename", type=self.check_valid_file, help="The location of the report file to analyse") | |
parser.add_argument("-l","--limit-results", required=False, action="store", dest="limitrows", help="Set row limit for the results table.", default=20,type=int) | |
return parser.parse_args() | |
# | |
# Puppet Yaml Objects | |
# | |
def construct_ruby_object(loader, suffix, node): | |
return loader.construct_yaml_map(node) | |
def construct_ruby_sym(loader, node): | |
return loader.construct_yaml_str(node) | |
# | |
# Main Execution | |
# | |
if __name__ == "__main__": | |
yaml.add_multi_constructor(u"!ruby/object:", construct_ruby_object) | |
yaml.add_constructor(u"!ruby/sym", construct_ruby_sym) | |
cli_params = CLIParser().get_params() | |
rp = ReportParser(cli_params) | |
rp.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment