Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: infra_libs/instrumented_requests.py

Issue 2213143002: Add infra_libs as a bootstrap dependency. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Removed the ugly import hack Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (c) 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 """Report ts_mon metrics for HTTP requests made by the `requests` library.
6
7 This module provides get(), post(), etc. methods that wrap the corresponding
8 methods in the requests module. They take an additional first 'name' argument
9 which is an identifier for the type of request being made.
10
11 Example::
12
13 from infra_libs import instrumented_requests
14 r = instrumented_requests.get('myapi', 'https://example.com/api')
15
16 Alternatively you can add the hook manually::
17
18 import requests
19 from infra_libs import instrumented_requests
20 r = requests.get(
21 'https://example.com/api',
22 hooks={'response': instrumented_requests.instrumentation_hook('myapi')})
23 """
24
25 import functools
26
27 import requests
28
29 from infra_libs.ts_mon.common import http_metrics
30
31
32 def instrumentation_hook(name):
33 """Returns a hook function that records ts_mon metrics about the request.
34
35 Usage::
36
37 r = requests.get(
38 'https://example.com/api',
39 hooks={'response': instrumented_requests.instrumentation_hook('myapi')})
40
41 Args:
42 name: An identifier for the HTTP requests made by this object.
43 """
44
45 def _content_length(headers):
46 if headers is None or 'content-length' not in headers:
47 return 0
48 return int(headers['content-length'])
49
50 def hook(response, *_args, **_kwargs):
51 request_bytes = _content_length(response.request.headers)
52 response_bytes = _content_length(response.headers)
53 duration_msec = response.elapsed.total_seconds() * 1000
54
55 fields = {'name': name, 'client': 'requests'}
56 http_metrics.request_bytes.add(request_bytes, fields=fields)
57 http_metrics.response_bytes.add(response_bytes, fields=fields)
58 http_metrics.durations.add(duration_msec, fields=fields)
59
60 _update_status(name, response.status_code)
61
62 return hook
63
64
65 def _update_status(name, status):
66 fields = {'status': status, 'name': name, 'client': 'requests'}
67 http_metrics.response_status.increment(fields=fields)
68
69
70 def _wrap(method, name, url, *args, **kwargs):
71 hooks = {'response': instrumentation_hook(name)}
72 if 'hooks' in kwargs:
73 hooks.update(kwargs['hooks'])
74 kwargs['hooks'] = hooks
75
76 try:
77 return getattr(requests, method)(url, *args, **kwargs)
78 except requests.exceptions.ReadTimeout:
79 _update_status(name, http_metrics.STATUS_TIMEOUT)
80 raise
81 except requests.exceptions.ConnectionError:
82 _update_status(name, http_metrics.STATUS_ERROR)
83 raise
84 except requests.exceptions.RequestException:
85 _update_status(name, http_metrics.STATUS_EXCEPTION)
86 raise
87
88
89 request = functools.partial(_wrap, 'request')
90 get = functools.partial(_wrap, 'get')
91 head = functools.partial(_wrap, 'head')
92 post = functools.partial(_wrap, 'post')
93 patch = functools.partial(_wrap, 'patch')
94 put = functools.partial(_wrap, 'put')
95 delete = functools.partial(_wrap, 'delete')
96 options = functools.partial(_wrap, 'options')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698