Skip to content

Commit b8b39b3

Browse files
committed
Make more changes
1 parent a48b45a commit b8b39b3

File tree

4 files changed

+19
-17
lines changed

4 files changed

+19
-17
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
([#4782](https://github.com/open-telemetry/opentelemetry-python/pull/4782))
1919
- semantic-conventions: Bump to 1.38.0
2020
([#4791](https://github.com/open-telemetry/opentelemetry-python/pull/4791))
21+
- Prevent possible endless recursion from happening in `SimpleLogRecordProcessor.on_emit`,
22+
([#4799](https://github.com/open-telemetry/opentelemetry-python/pull/4799)).
2123

2224
## Version 1.38.0/0.59b0 (2025-10-16)
2325

opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import enum
1818
import logging
1919
import sys
20-
from contextvars import ContextVar
20+
import traceback
2121
from os import environ, linesep
2222
from typing import IO, Callable, Optional, Sequence
2323

@@ -119,18 +119,23 @@ class SimpleLogRecordProcessor(LogRecordProcessor):
119119
"""
120120

121121
def __init__(self, exporter: LogExporter):
122-
self._emit_executing = ContextVar("var", default=False)
123122
self._exporter = exporter
124123
self._shutdown = False
125124

126125
def on_emit(self, log_data: LogData):
127126
# Prevent entering a recursive loop.
128-
if self._emit_executing.get():
127+
if (
128+
sum(
129+
item.name == "on_emit"
130+
and item.filename.endswith("export/__init__.py")
131+
for item in traceback.extract_stack()
132+
)
133+
> 3
134+
):
129135
_propagate_false_logger.warning(
130136
"SimpleLogRecordProcessor.on_emit has entered a recursive loop. Dropping log and exiting the loop."
131137
)
132138
return
133-
emit_token = self._emit_executing.set(True)
134139
suppress_token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True))
135140
try:
136141
if self._shutdown:
@@ -142,7 +147,6 @@ def on_emit(self, log_data: LogData):
142147
except Exception: # pylint: disable=broad-exception-caught
143148
_logger.exception("Exception while exporting logs.")
144149
finally:
145-
self._emit_executing.reset(emit_token)
146150
detach(suppress_token)
147151

148152
def shutdown(self):

opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,16 +201,12 @@ def _export(self, batch_strategy: BatchExportStrategy) -> None:
201201

202202
def emit(self, data: Telemetry) -> None:
203203
if self._shutdown:
204-
_logger.info(
205-
"Shutdown called, ignoring %s.", self._exporting
206-
)
204+
_logger.info("Shutdown called, ignoring %s.", self._exporting)
207205
return
208206
if self._pid != os.getpid():
209207
self._bsp_reset_once.do_once(self._at_fork_reinit)
210208
if len(self._queue) == self._max_queue_size:
211-
_logger.warning(
212-
"Queue full, dropping %s.", self._exporting
213-
)
209+
_logger.warning("Queue full, dropping %s.", self._exporting)
214210
# This will drop a log from the right side if the queue is at _max_queue_size.
215211
self._queue.appendleft(data)
216212
if len(self._queue) >= self._max_export_batch_size:

opentelemetry-sdk/tests/logs/test_export.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# pylint: disable=protected-access
1616
import logging
1717
import os
18-
import random
18+
import sys
1919
import time
2020
import unittest
2121
from concurrent.futures import ThreadPoolExecutor
@@ -64,7 +64,7 @@
6464

6565
class TestSimpleLogRecordProcessor(unittest.TestCase):
6666
@mark.skipif(
67-
version_info=(3, 13),
67+
sys.version_info == (3, 13),
6868
reason="This will fail on 3.13 due to https://github.com/python/cpython/pull/131812 which prevents recursive log messages but was later rolled back.",
6969
)
7070
def test_simple_log_record_processor_doesnt_enter_recursive_loop(self):
@@ -73,9 +73,8 @@ def shutdown(self):
7373
pass
7474

7575
def export(self, batch: Sequence[LogData]):
76-
raise ValueError(
77-
"Exception raised ! {}".format(random.randint(1, 10000))
78-
)
76+
logger = logging.getLogger("any logger..")
77+
logger.warning("Something happened.")
7978

8079
exporter = Exporter()
8180
logger_provider = LoggerProvider()
@@ -84,7 +83,8 @@ def export(self, batch: Sequence[LogData]):
8483
)
8584
root_logger = logging.getLogger()
8685
# Add the OTLP handler to the root logger like is done in auto instrumentation.
87-
# This means logs generated from within SimpleLogRecordProcessor.on_emit are sent back to SimpleLogRecordProcessor.on_emit
86+
# This causes logs generated from within SimpleLogRecordProcessor.on_emit (such as the above log in export)
87+
# to be sent back to SimpleLogRecordProcessor.on_emit
8888
handler = LoggingHandler(
8989
level=logging.DEBUG, logger_provider=logger_provider
9090
)

0 commit comments

Comments
 (0)