mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 20:52:57 +08:00
Logging instr hook (#1117)
This commit is contained in:
@ -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))
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
Reference in New Issue
Block a user