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

Side by Side Diff: infra/tools/send_monitoring_event/send_event.py

Issue 1427903002: send_monitoring_event: support for default event and gomastats (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@event-mon-no-default-kind
Patch Set: Created 5 years, 1 month 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
1 # Copyright 2015 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import argparse 5 import argparse
6 import glob 6 import glob
7 import logging 7 import logging
8 import os 8 import os
9 import json 9 import json
10 import sys 10 import sys
11 11
12 from infra_libs import event_mon 12 from infra_libs import event_mon
13 from infra_libs import ts_mon
13 import infra_libs.logs 14 import infra_libs.logs
14 from infra_libs import ts_mon
15 15
16 from infra_libs.event_mon.protos.log_request_lite_pb2 import LogRequestLite
17 from infra_libs.event_mon.protos.chrome_infra_log_pb2 import ChromeInfraEvent
18 from infra_libs.event_mon.protos.goma_stats_pb2 import GomaStats
16 19
17 LOGGER = logging.getLogger(__name__) 20 LOGGER = logging.getLogger(__name__)
18 21
19 22
20 def get_arguments(argv): 23 def get_arguments(argv):
21 """Process command-line arguments. 24 """Process command-line arguments.
22 25
23 Args: 26 Args:
24 argv (list of strings): sys.argv[1:] 27 argv (list of strings): sys.argv[1:]
25 Returns: 28 Returns:
(...skipping 13 matching lines...) Expand all
39 --service-event-stack-trace "<stack trace>" 42 --service-event-stack-trace "<stack trace>"
40 43
41 run.py infra.tools.send_monitoring_event --build-event-type=SCHEDULER \\ 44 run.py infra.tools.send_monitoring_event --build-event-type=SCHEDULER \\
42 --build-event-build-name=foo 45 --build-event-build-name=foo
43 --build-event-hostname='bot.dns.name' 46 --build-event-hostname='bot.dns.name'
44 """, formatter_class=argparse.RawTextHelpFormatter) 47 """, formatter_class=argparse.RawTextHelpFormatter)
45 48
46 # Common fields 49 # Common fields
47 common_group = parser.add_argument_group('Common event options') 50 common_group = parser.add_argument_group('Common event options')
48 common_group.add_argument('--event-mon-timestamp-kind', 51 common_group.add_argument('--event-mon-timestamp-kind',
49 choices=[kind 52 choices=event_mon.TIMESTAMP_KINDS,
50 for kind in event_mon.TIMESTAMP_KINDS
51 if kind],
52 default='POINT',
dsansome 2015/10/29 23:17:33 Should this still have the default? If not remove
pgervais 2015/11/02 19:38:58 Done.
53 help='General kind of event. This value is used ' 53 help='General kind of event. This value is used '
54 'e.g. to\nautomatically compute durations between ' 54 'e.g. to\nautomatically compute durations between '
55 'START and STOP\nevents. Default: %(default)s') 55 'START and STOP\nevents. Default: %(default)s')
56 common_group.add_argument('--event-mon-event-timestamp', type=int, 56 common_group.add_argument('--event-mon-event-timestamp', type=int,
57 help='Timestamp when the event was generated, as ' 57 help='Timestamp when the event was generated, as '
58 'number of\nmilliseconds since the Unix EPOCH.' 58 'number of\nmilliseconds since the Unix EPOCH.'
59 '\nDefaults to current time.') 59 '\nDefaults to current time.')
60 60
61 # Service event 61 # Service event
62 service_group = parser.add_argument_group('Service event options') 62 service_group = parser.add_argument_group('Service event options')
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 choices=event_mon.BUILD_RESULTS, 114 choices=event_mon.BUILD_RESULTS,
115 help='Result of build or step depending on ' 115 help='Result of build or step depending on '
116 'whether any \n--build-event-step-* options have ' 116 'whether any \n--build-event-step-* options have '
117 'been provided or not.') 117 'been provided or not.')
118 118
119 build_group.add_argument('--build-event-extra-result-code', 119 build_group.add_argument('--build-event-extra-result-code',
120 help='Extra result code. String, comma-separated ' 120 help='Extra result code. String, comma-separated '
121 'list of strings or json-encoded list of string. ' 121 'list of strings or json-encoded list of string. '
122 'Each one must be less than 20 characters long.') 122 'Each one must be less than 20 characters long.')
123 123
124 build_group.add_argument('--build-event-goma-stats-path',
125 metavar='FILENAME',
126 help='File containing a serialized GomaStats '
127 'protobuf.')
128
124 # Read events from file 129 # Read events from file
125 file_group = parser.add_argument_group('Read events from file') 130 file_group = parser.add_argument_group('Read events from file')
126 file_group.add_argument('--events-from-file', 131 file_group.add_argument('--events-from-file',
127 metavar='FILENAME', nargs='*', 132 metavar='FILENAME', nargs='*',
128 help='File containing events as json dict. This ' 133 help='File containing events as json dict. This '
129 'option\nis incompatible with --build-event-type and' 134 'option\nis incompatible with --build-event-type and'
130 '\n--service-event-type.\nSee ' 135 '\n--service-event-type.\nSee '
131 'send_event.read_events_from_file for details\n' 136 'send_event.read_events_from_file for details\n'
132 'on the format. This options can be passed multiple\n' 137 'on the format. This option can be passed multiple\n'
133 'times, and wildcards can be used.') 138 'times, and wildcards can be used.')
134 file_group.add_argument('--delete-file-when-sent', 139 file_group.add_argument('--delete-file-when-sent',
135 action='store_true', default=False, 140 action='store_true', default=False,
136 help='If all events read from a file have been ' 141 help='If all events read from a file have been '
137 'successfully\nsent to the endpoint, delete the ' 142 'successfully\nsent to the endpoint, delete the '
138 'file. By default\nfiles are kept.') 143 'file. By default\nfiles are kept. This does not '
144 'affect the file pointed to by '
145 '--event-logrequest-path')
146
147 file_group.add_argument('--event-logrequest-path',
148 metavar='FILENAME',
149 help='File containing a serialized LogRequestLite'
150 'proto, containing a single ChromeInfraEvent that '
151 'will be used as the default event. Such a file can '
152 'be generated by passing "file" to '
153 '--event-mon-run-type.')
139 154
140 ts_mon.add_argparse_options(parser) 155 ts_mon.add_argparse_options(parser)
141 event_mon.add_argparse_options(parser) 156 event_mon.add_argparse_options(parser)
142 infra_libs.logs.add_argparse_options(parser) 157 infra_libs.logs.add_argparse_options(parser)
143 158
144 parser.set_defaults( 159 parser.set_defaults(
145 ts_mon_flush='manual', 160 ts_mon_flush='manual',
146 ts_mon_target_type='task', 161 ts_mon_target_type='task',
147 ts_mon_task_service_name='send_monitoring_event', 162 ts_mon_task_service_name='send_monitoring_event',
148 ts_mon_task_job_name='manual', 163 ts_mon_task_job_name='manual',
(...skipping 17 matching lines...) Expand all
166 extra_result_code = args.build_event_extra_result_code.strip() 181 extra_result_code = args.build_event_extra_result_code.strip()
167 if extra_result_code.startswith('['): 182 if extra_result_code.startswith('['):
168 extra_result_code = json.loads(extra_result_code) 183 extra_result_code = json.loads(extra_result_code)
169 elif ',' in extra_result_code: 184 elif ',' in extra_result_code:
170 extra_result_code = extra_result_code.split(',') 185 extra_result_code = extra_result_code.split(',')
171 args.build_event_extra_result_code = extra_result_code 186 args.build_event_extra_result_code = extra_result_code
172 187
173 return args 188 return args
174 189
175 190
191 def _process_logrequest_path(args):
192 """Sets the default event based on --event-logrequest-path.
193
194 This function raises exceptions because if the base event is wrong, then it's
195 not worth sending anything anyway.
196 """
197 if args.event_logrequest_path:
198 try:
199 with open(args.event_logrequest_path, 'rb') as f:
200 request = LogRequestLite.FromString(f.read())
201
202 if len(request.log_event) == 1:
203 default_event = ChromeInfraEvent.FromString(
204 request.log_event[0].source_extension)
205 # Assume that the content is sane because we don't want to duplicate
206 # any business logic here.
207 # TODO(pgervais): find a better solution.
208 event_mon.set_default_event(default_event)
209 else:
210 raise ValueError(
211 'Expected only one log_event in the LogRequestLite proto '
212 'pointed by --event-logrequest-path. Found %d in %s',
213 len(request.log_event), args.event_logrequest_path)
214 except Exception:
215 LOGGER.exception('Failure when reading/parsing file %s',
216 args.event_logrequest_path)
217 raise
218
219 default_event = event_mon.get_default_event()
220
221 # When the default event is set using --event-logrequest-path, passing
222 # --build-event-type or --service-event-type is optional. These options
223 # still takes precedence but they must keep the event type the same.
224 if (default_event.build_event.HasField('type') and
225 default_event.service_event.HasField('type')):
226 msg = ('Default event contains both service_event_type and '
227 'build_event_type which is incorrect. Make sure you passed '
228 'a correct proto to --event-logrequest-path. Otherwise it\'s an '
229 'internal error. Aborting.')
230 LOGGER.error(msg)
231 raise ValueError(msg)
232
233 if default_event.build_event.HasField('type'):
234 if args.service_event_type:
235 msg = ('The default event contains a type for build_event, but a '
236 'service_event type was provided on the command-line. At most '
237 'one of them can be specified. Aborting.')
238 LOGGER.error(msg)
239 raise ValueError(msg)
240
241 if not args.build_event_type:
242 args.build_event_type = event_mon.BuildEvent.BuildEventType.Name(
243 default_event.build_event.type)
244
245 if default_event.service_event.HasField('type'):
246 if args.build_event_type:
247 msg = ('The default event contains a type for service_event, but a '
248 'build_event type was provided on the command-line. At most '
249 'one of them can be specified. Aborting.')
250 LOGGER.error(msg)
251 raise ValueError(msg)
252 if not args.service_event_type:
253 args.service_event_type = event_mon.ServiceEvent.ServiceEventType.Name(
254 default_event.service_event.type)
255
256
176 def process_argparse_options(args): # pragma: no cover 257 def process_argparse_options(args): # pragma: no cover
177 infra_libs.logs.process_argparse_options(args) 258 infra_libs.logs.process_argparse_options(args)
178 event_mon.process_argparse_options(args) 259 event_mon.process_argparse_options(args)
260 # Put here because we want to send the presence metric as late as possible.
179 ts_mon.process_argparse_options(args) 261 ts_mon.process_argparse_options(args)
262 _process_logrequest_path(args)
180 263
181 264
182 def send_service_event(args): 265 def send_service_event(args):
183 """Entry point when --service-event-type is passed.""" 266 """Entry point when --service-event-type is passed."""
184 revinfo = {} 267 revinfo = {}
185 if args.service_event_revinfo: 268 if args.service_event_revinfo:
186 if args.service_event_revinfo == '-': # pragma: no cover 269 if args.service_event_revinfo == '-': # pragma: no cover
187 revinfo = event_mon.parse_revinfo(sys.stdin.read()) 270 revinfo = event_mon.parse_revinfo(sys.stdin.read())
188 else: 271 else:
189 with open(args.service_event_revinfo, 'r') as f: 272 with open(args.service_event_revinfo, 'r') as f:
190 revinfo = event_mon.parse_revinfo(f.read()) 273 revinfo = event_mon.parse_revinfo(f.read())
191 elif args.service_event_revinfo_from_gclient: # pragma: no cover 274 elif args.service_event_revinfo_from_gclient: # pragma: no cover
192 revinfo = event_mon.get_revinfo() 275 revinfo = event_mon.get_revinfo()
193 276
194 if args.service_event_stack_trace: 277 if args.service_event_stack_trace:
195 args.service_event_type = 'CRASH' 278 args.service_event_type = 'CRASH'
196 279
197 return bool(event_mon.send_service_event( 280 return bool(event_mon.send_service_event(
198 args.service_event_type, 281 args.service_event_type,
199 code_version=revinfo.values(), 282 code_version=revinfo.values(),
200 stack_trace=args.service_event_stack_trace, 283 stack_trace=args.service_event_stack_trace,
201 timestamp_kind=args.event_mon_timestamp_kind, 284 timestamp_kind=args.event_mon_timestamp_kind,
202 event_timestamp=args.event_mon_event_timestamp)) 285 event_timestamp=args.event_mon_event_timestamp))
203 286
204 287
205 def send_build_event(args): 288 def send_build_event(args):
206 """Entry point when --build-event-type is passed.""" 289 """Entry point when --build-event-type is passed."""
290 goma_stats = None
291 if args.build_event_goma_stats_path:
292 try:
293 with open(args.build_event_goma_stats_path, 'rb') as f:
294 goma_stats = GomaStats.FromString(f.read())
295 except Exception:
296 LOGGER.exception('Failure when reading/parsing file %s',
297 args.build_event_goma_stats_path)
298 raise
299
207 300
208 return bool(event_mon.send_build_event( 301 return bool(event_mon.send_build_event(
209 args.build_event_type, 302 args.build_event_type,
210 args.build_event_hostname, 303 args.build_event_hostname,
211 args.build_event_build_name, 304 args.build_event_build_name,
212 build_number=args.build_event_build_number, 305 build_number=args.build_event_build_number,
213 build_scheduling_time=args.build_event_build_scheduling_time, 306 build_scheduling_time=args.build_event_build_scheduling_time,
214 step_name=args.build_event_step_name, 307 step_name=args.build_event_step_name,
215 step_number=args.build_event_step_number, 308 step_number=args.build_event_step_number,
216 result=args.build_event_result, 309 result=args.build_event_result,
217 extra_result_code=args.build_event_extra_result_code, 310 extra_result_code=args.build_event_extra_result_code,
218 timestamp_kind=args.event_mon_timestamp_kind, 311 timestamp_kind=args.event_mon_timestamp_kind,
219 event_timestamp=args.event_mon_event_timestamp)) 312 event_timestamp=args.event_mon_event_timestamp,
313 goma_stats=goma_stats))
220 314
221 315
222 def send_events_from_file(args): 316 def send_events_from_file(args):
223 """Entry point when --events-from-file is passed.""" 317 """Entry point when --events-from-file is passed."""
224 file_list = get_event_file_list(args.events_from_file) 318 file_list = get_event_file_list(args.events_from_file)
225 status = True 319 status = True
226 320
227 for filename in file_list: 321 for filename in file_list:
228 LOGGER.info('Processing %s', filename) 322 LOGGER.info('Processing %s', filename)
229 events = read_events_from_file(filename) 323 events = read_events_from_file(filename)
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 build_scheduling_time=args.get('build-event-build-scheduling-time'), 384 build_scheduling_time=args.get('build-event-build-scheduling-time'),
291 step_name=args.get('build-event-step-name'), 385 step_name=args.get('build-event-step-name'),
292 step_number=args.get('build-event-step-number'), 386 step_number=args.get('build-event-step-number'),
293 result=args.get('build-event-result'), 387 result=args.get('build-event-result'),
294 extra_result_code=args.get('build-event-extra-result-code'), 388 extra_result_code=args.get('build-event-extra-result-code'),
295 timestamp_kind=args.get('event-mon-timestamp-kind'), 389 timestamp_kind=args.get('event-mon-timestamp-kind'),
296 event_timestamp=args.get('event-mon-event-timestamp'), 390 event_timestamp=args.get('event-mon-event-timestamp'),
297 service_name=args.get('event-mon-service-name'))) 391 service_name=args.get('event-mon-service-name')))
298 392
299 return events 393 return events
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698