1# -*- coding: utf-8 -*- 2# Copyright 2015 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Logging module to be used by all scripts. 7 8cros_logging is a wrapper around logging with additional support for NOTICE 9level. This is to be used instead of the default logging module. The new 10logging level can only be used from here. 11 12The log levels should be used as follows: 13 14DEBUG: Enabled on the CLI with --debug. This is the noisiest logging level. 15Often, as the name suggests, it may contain debugging information you wouldn't 16otherwise need. 17 18INFO: Enabled on the CLI with --verbose. Logging at this level should contain 19relatively fine-grained info about the steps the process is performing, but 20should be light on details (which should be in debug). 21 22NOTICE: The default log level. It should relay a high level overview of what 23the process is doing. It should NOT be a noisy output. 24 25WARNING: Unexpected scenarios that are well handled and do not interrupt the 26process, things like retrying an operation or missing optional information 27needed to complete a portion of a process. 28 29ERROR: Problems that are fatal to a specific operation or script, e.g. 30unable to read a file or invalid arguments. 31 32CRITICAL/FATAL: Rarely needed. These should reflect an extraordinary error that 33might require the shutdown of an application or lead to data loss. 34 35WARNING, ERROR, CRITICAL/FATAL: These levels are always included in the above 36levels as one would expect. Limiting the output of a script to just these log 37levels is rarely desirable, but the --log-level argument can be used to do so. 38""" 39 40from __future__ import print_function 41 42import sys 43# pylint: disable=unused-wildcard-import, wildcard-import 44from logging import * 45# pylint: enable=unused-wildcard-import, wildcard-import 46 47# Have to import shutdown explicitly from logging because it is not included 48# in logging's __all__. 49# pylint: disable=unused-import 50from logging import shutdown 51# pylint: enable=unused-import 52 53# Import as private to avoid polluting module namespace. 54from autotest_lib.utils.frozen_chromite.lib import buildbot_annotations as _annotations 55 56 57# Remove deprecated APIs to force use of new ones. 58del WARN 59del warn 60 61 62# Notice Level. 63NOTICE = 25 64addLevelName(NOTICE, 'NOTICE') 65 66 67# Notice implementation. 68def notice(message, *args, **kwargs): 69 """Log 'msg % args' with severity 'NOTICE'.""" 70 log(NOTICE, message, *args, **kwargs) 71 72 73# Only buildbot aware entry-points need to spew buildbot specific logs. Require 74# user action for the special log lines. 75_buildbot_markers_enabled = False 76def EnableBuildbotMarkers(): 77 # pylint: disable=global-statement 78 global _buildbot_markers_enabled 79 _buildbot_markers_enabled = True 80 81 82def _PrintForBuildbot(handle, annotation_class, *args): 83 """Log a line for buildbot. 84 85 This function dumps a line to log recognizable by buildbot if 86 EnableBuildbotMarkers has been called. Otherwise, it dumps the same line in a 87 human friendly way that buildbot ignores. 88 89 Args: 90 handle: The pipe to dump the log to. If None, log to sys.stderr. 91 annotation_class: Annotation subclass for the type of buildbot log. 92 buildbot_tag: A tag specifying the type of buildbot log. 93 *args: The rest of the str arguments to be dumped to the log. 94 """ 95 if handle is None: 96 handle = sys.stderr 97 if annotation_class == _annotations.SetEmailNotifyProperty: 98 annotation = annotation_class(*args) 99 else: 100 # Cast each argument, because we end up getting all sorts of objects from 101 # callers. 102 str_args = [str(x) for x in args] 103 annotation = annotation_class(*str_args) 104 if _buildbot_markers_enabled: 105 line = str(annotation) 106 else: 107 line = annotation.human_friendly 108 handle.write('\n' + line + '\n') 109 110 111def PrintBuildbotLink(text, url, handle=None): 112 """Prints out a link to buildbot.""" 113 _PrintForBuildbot(handle, _annotations.StepLink, text, url) 114 115 116def PrintKitchenSetBuildProperty(name, data, handle=None): 117 """Prints out a request to set a build property to a JSON value.""" 118 _PrintForBuildbot(handle, _annotations.SetBuildProperty, name, data) 119 120 121def PrintKitchenSetEmailNotifyProperty(name, data, handle=None): 122 """Prints out a request to set an email_notify build property.""" 123 _PrintForBuildbot(handle, _annotations.SetEmailNotifyProperty, name, data) 124 125 126def PrintBuildbotStepText(text, handle=None): 127 """Prints out stage text to buildbot.""" 128 _PrintForBuildbot(handle, _annotations.StepText, text) 129 130 131def PrintBuildbotStepWarnings(handle=None): 132 """Marks a stage as having warnings.""" 133 PrintBuildbotStepText('[FAILED BUT FORGIVEN]', handle=handle) 134 # Warnings not supported by LUCI, so working around until re-added. 135 _PrintForBuildbot(handle, _annotations.StepWarnings) 136 137 138def PrintBuildbotStepFailure(handle=None): 139 """Marks a stage as having failures.""" 140 _PrintForBuildbot(handle, _annotations.StepFailure) 141 142 143def PrintBuildbotStepName(name, handle=None): 144 """Marks a step name for buildbot to display.""" 145 _PrintForBuildbot(handle, _annotations.BuildStep, name) 146