|
1 #!/usr/bin/env python |
|
2 # |
|
3 # Copyright 2007 Google Inc. |
|
4 # |
|
5 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 # you may not use this file except in compliance with the License. |
|
7 # You may obtain a copy of the License at |
|
8 # |
|
9 # http://www.apache.org/licenses/LICENSE-2.0 |
|
10 # |
|
11 # Unless required by applicable law or agreed to in writing, software |
|
12 # distributed under the License is distributed on an "AS IS" BASIS, |
|
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 # See the License for the specific language governing permissions and |
|
15 # limitations under the License. |
|
16 # |
|
17 |
|
18 """Logging utilities for use by applications. |
|
19 |
|
20 Classes defined here: |
|
21 AppLogsHandler: StreamHandler subclass |
|
22 """ |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 import logging |
|
29 import sys |
|
30 import types |
|
31 |
|
32 |
|
33 NEWLINE_REPLACEMENT = "\0" |
|
34 |
|
35 |
|
36 class AppLogsHandler(logging.StreamHandler): |
|
37 """Logging handler that will direct output to a persistent store of |
|
38 application logs. |
|
39 |
|
40 This handler will output log statements to stderr. This handler is |
|
41 automatically initialized and attached to the Python common logging library. |
|
42 """ |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 def __init__(self, stream=None): |
|
48 """Constructor. |
|
49 |
|
50 Args: |
|
51 # stream is optional. it defaults to sys.stderr. |
|
52 stream: destination for output |
|
53 """ |
|
54 logging.StreamHandler.__init__(self, stream) |
|
55 |
|
56 def close(self): |
|
57 """Closes the stream. |
|
58 |
|
59 This implementation based on the implementation of FileHandler.close().""" |
|
60 self.flush() |
|
61 self.stream.close() |
|
62 logging.StreamHandler.close(self) |
|
63 |
|
64 def emit(self, record): |
|
65 """Emit a record. |
|
66 |
|
67 This implementation is based on the implementation of |
|
68 StreamHandler.emit().""" |
|
69 try: |
|
70 message = self._AppLogsMessage(record) |
|
71 self.stream.write(message.encode("UTF-8")) |
|
72 self.flush() |
|
73 except (KeyboardInterrupt, SystemExit): |
|
74 raise |
|
75 except: |
|
76 self.handleError(record) |
|
77 |
|
78 def _AppLogsMessage(self, record): |
|
79 """Converts the log record into a log line.""" |
|
80 |
|
81 message = self.format(record).replace("\n", NEWLINE_REPLACEMENT) |
|
82 return "LOG %d %d %s\n" % (self._AppLogsLevel(record.levelno), |
|
83 long(record.created * 1000 * 1000), |
|
84 message) |
|
85 |
|
86 def _AppLogsLevel(self, level): |
|
87 """Converts the logging level used in Python to the API logging level""" |
|
88 if level >= logging.CRITICAL: |
|
89 return 4 |
|
90 elif level >= logging.ERROR: |
|
91 return 3 |
|
92 elif level >= logging.WARNING: |
|
93 return 2 |
|
94 elif level >= logging.INFO: |
|
95 return 1 |
|
96 else: |
|
97 return 0 |