blob: 1d0b1f5583a9c2331220a2e211d4fd016ed5fefe [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# 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.
#
"""Utility methods for working with logs."""
import os
import time
REQUEST_LOG_ID = 'REQUEST_LOG_ID'
_U_SEC = 1000000
LOG_LEVEL_DEBUG = 0
LOG_LEVEL_INFO = 1
LOG_LEVEL_WARNING = 2
LOG_LEVEL_ERROR = 3
LOG_LEVEL_CRITICAL = 4
LOG_LEVELS = [LOG_LEVEL_DEBUG,
LOG_LEVEL_INFO,
LOG_LEVEL_WARNING,
LOG_LEVEL_ERROR,
LOG_LEVEL_CRITICAL]
_DEFAULT_LEVEL = LOG_LEVEL_ERROR
def _CurrentTimeMicro():
return int(time.time() * _U_SEC)
def _Clean(e):
return e.replace('\0', '\n')
def RequestID():
"""Returns the ID of the current request assigned by App Engine."""
return os.environ.get(REQUEST_LOG_ID, None)
def _StrictParseLogEntry(entry):
"""Parses a single log entry emitted by app_logging.AppLogsHandler.
Parses a log entry of the form LOG <level> <timestamp> <message> where the
level is in the range [0, 4]. If the entry is not of that form, ValueError is
raised.
Args:
entry: The log entry to parse.
Returns:
A (timestamp, level, message) tuple.
Raises:
ValueError: if the entry failed to be parsed.
"""
magic, level, timestamp, message = entry.split(' ', 3)
if magic != 'LOG':
raise ValueError()
timestamp, level = int(timestamp), int(level)
if level not in LOG_LEVELS:
raise ValueError()
return timestamp, level, _Clean(message)
def ParseLogEntry(entry):
"""Parses a single log entry emitted by app_logging.AppLogsHandler.
Parses a log entry of the form LOG <level> <timestamp> <message> where the
level is in the range [0, 4]. If the entry is not of that form, take the whole
entry to be the message. Null characters in the entry are replaced by
newlines.
Args:
entry: The log entry to parse.
Returns:
A (timestamp, level, message) tuple.
"""
try:
return _StrictParseLogEntry(entry)
except ValueError:
return _CurrentTimeMicro(), _DEFAULT_LEVEL, _Clean(entry)
def ParseLogs(logs):
"""Parses a str containing newline separated log entries.
Parses a series of log entries in the form LOG <level> <timestamp> <message>
where the level is in the range [0, 4]. Null characters in the entry are
replaced by newlines.
Args:
logs: A string containing the log entries.
Returns:
A list of (timestamp, level, message) tuples.
"""
return [ParseLogEntry(line) for line in logs.split('\n') if line]