Logging instr hook (#1117)

This commit is contained in:
natashz
2022-06-09 11:42:54 +03:00
committed by GitHub
parent 0bd8e4c7fd
commit ad15f7bc82
3 changed files with 44 additions and 3 deletions

View File

@ -15,11 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- cleanup type hints for textmap `Getter` and `Setter` classes
([1106](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1106))
### Added
- `opentelemetry-instrumentation-remoulade` Initial release
([#1082](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1082))
### Added
- `opentelemetry-instrumentation-logging` add log hook support
([#1117](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1117))
- `opentelemetry-instrumentation-remoulade` Initial release
([#1082](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1082))
- Added `opentelemetry-instrumention-confluent-kafka`
([#1111](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1111))

View File

@ -55,6 +55,10 @@ class LoggingInstrumentor(BaseInstrumentor): # pylint: disable=empty-docstring
{DEFAULT_LOGGING_FORMAT}
def log_hook(span: Span, record: LogRecord):
if span and span.is_recording():
record.custom_user_attribute_from_log_hook = "some-value"
Args:
tracer_provider: Tracer provider instance that can be used to fetch a tracer.
set_logging_format: When set to True, it calls logging.basicConfig() and sets a logging format.
@ -66,11 +70,13 @@ class LoggingInstrumentor(BaseInstrumentor): # pylint: disable=empty-docstring
logging.WARN
logging.ERROR
logging.FATAL
log_hook: execute custom logic when record is created
See `BaseInstrumentor`
"""
_old_factory = None
_log_hook = None
def instrumentation_dependencies(self) -> Collection[str]:
return _instruments
@ -80,6 +86,7 @@ class LoggingInstrumentor(BaseInstrumentor): # pylint: disable=empty-docstring
provider = kwargs.get("tracer_provider", None) or get_tracer_provider()
old_factory = logging.getLogRecordFactory()
LoggingInstrumentor._old_factory = old_factory
LoggingInstrumentor._log_hook = kwargs.get("log_hook", None)
service_name = None
@ -107,6 +114,14 @@ class LoggingInstrumentor(BaseInstrumentor): # pylint: disable=empty-docstring
if ctx != INVALID_SPAN_CONTEXT:
record.otelSpanID = format(ctx.span_id, "016x")
record.otelTraceID = format(ctx.trace_id, "032x")
if callable(LoggingInstrumentor._log_hook):
try:
LoggingInstrumentor._log_hook( # pylint: disable=E1102
span, record
)
except Exception: # pylint: disable=W0703
pass
return record
logging.setLogRecordFactory(record_factory)

View File

@ -64,6 +64,10 @@ class TestLoggingInstrumentorProxyTracerProvider(TestBase):
self.assertEqual(record.otelServiceName, "")
def log_hook(span, record):
record.custom_user_attribute_from_log_hook = "some-value"
class TestLoggingInstrumentor(TestBase):
@pytest.fixture(autouse=True)
def inject_fixtures(self, caplog):
@ -150,6 +154,27 @@ class TestLoggingInstrumentor(TestBase):
format="%(message)s span_id=%(otelSpanID)s", level=logging.WARNING
)
def test_log_hook(self):
LoggingInstrumentor().uninstrument()
LoggingInstrumentor().instrument(
set_logging_format=True,
log_hook=log_hook,
)
with self.tracer.start_as_current_span("s1") as span:
span_id = format(span.get_span_context().span_id, "016x")
trace_id = format(span.get_span_context().trace_id, "032x")
with self.caplog.at_level(level=logging.INFO):
logger = logging.getLogger("test logger")
logger.info("hello")
self.assertEqual(len(self.caplog.records), 1)
record = self.caplog.records[0]
self.assertEqual(record.otelSpanID, span_id)
self.assertEqual(record.otelTraceID, trace_id)
self.assertEqual(record.otelServiceName, "unknown_service")
self.assertEqual(
record.custom_user_attribute_from_log_hook, "some-value"
)
def test_uninstrumented(self):
with self.tracer.start_as_current_span("s1") as span:
span_id = format(span.get_span_context().span_id, "016x")