Skip to content

Commit 21496e8

Browse files
docs: Clarify log processor error handling expectations
Add documentation to LogRecordProcessor, LogRecordExporter, and SimpleLogRecordProcessor explaining error handling responsibilities: - LogRecordProcessor: Clarifies that custom implementations must handle exceptions from exporter.export() to prevent application crashes - LogRecordExporter: Documents that export() may raise exceptions and processors are responsible for handling them - SimpleLogRecordProcessor: Highlights it as a reference implementation for proper error handling This addresses confusion where custom LogRecordProcessor implementations were not handling exceptions, causing unhandled exceptions to crash applications when network errors or timeouts occurred during export. Fixes #4724 Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent ba5fc05 commit 21496e8

2 files changed

Lines changed: 65 additions & 7 deletions

File tree

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,11 +293,43 @@ class LogRecordProcessor(abc.ABC):
293293
Log processors can be registered directly using
294294
:func:`LoggerProvider.add_log_record_processor` and they are invoked
295295
in the same order as they were registered.
296+
297+
Implementers of custom log processors should be aware of the following:
298+
299+
Error Handling
300+
--------------
301+
According to the OpenTelemetry error handling principles, the SDK should
302+
not throw unhandled exceptions at runtime. When implementing a custom
303+
``LogRecordProcessor``, it is the **processor's responsibility** to handle
304+
any exceptions that may be raised by the exporter's ``export()`` method.
305+
306+
The ``LogRecordExporter.export()`` method may raise exceptions (e.g.,
307+
network errors, timeouts). If these exceptions are not caught, they will
308+
propagate up and potentially crash the application.
309+
310+
Custom processor implementations should wrap exporter calls in a
311+
try/except block. See :class:`SimpleLogRecordProcessor` for a reference
312+
implementation::
313+
314+
def on_emit(self, log_record: ReadWriteLogRecord):
315+
try:
316+
self._exporter.export((log_record,))
317+
except Exception: # pylint: disable=broad-exception-caught
318+
logger.exception("Exception while exporting logs.")
319+
320+
The ``BatchLogRecordProcessor`` handles this implicitly since export
321+
operations occur in a background thread where exceptions cannot bubble
322+
up to the caller.
296323
"""
297324

298325
@abc.abstractmethod
299326
def on_emit(self, log_record: ReadWriteLogRecord):
300-
"""Emits the `ReadWriteLogRecord`"""
327+
"""Emits the ``ReadWriteLogRecord``.
328+
329+
Implementers should handle any exceptions raised during log processing
330+
to prevent application crashes. See the class docstring for details
331+
on error handling expectations.
332+
"""
301333

302334
@abc.abstractmethod
303335
def shutdown(self):

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,40 @@ class LogExportResult(enum.Enum):
7373

7474
class LogRecordExporter(abc.ABC):
7575
"""Interface for exporting logs.
76+
7677
Interface to be implemented by services that want to export logs received
7778
in their own format.
78-
To export data this MUST be registered to the :class`opentelemetry.sdk._logs.Logger` using a
79-
log processor.
79+
80+
To export data this MUST be registered to the :class:`opentelemetry.sdk._logs.Logger`
81+
using a log processor.
82+
83+
Important
84+
---------
85+
The ``export()`` method may raise exceptions (e.g., network errors,
86+
timeouts, serialization errors). It is the responsibility of the
87+
:class:`~opentelemetry.sdk._logs.LogRecordProcessor` calling this exporter
88+
to handle these exceptions appropriately to prevent application crashes.
89+
See :class:`~opentelemetry.sdk._logs.LogRecordProcessor` for guidance on
90+
implementing proper error handling.
8091
"""
8192

8293
@abc.abstractmethod
8394
def export(
8495
self, batch: Sequence[ReadableLogRecord]
8596
) -> LogRecordExportResult:
8697
"""Exports a batch of logs.
98+
8799
Args:
88-
batch: The list of `ReadableLogRecord` objects to be exported
100+
batch: The list of ``ReadableLogRecord`` objects to be exported.
101+
89102
Returns:
90-
The result of the export
103+
The result of the export.
104+
105+
Raises:
106+
Exception: This method may raise exceptions on network errors,
107+
timeouts, or other failures. Callers (i.e., log processors)
108+
should handle these exceptions to comply with OpenTelemetry
109+
error handling principles.
91110
"""
92111

93112
@abc.abstractmethod
@@ -141,8 +160,15 @@ class ConsoleLogExporter(ConsoleLogRecordExporter):
141160

142161

143162
class SimpleLogRecordProcessor(LogRecordProcessor):
144-
"""This is an implementation of LogRecordProcessor which passes
145-
received logs directly to the configured LogRecordExporter, as soon as they are emitted.
163+
"""Implementation of LogRecordProcessor that exports logs synchronously.
164+
165+
This processor passes received logs directly to the configured
166+
``LogRecordExporter`` as soon as they are emitted.
167+
168+
This class serves as a reference implementation for custom log processors,
169+
demonstrating proper error handling. Note how the ``on_emit`` method wraps
170+
the exporter call in a try/except block to prevent exceptions from
171+
propagating to the application.
146172
"""
147173

148174
def __init__(self, exporter: LogRecordExporter):

0 commit comments

Comments
 (0)