Describe the bug
_convert_log_to_envelope() in azure/monitor/opentelemetry/exporter/export/logs/_exporter.py never accesses readable_log_record.instrumentation_scope. The Python logger name (which the OTel SDK correctly records as InstrumentationScope.name per the OTel Logs Data Model spec) is silently dropped when converting log records to Application Insights envelopes.
This means customDimensions in the App Insights traces table has no field identifying which logger produced the record, making it impossible to filter logs by source module in KQL queries.
Consistency gap across exporter types in this package
| Exporter |
Uses instrumentation_scope? |
References |
Trace (export/trace/_exporter.py) |
Yes |
span.instrumentation_scope.name at lines 516-517, 591, 596, 605, 607 |
Metrics (export/metrics/_exporter.py) |
Yes |
scope.name at line 243 for metric namespace |
Log (export/logs/_exporter.py) |
No |
0 references to instrumentation_scope in entire logs/ directory |
OTLP Log (reference impl in opentelemetry-python) |
Yes |
readable_log.instrumentation_scope at line 80 of _log_encoder/__init__.py |
Same bug was reported (and fixed) for .NET
In .NET, LogRecord.CategoryName is the equivalent of Python's InstrumentationScope.name. Both issues confirmed the Azure Monitor exporter was dropping this field.
Expected behavior
InstrumentationScope.name should be mapped to a customDimensions property (e.g., CategoryName to match .NET convention, or LoggerName) on all log envelope types (Message, Exception, Event).
Actual behavior
InstrumentationScope.name is completely ignored. The field is available on ReadableLogRecord.instrumentation_scope (confirmed in OTel SDK source at opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py line 186) but never read by the Azure Monitor log exporter.
How the data flows (and where it breaks)
- Python logging -> OTel LogRecord:
LoggingHandler.emit() calls get_logger(record.name), setting InstrumentationScope.name correctly (e.g., myapp.services.graph).
record.name excluded from attributes by design: OTel's _RESERVED_ATTRS filters it out since it belongs in InstrumentationScope, not in log record attributes.
- Pipeline preserves it:
BatchLogRecordProcessor carries instrumentation_scope through on ReadableLogRecord.
- Azure Monitor exporter ignores it:
_convert_log_to_envelope() reads .log_record and .resource but never .instrumentation_scope. The logger name is lost.
Reproduction
import logging
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import LoggingHandler
from azure.monitor.opentelemetry.exporter import AzureMonitorLogExporter
log_provider = LoggerProvider()
log_exporter = AzureMonitorLogExporter(connection_string="InstrumentationKey=...")
log_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
set_logger_provider(log_provider)
handler = LoggingHandler(level=logging.INFO, logger_provider=log_provider)
logging.getLogger().addHandler(handler)
# This logger name ("myapp.services") will be lost in App Insights
logger = logging.getLogger("myapp.services")
logger.info("Test message")
# In App Insights traces table: customDimensions has no LoggerName/CategoryName field
Suggested fix
In _convert_log_to_envelope(), after building the properties dict from log_record.attributes:
scope = readable_log_record.instrumentation_scope
if scope is not None and scope.name:
properties.setdefault("CategoryName", str(scope.name))
Using setdefault ensures that if a user explicitly sets a CategoryName attribute, it takes precedence.
Environment
- azure-monitor-opentelemetry-exporter: 1.0.0b36
- opentelemetry-sdk: 1.33.1
- Python: 3.11.15
- OS: Linux (Azure Container Apps)
Describe the bug
_convert_log_to_envelope()inazure/monitor/opentelemetry/exporter/export/logs/_exporter.pynever accessesreadable_log_record.instrumentation_scope. The Python logger name (which the OTel SDK correctly records asInstrumentationScope.nameper the OTel Logs Data Model spec) is silently dropped when converting log records to Application Insights envelopes.This means
customDimensionsin the App Insightstracestable has no field identifying which logger produced the record, making it impossible to filter logs by source module in KQL queries.Consistency gap across exporter types in this package
instrumentation_scope?export/trace/_exporter.py)span.instrumentation_scope.nameat lines 516-517, 591, 596, 605, 607export/metrics/_exporter.py)scope.nameat line 243 for metric namespaceexport/logs/_exporter.py)instrumentation_scopein entirelogs/directoryopentelemetry-python)readable_log.instrumentation_scopeat line 80 of_log_encoder/__init__.pySame bug was reported (and fixed) for .NET
In .NET,
LogRecord.CategoryNameis the equivalent of Python'sInstrumentationScope.name. Both issues confirmed the Azure Monitor exporter was dropping this field.Expected behavior
InstrumentationScope.nameshould be mapped to acustomDimensionsproperty (e.g.,CategoryNameto match .NET convention, orLoggerName) on all log envelope types (Message, Exception, Event).Actual behavior
InstrumentationScope.nameis completely ignored. The field is available onReadableLogRecord.instrumentation_scope(confirmed in OTel SDK source atopentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.pyline 186) but never read by the Azure Monitor log exporter.How the data flows (and where it breaks)
LoggingHandler.emit()callsget_logger(record.name), settingInstrumentationScope.namecorrectly (e.g.,myapp.services.graph).record.nameexcluded from attributes by design: OTel's_RESERVED_ATTRSfilters it out since it belongs inInstrumentationScope, not in log record attributes.BatchLogRecordProcessorcarriesinstrumentation_scopethrough onReadableLogRecord._convert_log_to_envelope()reads.log_recordand.resourcebut never.instrumentation_scope. The logger name is lost.Reproduction
Suggested fix
In
_convert_log_to_envelope(), after building thepropertiesdict fromlog_record.attributes:Using
setdefaultensures that if a user explicitly sets aCategoryNameattribute, it takes precedence.Environment