datadog_tasks_timing.py 4.19 KB
Newer Older
1 2 3 4 5
import os
import datetime
import time
import logging
import datadog
6
import sys
7

8
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
9 10
logging.getLogger("requests").setLevel(logging.WARNING)
logging.getLogger("dd").setLevel(logging.WARNING)
11 12 13 14 15 16 17 18 19 20 21 22
logger = logging.getLogger(__name__)

"""
Originally written by 'Jharrod LaFon'
#https://github.com/jlafon/ansible-profile/blob/master/callback_plugins/profile_tasks.py

"""


class CallbackModule(object):

    """
Edward Zarecor committed
23 24
    Ansible plugin get the time of each task and total time
    to run the complete playbook
25 26 27 28
    """
    def __init__(self):
        self.stats = {}
        self.current_task = None
Edward Zarecor committed
29
        self.playbook_name = None
30 31 32
        self.datadog_api_key = os.getenv('DATADOG_API_KEY')
        self.datadog_api_initialized = False

Edward Zarecor committed
33
        if self.datadog_api_key:
34
            datadog.initialize(api_key=self.datadog_api_key,
Edward Zarecor committed
35
                               app_key=None)
36
            self.datadog_api_initialized = True
Edward Zarecor committed
37

Edward Zarecor committed
38 39 40
    def clean_tag_value(self, value):
        return value.replace(" | ", ".").replace(" ", "-").lower()

Edward Zarecor committed
41
    def playbook_on_play_start(self, pattern):
Edward Zarecor committed
42 43 44 45
            self.playbook_name, _ = os.path.splitext(
                os.path.basename(self.play.playbook.filename)
            )

46 47
    def playbook_on_task_start(self, name, is_conditional):
        """
Edward Zarecor committed
48
        Logs the start of each task
49 50 51 52 53 54 55 56 57 58 59 60
        """

        if self.current_task is not None:
            # Record the running time of the last executed task
            self.stats[self.current_task] = (time.time(), time.time() - self.stats[self.current_task])

        # Record the start time of the current task
        self.current_task = name
        self.stats[self.current_task] = time.time()

    def playbook_on_stats(self, stats):
        """
Edward Zarecor committed
61 62
        Prints the timing of each task and total time to
        run the complete playbook
63
        """
Edward Zarecor committed
64 65
        # Record the timing of the very last task, we use it here, because we
        # don't have stop task function by default
66 67 68 69
        if self.current_task is not None:
            self.stats[self.current_task] = (time.time(), time.time() - self.stats[self.current_task])

        # Sort the tasks by their running time
Edward Zarecor committed
70 71
        results = sorted(self.stats.items(),
                         key=lambda value: value[1][1], reverse=True)
72 73 74

        # Total time to run the complete playbook
        total_seconds = sum([x[1][1] for x in self.stats.items()])
75
          
76 77
        # send the metric to datadog
        if self.datadog_api_initialized:
78
            datadog_tasks_metrics = []
79
            for name, points in results:
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
                datadog_tasks_metrics.append({'metric': 'edx.ansible.task_duration',
                                              'date_happened': points[0],
                                              'points': points[1],
                                              'tags': ['task:{0}'.format(self.clean_tag_value(name)),
                                                       'playbook:{0}'.format(self.clean_tag_value(self.playbook_name))
                                                       ]
                                              }
                                             )
            try:
                datadog.api.Metric.send(datadog_tasks_metrics)
                datadog.api.Metric.send(metric="edx.ansible.playbook_duration",
                                        date_happened=time.time(),
                                        points=total_seconds,
                                        tags=["playbook:{0}".format(self.clean_tag_value(self.playbook_name))]
                                        )
            except Exception as ex:
                logger.error(ex.message)
97 98

        # Log the time of each task
99
        for name, elapsed in results[:10]:
100 101 102 103 104 105 106
            logger.info(
                "{0:-<80}{1:->8}".format(
                    '{0} '.format(name),
                    ' {0:.02f}s'.format(elapsed[1]),
                )
            )

107 108
        logger.info("\nPlaybook {0} finished: {1}, {2} total tasks.  {3} elapsed. \n".format(
                self.playbook_name,
109 110 111 112 113
                time.asctime(),
                len(self.stats.items()),
                datetime.timedelta(seconds=(int(total_seconds)))
                )
          )