• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..16-Feb-2021-

common/H16-Feb-2021-2,1081,483

protobuf/google/H16-Feb-2021-49,26041,304

protos/H16-Feb-2021-1,5931,407

third_party/H16-Feb-2021-13,31810,044

.expect_tests.cfgH A D16-Feb-202170 65

README.mdH A D16-Feb-20215.9 KiB146108

__init__.pyH A D16-Feb-20214 KiB8859

config.pyH A D16-Feb-202111.8 KiB361276

handlers.pyH A D16-Feb-20219.4 KiB290233

httplib2_utils.pyH A D16-Feb-202113.8 KiB399321

include.yamlH A D16-Feb-202182 54

shared.pyH A D16-Feb-20212.3 KiB7856

utils.pyH A D16-Feb-20218 KiB247184

README.md

1# Setting up timeseries monitoring on App Engine.
2
31.  Symlink this directory into your appengine app.
4
5        cd infra/appengine/myapp
6        ln -s ../../appengine_module/gae_ts_mon .
7
81.  Add the scheduled task to your `cron.yaml` file.  Create it if you don't
9    have one already.
10
11        cron:
12        - description: Send ts_mon metrics
13          url: /internal/cron/ts_mon/send
14          schedule: every 1 minutes
15          target: <cron_module_name>  # optional
16
171.  Include the URL handler for that scheduled task in your `app.yaml` file.
18
19        includes:
20        - gae_ts_mon  # handles /internal/cron/ts_mon/send
21
221.  Initialize the library in your request handler.
23
24        import gae_ts_mon
25
26        [...]
27
28        app = webapp2.WSGIApplication(my_handlers)
29        gae_ts_mon.initialize(app, cron_module='<cron_module_name>')
30
31    You must do this in every top-level request handler that's listed in your
32    app.yaml to ensure metrics are registered no matter which type of request
33    an instance receives first.
34
35    If your app does not contain a `webapp2.WSGIApplication` instance
36    (e.g. it's a Cloud Endpoints only app), then pass `None` as the
37    first argument to `gae_ts_mon.initialize`.
38
39    The `gae_ts_mon.initialize` method takes a few optional parameters:
40     - `cron_module` (str, default='default'): if you specified a custom
41       module for the cron job, you must specify it in every call to
42       `initialize`.
43     - `is_enabled_fn` (function with no arguments returning `bool`):
44       a callback to enable/disable sending the actual metrics. Default: `None`
45       which is equivalent to `lambda: True`. The callback is called on every
46       metrics flush, and takes effect immediately. Make sure the callback is
47       efficient, or it will slow down your requests.
48
491.  Instrument all Cloud Endpoint methods if you have any by adding a decorator:
50
51        @gae_ts_mon.instrument_endpoint()
52        @endpoints.method(...)
53        def your_method(self, request):
54          ...
55
561.  Give your app's service account permission to send metrics to the API.
57    You need the email address of your app's "App Engine default service
58    account" from the `IAM & Admin` page in the cloud console.  It'll look
59    something like `app-id@appspot.gserviceaccount.com`.
60    Add it as a "Service Account Actor" of the "App Engine Metric Publishers"
61    service account in the
62    [google.com:prodx-mon-chrome-infra project](https://console.developers.google.com/iam-admin/serviceaccounts/project?project=google.com:prodx-mon-chrome-infra&organizationId=433637338589)
63    by selecting it from the list and clicking "Permissions".
64    If you see an error "You do not have viewing permissions for the selected
65    resource.", then please ask the current chrome-trooper to do it for you.
66
671.  You also need to enable the Google Identity and Access Management (IAM) API
68    for your project if it's not enabled already.
69
70You're done!  You can now use ts_mon metrics exactly as you normally would using
71the infra_libs.ts_mon module. Here's a quick example, but see the
72[timeseries monitoring docs](https://chrome-internal.googlesource.com/infra/infra_internal/+/master/doc/ts_mon.md)
73for more information.
74
75    from infra_libs import ts_mon
76
77    class MyHandler(webapp2.RequestHandler):
78      goats_teleported = ts_mon.CounterMetric(
79          'goats/teleported',
80          'Number of goats teleported',
81          None)
82
83      def get(self):
84        count = goat_teleporter.teleport()
85        goats_teleported.increment(count)
86
87        self.response.write('Teleported %d goats this time' % count)
88
89
90## Appengine Modules
91
92Multiple Appengine modules are fully supported - the module name will appear in
93as `job_name` field in metrics when they are exported.
94
95The scheduled task only needs to run in one module.
96
97## Global Metrics
98
99Normally, each AppEnigne app's instance sends its own set of metrics
100at its own pace.  This can be a problem, however, if you want to
101report a metric that only makes sense globally, e.g. the count of
102certain Datastore entities computed once a minute in a cron job.
103
104Setting such a metric in an individual instance is incorrect, since a
105cron job will run in a randomly selected instance, and that instance
106will continue to send the same old value until it's picked by the cron
107job again. The receiving monitoring endpoint will not be able to tell
108which metric is the most recent, and by default will try to sum up the
109values from all the instances, resulting in a wrong value.
110
111A "global" metric is a metric that is not tied to an instance, and is
112guaranteed to be computed and sent at most once per minute,
113globally. Here's an example of how to set up a global metric:
114
115    from infra_libs import ts_mon
116
117    # Override default target fields for app-global metrics.
118    TARGET_FIELDS = {
119        'job_name':  '',  # module name
120        'hostname': '',  # version
121        'task_num':  0,  # instance ID
122    }
123
124    remaining = ts_mon.GaugeMetric('goats/remaining', '...', None)
125    in_flight = ts_mon.GaugeMetric('goats/in_flight', '...', None)
126
127    def set_global_metrics():
128      # Query some global resource, e.g. Datastore
129      remaining.set(len(goats_to_teleport()), target_fields=TARGET_FIELDS)
130      in_flight.set(len(goats_being_teleported()), target_fields=TARGET_FIELDS)
131
132    ts_mon.register_global_metrics([remaining, in_flight])
133    ts_mon.register_global_metrics_callback('my callback', set_global_metrics)
134
135The registered callback will be called at most once per minute, and
136only one instance will be running it at a time. A global metric is
137then cleared the moment it is sent.  Thus, global metrics will be sent
138at the correct intervals, regardless of the number of instances the
139app is currently running.
140
141Note also the use of `target_fields` parameter: it overrides the
142default target fields which would otherwise distinguish the metric per
143module, version, or instance ID. Using `target_fields` in regular,
144"local" metrics is not allowed, as it would result in errors on the
145monitoring endpoint, and loss of data.
146