blob: 2382c0ebf6a0ebac25b0f015981c49b414d98439 [file] [log] [blame]
#
# Copyright 2016 the original author or authors.
#
# 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.
#
"""Setting up proper logging for Voltha"""
import logging
import logging.config
from collections import OrderedDict
import structlog
from structlog.stdlib import BoundLogger
try:
from thread import get_ident as _get_ident
except ImportError:
from dummy_thread import get_ident as _get_ident
DEFAULT_FLUENT_SERVER = 'localhost:24224'
class FluentRenderer(object):
def __call__(self, logger, name, event_dict):
# in order to keep structured log data in event_dict to be forwarded as
# is to the fluent logger, we need to pass it into the logger framework
# as the first positional argument.
args = (event_dict, )
kwargs = {}
return args, kwargs
class PlainRenderedOrderedDict(OrderedDict):
"""Our special version of OrderedDict that renders into string as a dict,
to make the log stream output cleaner.
"""
def __repr__(self, _repr_running={}):
'od.__repr__() <==> repr(od)'
call_key = id(self), _get_ident()
if call_key in _repr_running:
return '...'
_repr_running[call_key] = 1
try:
if not self:
return '{}'
return '{%s}' % ", ".join("%s: %s" % (k, v) for k, v in self.items())
finally:
del _repr_running[call_key]
def setup_logging(log_config):
"""
Set up logging such that:
- The primary logging entry method is structlog (see http://structlog.readthedocs.io/en/stable/index.html)
- By default, the logging backend is Python standard lib logger
- Alternatively, fluentd can be configured with to be the backend, providing direct
bridge to a fluent logging agent.
"""
def add_exc_info_flag_for_exception(logger, name, event_dict):
if name == 'exception':
event_dict['exc_info'] = True
return event_dict
# Configure standard logging
logging.config.dictConfig(log_config)
processors = [
add_exc_info_flag_for_exception,
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
FluentRenderer(),
]
structlog.configure(logger_factory=structlog.stdlib.LoggerFactory(),
context_class=PlainRenderedOrderedDict,
wrapper_class=BoundLogger,
processors=processors)
# Mark first line of log
log = structlog.get_logger()
log.info("first-line")
return log