| Index: infra/tools/send_monitoring_event/send_event.py
|
| diff --git a/infra/tools/send_monitoring_event/send_event.py b/infra/tools/send_monitoring_event/send_event.py
|
| index 40d73a3d1d6a2412ad0310c048e2437ab9f2287a..14ea381c96073763e55035c91d91f221195960d5 100644
|
| --- a/infra/tools/send_monitoring_event/send_event.py
|
| +++ b/infra/tools/send_monitoring_event/send_event.py
|
| @@ -10,9 +10,12 @@ import json
|
| import sys
|
|
|
| from infra_libs import event_mon
|
| -import infra_libs.logs
|
| from infra_libs import ts_mon
|
| +import infra_libs.logs
|
|
|
| +from infra_libs.event_mon.protos.log_request_lite_pb2 import LogRequestLite
|
| +from infra_libs.event_mon.protos.chrome_infra_log_pb2 import ChromeInfraEvent
|
| +from infra_libs.event_mon.protos.goma_stats_pb2 import GomaStats
|
|
|
| LOGGER = logging.getLogger(__name__)
|
|
|
| @@ -46,13 +49,10 @@ def get_arguments(argv):
|
| # Common fields
|
| common_group = parser.add_argument_group('Common event options')
|
| common_group.add_argument('--event-mon-timestamp-kind',
|
| - choices=[kind
|
| - for kind in event_mon.TIMESTAMP_KINDS
|
| - if kind],
|
| - default='POINT',
|
| + choices=event_mon.TIMESTAMP_KINDS,
|
| help='General kind of event. This value is used '
|
| 'e.g. to\nautomatically compute durations between '
|
| - 'START and STOP\nevents. Default: %(default)s')
|
| + 'START and STOP\nevents.')
|
| common_group.add_argument('--event-mon-event-timestamp', type=int,
|
| help='Timestamp when the event was generated, as '
|
| 'number of\nmilliseconds since the Unix EPOCH.'
|
| @@ -121,6 +121,11 @@ def get_arguments(argv):
|
| 'list of strings or json-encoded list of string. '
|
| 'Each one must be less than 20 characters long.')
|
|
|
| + build_group.add_argument('--build-event-goma-stats-path',
|
| + metavar='FILENAME',
|
| + help='File containing a serialized GomaStats '
|
| + 'protobuf.')
|
| +
|
| # Read events from file
|
| file_group = parser.add_argument_group('Read events from file')
|
| file_group.add_argument('--events-from-file',
|
| @@ -129,13 +134,23 @@ def get_arguments(argv):
|
| 'option\nis incompatible with --build-event-type and'
|
| '\n--service-event-type.\nSee '
|
| 'send_event.read_events_from_file for details\n'
|
| - 'on the format. This options can be passed multiple\n'
|
| + 'on the format. This option can be passed multiple\n'
|
| 'times, and wildcards can be used.')
|
| file_group.add_argument('--delete-file-when-sent',
|
| action='store_true', default=False,
|
| help='If all events read from a file have been '
|
| 'successfully\nsent to the endpoint, delete the '
|
| - 'file. By default\nfiles are kept.')
|
| + 'file. By default\nfiles are kept. This does not '
|
| + 'affect the file pointed to by '
|
| + '--event-logrequest-path')
|
| +
|
| + file_group.add_argument('--event-logrequest-path',
|
| + metavar='FILENAME',
|
| + help='File containing a serialized LogRequestLite'
|
| + 'proto, containing a single ChromeInfraEvent that '
|
| + 'will be used as the default event. Such a file can '
|
| + 'be generated by passing "file" to '
|
| + '--event-mon-run-type.')
|
|
|
| ts_mon.add_argparse_options(parser)
|
| event_mon.add_argparse_options(parser)
|
| @@ -173,10 +188,78 @@ def get_arguments(argv):
|
| return args
|
|
|
|
|
| +def _process_logrequest_path(args):
|
| + """Sets the default event based on --event-logrequest-path.
|
| +
|
| + This function raises exceptions because if the base event is wrong, then it's
|
| + not worth sending anything anyway.
|
| + """
|
| + if args.event_logrequest_path:
|
| + try:
|
| + with open(args.event_logrequest_path, 'rb') as f:
|
| + request = LogRequestLite.FromString(f.read())
|
| +
|
| + if len(request.log_event) == 1:
|
| + default_event = ChromeInfraEvent.FromString(
|
| + request.log_event[0].source_extension)
|
| + # Assume that the content is sane because we don't want to duplicate
|
| + # any business logic here.
|
| + # TODO(pgervais): find a better solution.
|
| + event_mon.set_default_event(default_event)
|
| + else:
|
| + raise ValueError(
|
| + 'Expected only one log_event in the LogRequestLite proto '
|
| + 'pointed by --event-logrequest-path. Found %d in %s',
|
| + len(request.log_event), args.event_logrequest_path)
|
| + except Exception:
|
| + LOGGER.exception('Failure when reading/parsing file %s',
|
| + args.event_logrequest_path)
|
| + raise
|
| +
|
| + default_event = event_mon.get_default_event()
|
| +
|
| + # When the default event is set using --event-logrequest-path, passing
|
| + # --build-event-type or --service-event-type is optional. These options
|
| + # still takes precedence but they must keep the event type the same.
|
| + if (default_event.build_event.HasField('type') and
|
| + default_event.service_event.HasField('type')):
|
| + msg = ('Default event contains both service_event_type and '
|
| + 'build_event_type which is incorrect. Make sure you passed '
|
| + 'a correct proto to --event-logrequest-path. Otherwise it\'s an '
|
| + 'internal error. Aborting.')
|
| + LOGGER.error(msg)
|
| + raise ValueError(msg)
|
| +
|
| + if default_event.build_event.HasField('type'):
|
| + if args.service_event_type:
|
| + msg = ('The default event contains a type for build_event, but a '
|
| + 'service_event type was provided on the command-line. At most '
|
| + 'one of them can be specified. Aborting.')
|
| + LOGGER.error(msg)
|
| + raise ValueError(msg)
|
| +
|
| + if not args.build_event_type:
|
| + args.build_event_type = event_mon.BuildEvent.BuildEventType.Name(
|
| + default_event.build_event.type)
|
| +
|
| + if default_event.service_event.HasField('type'):
|
| + if args.build_event_type:
|
| + msg = ('The default event contains a type for service_event, but a '
|
| + 'build_event type was provided on the command-line. At most '
|
| + 'one of them can be specified. Aborting.')
|
| + LOGGER.error(msg)
|
| + raise ValueError(msg)
|
| + if not args.service_event_type:
|
| + args.service_event_type = event_mon.ServiceEvent.ServiceEventType.Name(
|
| + default_event.service_event.type)
|
| +
|
| +
|
| def process_argparse_options(args): # pragma: no cover
|
| infra_libs.logs.process_argparse_options(args)
|
| event_mon.process_argparse_options(args)
|
| + # Put here because we want to send the presence metric as late as possible.
|
| ts_mon.process_argparse_options(args)
|
| + _process_logrequest_path(args)
|
|
|
|
|
| def send_service_event(args):
|
| @@ -204,6 +287,16 @@ def send_service_event(args):
|
|
|
| def send_build_event(args):
|
| """Entry point when --build-event-type is passed."""
|
| + goma_stats = None
|
| + if args.build_event_goma_stats_path:
|
| + try:
|
| + with open(args.build_event_goma_stats_path, 'rb') as f:
|
| + goma_stats = GomaStats.FromString(f.read())
|
| + except Exception:
|
| + LOGGER.exception('Failure when reading/parsing file %s',
|
| + args.build_event_goma_stats_path)
|
| + raise
|
| +
|
|
|
| return bool(event_mon.send_build_event(
|
| args.build_event_type,
|
| @@ -216,7 +309,8 @@ def send_build_event(args):
|
| result=args.build_event_result,
|
| extra_result_code=args.build_event_extra_result_code,
|
| timestamp_kind=args.event_mon_timestamp_kind,
|
| - event_timestamp=args.event_mon_event_timestamp))
|
| + event_timestamp=args.event_mon_event_timestamp,
|
| + goma_stats=goma_stats))
|
|
|
|
|
| def send_events_from_file(args):
|
|
|