Skip to content

Commit b9e7829

Browse files
authored
Prioritize logger body in exception details message (#34020)
* exc * Update CHANGELOG.md * comments * Update _utils.py * Update _utils.py * mypy * mypy
1 parent d4a3e7c commit b9e7829

File tree

3 files changed

+94
-13
lines changed

3 files changed

+94
-13
lines changed

sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
### Bugs Fixed
1515

16+
- Update exception details messsage based on `LogRecord` body
17+
([#34020](https://github.com/Azure/azure-sdk-for-python/pull/34020))
18+
1619
### Other Changes
1720

1821
## 1.0.0b21 (2024-01-16)

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/logs/_exporter.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,10 @@ def _convert_log_to_envelope(log_data: LogData) -> TelemetryItem:
132132
stack_trace = log_record.attributes.get(SpanAttributes.EXCEPTION_STACKTRACE)
133133
severity_level = _get_severity_level(log_record.severity_number)
134134

135-
if not log_record.body:
136-
log_record.body = "n/a"
137-
138135
# Event telemetry
139136
if _log_data_is_event(log_data):
137+
if not log_record.body:
138+
log_record.body = "n/a"
140139
_set_statsbeat_custom_events_feature()
141140
envelope.name = 'Microsoft.ApplicationInsights.Event'
142141
data = TelemetryEventData(
@@ -150,11 +149,16 @@ def _convert_log_to_envelope(log_data: LogData) -> TelemetryItem:
150149
has_full_stack = stack_trace is not None
151150
if not exc_type:
152151
exc_type = "Exception"
153-
if not exc_message:
154-
exc_message = "Exception"
152+
# Log body takes priority for message
153+
if log_record.body:
154+
message = str(log_record.body)
155+
elif exc_message:
156+
message = exc_message # type: ignore
157+
else:
158+
message = "Exception"
155159
exc_details = TelemetryExceptionDetails(
156-
type_name=str(exc_type)[:1024],
157-
message=str(exc_message)[:32768],
160+
type_name=str(exc_type)[:1024], # type: ignore
161+
message=str(message)[:32768],
158162
has_full_stack=has_full_stack,
159163
stack=str(stack_trace)[:32768],
160164
)
@@ -166,6 +170,8 @@ def _convert_log_to_envelope(log_data: LogData) -> TelemetryItem:
166170
# pylint: disable=line-too-long
167171
envelope.data = MonitorBase(base_data=data, base_type="ExceptionData")
168172
else: # Message telemetry
173+
if not log_record.body:
174+
log_record.body = "n/a"
169175
envelope.name = _MESSAGE_ENVELOPE_NAME
170176
# pylint: disable=line-too-long
171177
# Severity number: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber

sdk/monitor/azure-monitor-opentelemetry-exporter/tests/logs/test_logs.py

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,57 @@ def setUpClass(cls):
143143
),
144144
InstrumentationScope("test_name"),
145145
)
146-
cls._exc_data_blank = _logs.LogData(
146+
cls._exc_data_with_exc_body = _logs.LogData(
147147
_logs.LogRecord(
148148
timestamp = 1646865018558419456,
149149
trace_id = 125960616039069540489478540494783893221,
150150
span_id = 2909973987304607650,
151151
severity_text = "EXCEPTION",
152152
trace_flags = None,
153153
severity_number = SeverityNumber.FATAL,
154-
body = "Test message",
154+
body = Exception("test exception message"),
155+
resource = Resource.create(
156+
attributes={"asd":"test_resource"}
157+
),
158+
attributes={
159+
"test": "attribute",
160+
SpanAttributes.EXCEPTION_TYPE: "ZeroDivisionError",
161+
SpanAttributes.EXCEPTION_MESSAGE: "division by zero",
162+
SpanAttributes.EXCEPTION_STACKTRACE: 'Traceback (most recent call last):\n File "test.py", line 38, in <module>\n raise ZeroDivisionError()\nZeroDivisionError\n'
163+
},
164+
),
165+
InstrumentationScope("test_name"),
166+
)
167+
cls._exc_data_blank_exception = _logs.LogData(
168+
_logs.LogRecord(
169+
timestamp = 1646865018558419456,
170+
trace_id = 125960616039069540489478540494783893221,
171+
span_id = 2909973987304607650,
172+
severity_text = "EXCEPTION",
173+
trace_flags = None,
174+
severity_number = SeverityNumber.FATAL,
175+
body = "test exception",
176+
resource = Resource.create(
177+
attributes={"asd":"test_resource"}
178+
),
179+
attributes={
180+
"test": "attribute",
181+
SpanAttributes.EXCEPTION_TYPE: "",
182+
SpanAttributes.EXCEPTION_MESSAGE: "",
183+
SpanAttributes.EXCEPTION_STACKTRACE: ""
184+
},
185+
),
186+
InstrumentationScope("test_name"),
187+
)
188+
cls._exc_data_empty = _logs.LogData(
189+
_logs.LogRecord(
190+
timestamp = 1646865018558419456,
191+
trace_id = 125960616039069540489478540494783893221,
192+
span_id = 2909973987304607650,
193+
severity_text = "EXCEPTION",
194+
trace_flags = None,
195+
severity_number = SeverityNumber.FATAL,
196+
body = "",
155197
resource = Resource.create(
156198
attributes={"asd":"test_resource"}
157199
),
@@ -304,7 +346,7 @@ def test_log_to_envelope_log_empty(self):
304346
self.assertEqual(envelope.data.base_type, 'MessageData')
305347
self.assertEqual(envelope.data.base_data.message, "n/a")
306348

307-
def test_log_to_envelope_exception(self):
349+
def test_log_to_envelope_exception_with_string_message(self):
308350
exporter = self._exporter
309351
envelope = exporter._log_to_envelope(self._exc_data)
310352
record = self._log_data.log_record
@@ -315,13 +357,28 @@ def test_log_to_envelope_exception(self):
315357
self.assertEqual(envelope.data.base_data.properties["test"], "attribute")
316358
self.assertEqual(len(envelope.data.base_data.exceptions), 1)
317359
self.assertEqual(envelope.data.base_data.exceptions[0].type_name, "ZeroDivisionError")
318-
self.assertEqual(envelope.data.base_data.exceptions[0].message, "division by zero")
360+
self.assertEqual(envelope.data.base_data.exceptions[0].message, "Test message")
361+
self.assertTrue(envelope.data.base_data.exceptions[0].has_full_stack)
362+
self.assertEqual(envelope.data.base_data.exceptions[0].stack, 'Traceback (most recent call last):\n File "test.py", line 38, in <module>\n raise ZeroDivisionError()\nZeroDivisionError\n')
363+
364+
def test_log_to_envelope_exception_with_exc_message(self):
365+
exporter = self._exporter
366+
envelope = exporter._log_to_envelope(self._exc_data_with_exc_body)
367+
record = self._log_data.log_record
368+
self.assertEqual(envelope.name, 'Microsoft.ApplicationInsights.Exception')
369+
self.assertEqual(envelope.time, ns_to_iso_str(record.timestamp))
370+
self.assertEqual(envelope.data.base_type, 'ExceptionData')
371+
self.assertEqual(envelope.data.base_data.severity_level, 4)
372+
self.assertEqual(envelope.data.base_data.properties["test"], "attribute")
373+
self.assertEqual(len(envelope.data.base_data.exceptions), 1)
374+
self.assertEqual(envelope.data.base_data.exceptions[0].type_name, "ZeroDivisionError")
375+
self.assertEqual(envelope.data.base_data.exceptions[0].message, "test exception message")
319376
self.assertTrue(envelope.data.base_data.exceptions[0].has_full_stack)
320377
self.assertEqual(envelope.data.base_data.exceptions[0].stack, 'Traceback (most recent call last):\n File "test.py", line 38, in <module>\n raise ZeroDivisionError()\nZeroDivisionError\n')
321378

322-
def test_log_to_envelope_exception_blank(self):
379+
def test_log_to_envelope_exception_empty(self):
323380
exporter = self._exporter
324-
envelope = exporter._log_to_envelope(self._exc_data_blank)
381+
envelope = exporter._log_to_envelope(self._exc_data_empty)
325382
record = self._log_data.log_record
326383
self.assertEqual(envelope.name, 'Microsoft.ApplicationInsights.Exception')
327384
self.assertEqual(envelope.time, ns_to_iso_str(record.timestamp))
@@ -334,6 +391,21 @@ def test_log_to_envelope_exception_blank(self):
334391
self.assertTrue(envelope.data.base_data.exceptions[0].has_full_stack)
335392
self.assertEqual(envelope.data.base_data.exceptions[0].stack, "")
336393

394+
def test_log_to_envelope_exception_with_blank_exception(self):
395+
exporter = self._exporter
396+
envelope = exporter._log_to_envelope(self._exc_data_blank_exception)
397+
record = self._log_data.log_record
398+
self.assertEqual(envelope.name, 'Microsoft.ApplicationInsights.Exception')
399+
self.assertEqual(envelope.time, ns_to_iso_str(record.timestamp))
400+
self.assertEqual(envelope.data.base_type, 'ExceptionData')
401+
self.assertEqual(envelope.data.base_data.severity_level, 4)
402+
self.assertEqual(envelope.data.base_data.properties["test"], "attribute")
403+
self.assertEqual(len(envelope.data.base_data.exceptions), 1)
404+
self.assertEqual(envelope.data.base_data.exceptions[0].type_name, "Exception")
405+
self.assertEqual(envelope.data.base_data.exceptions[0].message, "test exception")
406+
self.assertTrue(envelope.data.base_data.exceptions[0].has_full_stack)
407+
self.assertEqual(envelope.data.base_data.exceptions[0].stack, "")
408+
337409
def test_log_to_envelope_event(self):
338410
exporter = self._exporter
339411
envelope = exporter._log_to_envelope(self._log_data_event)

0 commit comments

Comments
 (0)