Martin Blanchard pushed to branch mablanch/23-new-logging at BuildGrid / buildgrid
Commits:
-
0550b93a
by Martin Blanchard at 2018-11-12T14:39:46Z
-
b7029a51
by Martin Blanchard at 2018-11-12T14:40:36Z
-
3984c93a
by Martin Blanchard at 2018-11-12T14:40:38Z
3 changed files:
Changes:
| ... | ... | @@ -27,6 +27,7 @@ import os |
| 27 | 27 |
import click
|
| 28 | 28 |
import grpc
|
| 29 | 29 |
|
| 30 |
+from buildgrid.settings import LOG_RECORD_FORMAT
|
|
| 30 | 31 |
from buildgrid.utils import read_file
|
| 31 | 32 |
|
| 32 | 33 |
CONTEXT_SETTINGS = dict(auto_envvar_prefix='BUILDGRID')
|
| ... | ... | @@ -139,10 +140,12 @@ class BuildGridCLI(click.MultiCommand): |
| 139 | 140 |
|
| 140 | 141 |
|
| 141 | 142 |
@click.command(cls=BuildGridCLI, context_settings=CONTEXT_SETTINGS)
|
| 143 |
+@click.option('--no-print', is_flag=True, show_default=True,
|
|
| 144 |
+ help="Do not print log records to stdout/stderr.")
|
|
| 142 | 145 |
@click.option('-v', '--verbose', count=True,
|
| 143 | 146 |
help='Increase log verbosity level.')
|
| 144 | 147 |
@pass_context
|
| 145 |
-def cli(context, verbose):
|
|
| 148 |
+def cli(context, no_print, verbose):
|
|
| 146 | 149 |
"""BuildGrid App"""
|
| 147 | 150 |
logger = logging.getLogger()
|
| 148 | 151 |
|
| ... | ... | @@ -152,14 +155,15 @@ def cli(context, verbose): |
| 152 | 155 |
for log_filter in logger.filters[:]:
|
| 153 | 156 |
logger.removeFilter(log_filter)
|
| 154 | 157 |
|
| 155 |
- logging.basicConfig(
|
|
| 156 |
- format='%(asctime)s:%(name)32.32s][%(levelname)5.5s]: %(message)s')
|
|
| 157 |
- |
|
| 158 |
+ # Do not register a stream handler if no-print is requested:
|
|
| 159 |
+ if not no_print:
|
|
| 160 |
+ logging.basicConfig(format=LOG_RECORD_FORMAT)
|
|
| 161 |
+ else:
|
|
| 162 |
+ logging.basicConfig(format=LOG_RECORD_FORMAT,
|
|
| 163 |
+ handlers=[logging.NullHandler()])
|
|
| 158 | 164 |
if verbose == 1:
|
| 159 | 165 |
logger.setLevel(logging.WARNING)
|
| 160 | 166 |
elif verbose == 2:
|
| 161 | 167 |
logger.setLevel(logging.INFO)
|
| 162 | 168 |
elif verbose >= 3:
|
| 163 | 169 |
logger.setLevel(logging.DEBUG)
|
| 164 |
- else:
|
|
| 165 |
- logger.setLevel(logging.ERROR)
|
| ... | ... | @@ -16,10 +16,12 @@ |
| 16 | 16 |
import asyncio
|
| 17 | 17 |
from concurrent import futures
|
| 18 | 18 |
import logging
|
| 19 |
+from logging.handlers import QueueHandler
|
|
| 19 | 20 |
import os
|
| 20 | 21 |
import time
|
| 21 | 22 |
|
| 22 | 23 |
import grpc
|
| 24 |
+import janus
|
|
| 23 | 25 |
|
| 24 | 26 |
from buildgrid.server.cas.service import ByteStreamService, ContentAddressableStorageService
|
| 25 | 27 |
from buildgrid.server.actioncache.service import ActionCacheService
|
| ... | ... | @@ -54,6 +56,10 @@ class BuildGridServer: |
| 54 | 56 |
|
| 55 | 57 |
self.__main_loop = asyncio.get_event_loop()
|
| 56 | 58 |
self.__monitoring_task = None
|
| 59 |
+ self.__logging_task = None
|
|
| 60 |
+ |
|
| 61 |
+ self.__logging_queue = janus.Queue(loop=self.__main_loop)
|
|
| 62 |
+ self.__logging_handler = None
|
|
| 57 | 63 |
|
| 58 | 64 |
self._execution_service = None
|
| 59 | 65 |
self._bots_service = None
|
| ... | ... | @@ -72,8 +78,13 @@ class BuildGridServer: |
| 72 | 78 |
"""
|
| 73 | 79 |
self.__grpc_server.start()
|
| 74 | 80 |
|
| 81 |
+ self._setup_logging_handler()
|
|
| 82 |
+ self.__logging_task = asyncio.ensure_future(
|
|
| 83 |
+ self._logging_worker(), loop=self.__main_loop)
|
|
| 84 |
+ |
|
| 75 | 85 |
self.__monitoring_task = asyncio.ensure_future(
|
| 76 | 86 |
self._monitoring_worker(period=MONITORING_PERIOD), loop=self.__main_loop)
|
| 87 |
+ |
|
| 77 | 88 |
self.__main_loop.run_forever()
|
| 78 | 89 |
|
| 79 | 90 |
def stop(self, grace=0):
|
| ... | ... | @@ -84,6 +95,8 @@ class BuildGridServer: |
| 84 | 95 |
"""
|
| 85 | 96 |
if self.__monitoring_task is not None:
|
| 86 | 97 |
self.__monitoring_task.cancel()
|
| 98 |
+ if self.__logging_task is not None:
|
|
| 99 |
+ self.__logging_task.cancel()
|
|
| 87 | 100 |
|
| 88 | 101 |
self.__grpc_server.stop(grace)
|
| 89 | 102 |
|
| ... | ... | @@ -205,6 +218,25 @@ class BuildGridServer: |
| 205 | 218 |
|
| 206 | 219 |
# --- Private API ---
|
| 207 | 220 |
|
| 221 |
+ def _setup_logging_handler(self):
|
|
| 222 |
+ self.__logging_handler = QueueHandler(self.__logging_queue.sync_q)
|
|
| 223 |
+ |
|
| 224 |
+ root_logger = logging.getLogger()
|
|
| 225 |
+ root_logger.addHandler(self.__logging_handler)
|
|
| 226 |
+ |
|
| 227 |
+ async def _logging_worker(self):
|
|
| 228 |
+ while True:
|
|
| 229 |
+ try:
|
|
| 230 |
+ log_record = await self.__logging_queue.async_q.get()
|
|
| 231 |
+ |
|
| 232 |
+ print(log_record)
|
|
| 233 |
+ |
|
| 234 |
+ except asyncio.CancelledError:
|
|
| 235 |
+ break
|
|
| 236 |
+ |
|
| 237 |
+ if len(asyncio.all_tasks(loop=self.__main_loop)) <= 1:
|
|
| 238 |
+ self.__main_loop.stop()
|
|
| 239 |
+ |
|
| 208 | 240 |
async def _monitoring_worker(self, period=1):
|
| 209 | 241 |
while True:
|
| 210 | 242 |
try:
|
| ... | ... | @@ -229,4 +261,5 @@ class BuildGridServer: |
| 229 | 261 |
except asyncio.CancelledError:
|
| 230 | 262 |
break
|
| 231 | 263 |
|
| 232 |
- self.__main_loop.stop()
|
|
| 264 |
+ if len(asyncio.all_tasks(loop=self.__main_loop)) <= 1:
|
|
| 265 |
+ self.__main_loop.stop()
|
| ... | ... | @@ -24,3 +24,8 @@ HASH_LENGTH = HASH().digest_size * 2 |
| 24 | 24 |
|
| 25 | 25 |
# Period, in seconds, for the monitoring cycle:
|
| 26 | 26 |
MONITORING_PERIOD = 5.0
|
| 27 |
+ |
|
| 28 |
+# String format for log records:
|
|
| 29 |
+LOG_RECORD_FORMAT = '%(asctime)s:%(name)36.36s][%(levelname)5.5s]: %(message)s'
|
|
| 30 |
+# The different log record attributes are documented here:
|
|
| 31 |
+# https://docs.python.org/3/library/logging.html#logrecord-attributes
|
