# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Puppet metrics"""

from __future__ import absolute_import
from __future__ import print_function

import time

import yaml

from chromite.lib import cros_logging as logging
from chromite.lib import metrics


logger = logging.getLogger(__name__)

LAST_RUN_FILE = '/var/lib/cros_puppet/state/last_run_summary.yaml'

_config_version_metric = metrics.GaugeMetric(
    'puppet/version/config',
    description='The version of the puppet configuration.'
    '  By default this is the time that the configuration was parsed')
_puppet_version_metric = metrics.StringMetric(
    'puppet/version/puppet',
    description='Version of puppet client installed.')
_events_metric = metrics.GaugeMetric(
    'puppet/events',
    description='Number of changes the puppet client made to the system in its'
    ' last run, by success or failure')
_resources_metric = metrics.GaugeMetric(
    'puppet/resources',
    description='Number of resources known by the puppet client in its last'
    ' run')
_times_metric = metrics.FloatMetric(
    'puppet/times',
    description='Time taken to perform various parts of the last puppet run')
_age_metric = metrics.FloatMetric(
    'puppet/age',
    description='Time since last run')


class _PuppetRunSummary(object):
  """Puppet run summary information."""

  def __init__(self, f):
    """Instantiate instance.

    Args:
      f: file object to read summary from
    """
    self._data = yaml.safe_load(f)

  @property
  def _versions(self):
    """Return mapping of version information."""
    return self._data.get('version', {})

  @property
  def config_version(self):
    """Return config version as int."""
    return self._versions.get('config', -1)

  @property
  def puppet_version(self):
    """Return Puppet version as string."""
    return self._versions.get('puppet', '')

  @property
  def events(self):
    """Return mapping of events information."""
    events = self._data.get('events', {})
    events.pop('total', None)
    return events

  @property
  def resources(self):
    """Return mapping of resources information."""
    resources = self._data.get('resources', {})
    total = resources.pop('total', 0)
    resources['other'] = max(0, total - sum(resources.itervalues()))
    return resources

  @property
  def times(self):
    """Return mapping of time information."""
    times = self._data.get('time', {})
    times.pop('last_run', None)
    total = times.pop('total', None)
    times['other'] = max(0, total - sum(times.itervalues()))
    return times

  @property
  def last_run_time(self):
    """Return last run time as UNIX seconds or None."""
    times = self._data.get('time', {})
    return times.get('last_run')


def collect_puppet_summary():
  """Send Puppet run summary metrics."""
  try:
    with open(LAST_RUN_FILE) as f:
      summary = _PuppetRunSummary(f)
  except Exception as e:
    logger.warning(u'Error loading Puppet run summary: %s', e)
  else:
    _config_version_metric.set(summary.config_version)
    _puppet_version_metric.set(str(summary.puppet_version))

    for key, value in summary.events.iteritems():
      _events_metric.set(value, {'result': key})

    for key, value in summary.resources.iteritems():
      _resources_metric.set(value, {'action': key})

    for key, value in summary.times.iteritems():
      _times_metric.set(value, {'step': key})

    if summary.last_run_time is not None:
      _age_metric.set(time.time() - summary.last_run_time)
