Skip to content

Commit bd7a7df

Browse files
committed
simplify try logic
1 parent 5eeb369 commit bd7a7df

File tree

2 files changed

+57
-94
lines changed

2 files changed

+57
-94
lines changed

scout_apm_logging/handler.py

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,28 @@
1212

1313

1414
class ScoutOtelHandler(logging.Handler):
15-
# Flag to prevent multiple initializations
16-
_class_initialized = False
1715
_initialization_lock = threading.Lock()
16+
otel_handler = None
1817

1918
def __init__(self, service_name):
2019
super().__init__()
2120
self.logger_provider = None
22-
self.otel_handler = None
2321
self.service_name = service_name
2422
self._handling_log = threading.local()
2523
self._initialized = False
2624
self._initializing = False
2725

2826
def _initialize(self):
2927
with self._initialization_lock:
30-
if ScoutOtelHandler._class_initialized:
28+
if ScoutOtelHandler.otel_handler:
3129
return
3230

3331
self.service_name = self._get_service_name(self.service_name)
3432
self.ingest_key = self._get_ingest_key()
3533
self.endpoint = self._get_endpoint()
36-
self.setup_logging()
37-
ScoutOtelHandler._class_initialized = True
34+
self.setup_otel_handler()
3835

39-
def setup_logging(self):
36+
def setup_otel_handler(self):
4037
self.logger_provider = LoggerProvider(
4138
resource=Resource.create(
4239
{
@@ -55,62 +52,57 @@ def setup_logging(self):
5552
BatchLogRecordProcessor(otlp_exporter)
5653
)
5754

58-
self.otel_handler = LoggingHandler(
55+
ScoutOtelHandler.otel_handler = LoggingHandler(
5956
level=logging.NOTSET, logger_provider=self.logger_provider
6057
)
6158

6259
def emit(self, record):
63-
try:
64-
# Initialize here to ensure that required configuration variables are loaded
65-
if not ScoutOtelHandler._class_initialized:
66-
try:
67-
self._initialize()
68-
except Exception as e:
69-
print(f"Failed to initialize ScoutOtelHandler: {e}")
70-
return
71-
72-
if getattr(self._handling_log, "value", False):
73-
# We're already handling a log message, don't get the TrackedRequest
74-
return self.otel_handler.emit(record)
75-
76-
self._handling_log.value = True
77-
scout_request = TrackedRequest.instance()
78-
79-
if scout_request:
80-
operation_detail = get_operation_detail(scout_request)
81-
if operation_detail:
82-
setattr(
83-
record,
84-
operation_detail.entrypoint_attribute,
85-
operation_detail.name,
86-
)
87-
88-
# Add Scout-specific attributes to the log record
89-
record.scout_request_id = scout_request.request_id
90-
record.scout_start_time = scout_request.start_time.isoformat()
91-
# Add duration if the request is completed
92-
if scout_request.end_time:
93-
record.scout_end_time = scout_request.end_time.isoformat()
94-
record.scout_duration = (
95-
scout_request.end_time - scout_request.start_time
96-
).total_seconds()
97-
98-
setattr(record, "service.name", self.service_name)
99-
100-
# Add tags
101-
for key, value in scout_request.tags.items():
102-
setattr(record, f"scout_tag_{key}", value)
103-
104-
# Add the current span's operation if available
105-
current_span = scout_request.current_span()
106-
if current_span:
107-
record.scout_current_operation = current_span.operation
108-
109-
self.otel_handler.emit(record)
110-
except Exception as e:
111-
print(f"Error in ScoutOtelHandler.emit: {e}")
112-
finally:
113-
self._handling_log.value = False
60+
if not ScoutOtelHandler.otel_handler:
61+
try:
62+
self._initialize()
63+
except Exception as e:
64+
print(f"Failed to initialize ScoutOtelHandler: {e}")
65+
return
66+
67+
if getattr(self._handling_log, "value", False):
68+
# We're already handling a log message, don't get the TrackedRequest
69+
return ScoutOtelHandler.otel_handler.emit(record)
70+
71+
self._handling_log.value = True
72+
scout_request = TrackedRequest.instance()
73+
74+
if scout_request:
75+
operation_detail = get_operation_detail(scout_request)
76+
if operation_detail:
77+
setattr(
78+
record,
79+
operation_detail.entrypoint_attribute,
80+
operation_detail.name,
81+
)
82+
83+
# Add Scout-specific attributes to the log record
84+
record.scout_request_id = scout_request.request_id
85+
record.scout_start_time = scout_request.start_time.isoformat()
86+
# Add duration if the request is completed
87+
if scout_request.end_time:
88+
record.scout_end_time = scout_request.end_time.isoformat()
89+
record.scout_duration = (
90+
scout_request.end_time - scout_request.start_time
91+
).total_seconds()
92+
93+
setattr(record, "service.name", self.service_name)
94+
95+
# Add tags
96+
for key, value in scout_request.tags.items():
97+
setattr(record, f"scout_tag_{key}", value)
98+
99+
# Add the current span's operation if available
100+
current_span = scout_request.current_span()
101+
if current_span:
102+
record.scout_current_operation = current_span.operation
103+
104+
ScoutOtelHandler.otel_handler.emit(record)
105+
self._handling_log.value = False
114106

115107
def close(self):
116108
if self.logger_provider:

tests/unit/test_handler.py

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
@pytest.fixture
1010
def otel_scout_handler():
1111
# Reset class initialization state
12-
ScoutOtelHandler._class_initialized = False
12+
ScoutOtelHandler.otel_handler = None
1313

1414
with patch("scout_apm_logging.handler.scout_config") as mock_scout_config, patch(
1515
"scout_apm_logging.handler.OTLPLogExporter"
@@ -46,7 +46,7 @@ def test_emit_with_scout_request(mock_tracked_request, otel_scout_handler):
4646
]
4747
mock_tracked_request.instance.return_value = mock_request
4848

49-
with patch.object(otel_scout_handler, "otel_handler") as mock_otel_handler:
49+
with patch.object(ScoutOtelHandler, "otel_handler") as mock_otel_handler:
5050
record = logging.LogRecord(
5151
name="test",
5252
level=logging.INFO,
@@ -81,7 +81,7 @@ def test_emit_when_scout_request_contains_operation(
8181
mock_request.operation = MagicMock().return_value = "Controller/foobar"
8282
mock_tracked_request.instance.return_value = mock_request
8383

84-
with patch.object(otel_scout_handler, "otel_handler") as mock_otel_handler:
84+
with patch.object(ScoutOtelHandler, "otel_handler") as mock_otel_handler:
8585
record = logging.LogRecord(
8686
name="test",
8787
level=logging.INFO,
@@ -104,7 +104,7 @@ def test_emit_when_scout_request_contains_operation(
104104
@patch("scout_apm_logging.handler.TrackedRequest")
105105
def test_emit_without_scout_request(mock_tracked_request, otel_scout_handler):
106106
mock_tracked_request.instance.return_value = None
107-
with patch.object(otel_scout_handler, "otel_handler") as mock_otel_handler:
107+
with patch.object(ScoutOtelHandler, "otel_handler") as mock_otel_handler:
108108
record = logging.LogRecord(
109109
name="test",
110110
level=logging.INFO,
@@ -121,7 +121,7 @@ def test_emit_without_scout_request(mock_tracked_request, otel_scout_handler):
121121

122122

123123
def test_emit_already_handling_log(otel_scout_handler):
124-
with patch.object(otel_scout_handler, "otel_handler") as mock_otel_handler:
124+
with patch.object(ScoutOtelHandler, "otel_handler") as mock_otel_handler:
125125
# Simulate that we're already handling a log message
126126
otel_scout_handler._handling_log.value = True
127127

@@ -141,35 +141,6 @@ def test_emit_already_handling_log(otel_scout_handler):
141141
otel_scout_handler._handling_log.value = False
142142

143143

144-
def test_emit_exception_handling(otel_scout_handler):
145-
with patch(
146-
"scout_apm_logging.handler.TrackedRequest"
147-
) as mock_tracked_request, patch(
148-
"sys.stdout", new_callable=io.StringIO
149-
) as mock_stdout:
150-
151-
mock_tracked_request.instance.side_effect = Exception("Test exception")
152-
153-
record = logging.LogRecord(
154-
name="test",
155-
level=logging.INFO,
156-
pathname="",
157-
lineno=0,
158-
msg="Test message",
159-
args=(),
160-
exc_info=None,
161-
)
162-
163-
otel_scout_handler.emit(record)
164-
165-
# Check that the exception was caught and the error message was printed
166-
assert (
167-
"Error in ScoutOtelHandler.emit: Test exception" in mock_stdout.getvalue()
168-
)
169-
170-
otel_scout_handler._handling_log.value = False
171-
172-
173144
def test_close(otel_scout_handler):
174145
with patch.object(otel_scout_handler.logger_provider, "shutdown") as mock_shutdown:
175146
otel_scout_handler.close()
@@ -222,7 +193,7 @@ def test_emit_handles_initialization_failure():
222193
mock_scout_config.value.return_value = (
223194
None # This will cause _get_ingest_key to fail
224195
)
225-
ScoutOtelHandler._class_initialized = False
196+
ScoutOtelHandler.otel_handler = None
226197

227198
handler = ScoutOtelHandler(service_name="test-service")
228199

0 commit comments

Comments
 (0)