| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Classes representing the monitoring interface for tasks or devices. |
| 6 |
| 7 Usage: |
| 8 # symlink appengine/modules/gae_ts_mon into the top level directory |
| 9 # of your appengine app |
| 10 |
| 11 import gae_ts_mon |
| 12 from google.appengine.api import modules |
| 13 |
| 14 # Sets up default target |
| 15 instance_id = hash(modules.get_current_instance_id()) % 10 |
| 16 gae_ts_mon.initialize(job_name='job', instance=instance_id, |
| 17 service_name='service', endpoint='endpoint') |
| 18 |
| 19 # Will use the default Target set up with initialize |
| 20 count_metric = gae_ts_mon.CounterMetric('my/metric/name', fields={}) |
| 21 count_metric.set(0) |
| 22 for x in range(100): |
| 23 count_metric.increment() |
| 24 |
| 25 # Use a custom Target: |
| 26 t = ts_mon.TaskTarget('service', 'job', 'region', 'host') |
| 27 g_metric = ts_mon.GaugeMetric('/my/metric/name2', |
| 28 fields={'key': 'value'}, |
| 29 target=t) |
| 30 g_metric.set(5) |
| 31 |
| 32 # Flush (sends metrics to monarch, already done automatically every 5m) |
| 33 gae_ts_mon.flush() |
| 34 |
| 35 """ |
| 36 |
| 37 import logging |
| 38 import os |
| 39 import random |
| 40 import threading |
| 41 import time |
| 42 |
| 43 from monacq.proto import metrics_pb2 |
| 44 |
| 45 from common import errors |
| 46 |
| 47 # The maximum number of MetricsData messages to include in each HTTP request. |
| 48 # MetricsCollections larger than this will be split into multiple requests. |
| 49 METRICS_DATA_LENGTH_LIMIT = 1000 |
| 50 |
| 51 |
| 52 class State(object): |
| 53 """Package-level state is stored here so that it is easily accessible. |
| 54 |
| 55 Configuration is kept in this one object at the global level so that all |
| 56 libraries in use by the same tool or service can all take advantage of the |
| 57 same configuration. |
| 58 """ |
| 59 |
| 60 def __init__(self): |
| 61 # The Monitor object that will be used to send all metrics. |
| 62 self.global_monitor = None |
| 63 # The Target object that will be paired with all metrics that don't supply |
| 64 # their own. |
| 65 self.default_target = None |
| 66 # The flush mode being used to control when metrics are pushed. |
| 67 self.flush_mode = None |
| 68 # All metrics created by this application. |
| 69 self.metrics = set() |
| 70 |
| 71 state = State() |
| 72 |
| 73 |
| 74 def send(metric): |
| 75 """Send a single metric to the monitoring api. |
| 76 |
| 77 This is called automatically by Metric.set - you don't need to call it |
| 78 manually. |
| 79 """ |
| 80 if state.flush_mode != 'all': |
| 81 return |
| 82 |
| 83 if not state.global_monitor: |
| 84 raise errors.MonitoringNoConfiguredMonitorError(metric._name) |
| 85 |
| 86 proto = metrics_pb2.MetricsCollection() |
| 87 metric.serialize_to(proto, default_target=state.default_target) |
| 88 state.global_monitor.send(proto) |
| 89 |
| 90 |
| 91 def flush(): |
| 92 """Send all metrics that are registered in the application.""" |
| 93 if not state.global_monitor: |
| 94 raise errors.MonitoringNoConfiguredMonitorError(None) |
| 95 |
| 96 proto = metrics_pb2.MetricsCollection() |
| 97 |
| 98 def loop_action(proto): |
| 99 if len(proto.data) >= METRICS_DATA_LENGTH_LIMIT: |
| 100 state.global_monitor.send(proto) |
| 101 del proto.data[:] |
| 102 |
| 103 for metric in state.metrics: |
| 104 metric.serialize_to(proto, default_target=state.default_target, |
| 105 loop_action=loop_action) |
| 106 |
| 107 state.global_monitor.send(proto) |
| 108 |
| 109 |
| 110 def register(metric): |
| 111 """Adds the metric to the list of metrics sent by flush(). |
| 112 |
| 113 This is called automatically by Metric's constructor. |
| 114 """ |
| 115 # If someone is registering the same metric object twice, that's okay, but |
| 116 # registering two different metric objects with the same metric name is not. |
| 117 if metric in state.metrics: |
| 118 return |
| 119 if any([metric._name == m._name for m in state.metrics]): |
| 120 raise errors.MonitoringDuplicateRegistrationError(metric._name) |
| 121 |
| 122 state.metrics.add(metric) |
| 123 |
| 124 |
| 125 def unregister(metric): |
| 126 """Removes the metric from the list of metrics sent by flush().""" |
| 127 state.metrics.remove(metric) |
| OLD | NEW |