| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- # Copyright (C) 2017 The Android Open Source Project
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import json
- import multiprocessing
- TASK_COMMAND = 'command'
- TASK_SYNC_NETWORK = 'sync-network'
- TASK_SYNC_LOCAL = 'sync-local'
- class EventLog(object):
- """Event log that records events that occurred during a repo invocation.
- Events are written to the log as a consecutive JSON entries, one per line.
- Each entry contains the following keys:
- - id: A ('RepoOp', ID) tuple, suitable for storing in a datastore.
- The ID is only unique for the invocation of the repo command.
- - name: Name of the object being operated upon.
- - task_name: The task that was performed.
- - start: Timestamp of when the operation started.
- - finish: Timestamp of when the operation finished.
- - success: Boolean indicating if the operation was successful.
- - try_count: A counter indicating the try count of this task.
- Optionally:
- - parent: A ('RepoOp', ID) tuple indicating the parent event for nested
- events.
- Valid task_names include:
- - command: The invocation of a subcommand.
- - sync-network: The network component of a sync command.
- - sync-local: The local component of a sync command.
- Specific tasks may include additional informational properties.
- """
- def __init__(self):
- """Initializes the event log."""
- self._log = []
- self._parent = None
- def Add(self, name, task_name, start, finish=None, success=None,
- try_count=1, kind='RepoOp'):
- """Add an event to the log.
- Args:
- name: Name of the object being operated upon.
- task_name: A sub-task that was performed for name.
- start: Timestamp of when the operation started.
- finish: Timestamp of when the operation finished.
- success: Boolean indicating if the operation was successful.
- try_count: A counter indicating the try count of this task.
- kind: The kind of the object for the unique identifier.
- Returns:
- A dictionary of the event added to the log.
- """
- event = {
- 'id': (kind, _NextEventId()),
- 'name': name,
- 'task_name': task_name,
- 'start_time': start,
- 'try': try_count,
- }
- if self._parent:
- event['parent'] = self._parent['id']
- if success is not None or finish is not None:
- self.FinishEvent(event, finish, success)
- self._log.append(event)
- return event
- def AddSync(self, project, task_name, start, finish, success):
- """Add a event to the log for a sync command.
- Args:
- project: Project being synced.
- task_name: A sub-task that was performed for name.
- One of (TASK_SYNC_NETWORK, TASK_SYNC_LOCAL)
- start: Timestamp of when the operation started.
- finish: Timestamp of when the operation finished.
- success: Boolean indicating if the operation was successful.
- Returns:
- A dictionary of the event added to the log.
- """
- event = self.Add(project.relpath, task_name, start, finish, success)
- if event is not None:
- event['project'] = project.name
- if project.revisionExpr:
- event['revision'] = project.revisionExpr
- if project.remote.url:
- event['project_url'] = project.remote.url
- if project.remote.fetchUrl:
- event['remote_url'] = project.remote.fetchUrl
- try:
- event['git_hash'] = project.GetCommitRevisionId()
- except Exception:
- pass
- return event
- def GetStatusString(self, success):
- """Converst a boolean success to a status string.
- Args:
- success: Boolean indicating if the operation was successful.
- Returns:
- status string.
- """
- return 'pass' if success else 'fail'
- def FinishEvent(self, event, finish, success):
- """Finishes an incomplete event.
- Args:
- event: An event that has been added to the log.
- finish: Timestamp of when the operation finished.
- success: Boolean indicating if the operation was successful.
- Returns:
- A dictionary of the event added to the log.
- """
- event['status'] = self.GetStatusString(success)
- event['finish_time'] = finish
- return event
- def SetParent(self, event):
- """Set a parent event for all new entities.
- Args:
- event: The event to use as a parent.
- """
- self._parent = event
- def Write(self, filename):
- """Writes the log out to a file.
- Args:
- filename: The file to write the log to.
- """
- with open(filename, 'w+') as f:
- for e in self._log:
- json.dump(e, f, sort_keys=True)
- f.write('\n')
- # An integer id that is unique across this invocation of the program.
- _EVENT_ID = multiprocessing.Value('i', 1)
- def _NextEventId():
- """Helper function for grabbing the next unique id.
- Returns:
- A unique, to this invocation of the program, integer id.
- """
- with _EVENT_ID.get_lock():
- val = _EVENT_ID.value
- _EVENT_ID.value += 1
- return val
|