| #!/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. |
| # |
| |
| |
| |
| |
| |
| """Logging utilities for use by applications. |
| |
| Classes defined here: |
| AppLogsHandler: StreamHandler subclass |
| """ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| import logging |
| import sys |
| import types |
| |
| from google.appengine.api import logservice |
| |
| |
| |
| |
| NEWLINE_REPLACEMENT = "\0" |
| |
| class AppLogsHandler(logging.StreamHandler): |
| """Logging handler that will direct output to a persistent store of |
| application logs. |
| |
| This handler will output log statements to stderr. This handler is |
| automatically initialized and attached to the Python common logging library. |
| """ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| def __init__(self, stream=None): |
| """Constructor. |
| |
| Args: |
| # stream is optional. it defaults to sys.stderr. |
| stream: destination for output |
| """ |
| |
| |
| logging.StreamHandler.__init__(self, stream) |
| |
| def close(self): |
| """Closes the stream. |
| |
| This implementation based on the implementation of FileHandler.close().""" |
| self.flush() |
| self.stream.close() |
| logging.StreamHandler.close(self) |
| |
| def emit(self, record): |
| """Emit a record. |
| |
| This implementation is based on the implementation of |
| StreamHandler.emit().""" |
| try: |
| message = self._AppLogsMessage(record) |
| if isinstance(message, unicode): |
| message = message.encode("UTF-8") |
| self.stream.write(message) |
| |
| |
| self.flush() |
| logservice.auto_flush(lines_emitted=1) |
| except (KeyboardInterrupt, SystemExit): |
| raise |
| except: |
| self.handleError(record) |
| |
| def _AppLogsMessage(self, record): |
| """Converts the log record into a log line.""" |
| |
| |
| |
| message = self.format(record).replace("\r\n", NEWLINE_REPLACEMENT) |
| message = message.replace("\r", NEWLINE_REPLACEMENT) |
| message = message.replace("\n", NEWLINE_REPLACEMENT) |
| |
| return "LOG %d %d %s\n" % (self._AppLogsLevel(record.levelno), |
| long(record.created * 1000 * 1000), |
| message) |
| |
| def _AppLogsLevel(self, level): |
| """Converts the logging level used in Python to the API logging level""" |
| if level >= logging.CRITICAL: |
| return 4 |
| elif level >= logging.ERROR: |
| return 3 |
| elif level >= logging.WARNING: |
| return 2 |
| elif level >= logging.INFO: |
| return 1 |
| else: |
| return 0 |