Skip to content

Commit 056618b

Browse files
committed
Fix comments
1 parent 95ec428 commit 056618b

File tree

6 files changed

+103
-216
lines changed

6 files changed

+103
-216
lines changed

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/aws_opentelemetry_configurator.py

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,14 @@ class OtlpLogHeaderSetting(NamedTuple):
122122
log_group: Optional[str]
123123
log_stream: Optional[str]
124124
namespace: Optional[str]
125-
is_valid: bool
125+
126+
def is_valid(self) -> bool:
127+
"""Check if the log header setting is valid by ensuring both log_group and log_stream are present."""
128+
return self.log_group is not None and self.log_stream is not None
129+
130+
131+
# Singleton cache for OtlpLogHeaderSetting
132+
_otlp_log_header_setting_cache: Optional[OtlpLogHeaderSetting] = None
126133

127134

128135
class AwsOpenTelemetryConfigurator(_OTelSDKConfigurator):
@@ -440,7 +447,7 @@ def _customize_logs_exporter(log_exporter: LogExporter) -> LogExporter:
440447

441448
if isinstance(log_exporter, OTLPLogExporter):
442449

443-
if _validate_and_fetch_logs_header().is_valid:
450+
if _fetch_logs_header().is_valid():
444451
endpoint, region = _extract_endpoint_and_region_from_otlp_endpoint(logs_endpoint)
445452
# Setting default compression mode to Gzip as this is the behavior in upstream's
446453
# collector otlp http exporter:
@@ -627,9 +634,12 @@ def _extract_endpoint_and_region_from_otlp_endpoint(endpoint: str):
627634
return endpoint, region
628635

629636

630-
def _validate_and_fetch_logs_header() -> OtlpLogHeaderSetting:
631-
"""Checks if x-aws-log-group and x-aws-log-stream are present in the headers in order to send logs to
632-
AWS OTLP Logs endpoint."""
637+
def _fetch_logs_header() -> OtlpLogHeaderSetting:
638+
"""Returns the OTLP log header setting as a singleton instance."""
639+
global _otlp_log_header_setting_cache # pylint: disable=global-statement
640+
641+
if _otlp_log_header_setting_cache is not None:
642+
return _otlp_log_header_setting_cache
633643

634644
logs_headers = os.environ.get(OTEL_EXPORTER_OTLP_LOGS_HEADERS)
635645

@@ -639,7 +649,8 @@ def _validate_and_fetch_logs_header() -> OtlpLogHeaderSetting:
639649
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS "
640650
"to include x-aws-log-group and x-aws-log-stream"
641651
)
642-
return OtlpLogHeaderSetting(None, None, None, False)
652+
_otlp_log_header_setting_cache = OtlpLogHeaderSetting(None, None, None)
653+
return _otlp_log_header_setting_cache
643654

644655
log_group = None
645656
log_stream = None
@@ -657,9 +668,14 @@ def _validate_and_fetch_logs_header() -> OtlpLogHeaderSetting:
657668
elif key == AWS_EMF_METRICS_NAMESPACE and value:
658669
namespace = value
659670

660-
is_valid = log_group is not None and log_stream is not None
671+
_otlp_log_header_setting_cache = OtlpLogHeaderSetting(log_group, log_stream, namespace)
672+
return _otlp_log_header_setting_cache
661673

662-
return OtlpLogHeaderSetting(log_group, log_stream, namespace, is_valid)
674+
675+
def _clear_logs_header_cache():
676+
"""Clear the singleton cache for OtlpLogHeaderSetting. Used primarily for testing."""
677+
global _otlp_log_header_setting_cache # pylint: disable=global-statement
678+
_otlp_log_header_setting_cache = None
663679

664680

665681
def _get_metric_export_interval():
@@ -772,26 +788,26 @@ def _check_emf_exporter_enabled() -> bool:
772788

773789
return True
774790

791+
775792
def _create_emf_exporter():
776793
"""
777794
Create the appropriate EMF exporter based on the environment and configuration.
778795
796+
Returns:
797+
ConsoleEmfExporter for Lambda without log headers log group and stream
798+
AwsCloudWatchEmfExporter for other cases (when conditions are met)
799+
None if CloudWatch exporter cannot be created
779800
"""
780-
log_header_setting = _validate_and_fetch_logs_header()
781-
782-
if _is_lambda_environment() and not log_header_setting.is_valid:
801+
try:
802+
log_header_setting = _fetch_logs_header()
803+
783804
# Lambda without valid logs http headers - use Console EMF exporter
784-
from amazon.opentelemetry.distro.exporter.aws.metrics.console_emf_exporter import (
785-
ConsoleEmfExporter,
786-
)
787-
return ConsoleEmfExporter(namespace=log_header_setting.namespace)
788-
else:
789-
# Non-Lambda environment - use CloudWatch EMF exporter
790-
return _create_cloudwatch_emf_exporter()
805+
if _is_lambda_environment() and not log_header_setting.is_valid():
806+
# pylint: disable=import-outside-toplevel
807+
from amazon.opentelemetry.distro.exporter.aws.metrics.console_emf_exporter import ConsoleEmfExporter
808+
return ConsoleEmfExporter(namespace=log_header_setting.namespace)
791809

792-
def _create_cloudwatch_emf_exporter():
793-
"""Create and configure the CloudWatch EMF exporter."""
794-
try:
810+
# For non-Lambda environment or Lambda with valid headers - use CloudWatch EMF exporter
795811
session = get_aws_session()
796812
# Check if botocore is available before importing the EMF exporter
797813
if not session:
@@ -803,9 +819,7 @@ def _create_cloudwatch_emf_exporter():
803819
AwsCloudWatchEmfExporter,
804820
)
805821

806-
log_header_setting = _validate_and_fetch_logs_header()
807-
808-
if not log_header_setting.is_valid:
822+
if not log_header_setting.is_valid():
809823
return None
810824

811825
return AwsCloudWatchEmfExporter(

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/aws_cloudwatch_emf_exporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def __init__(
5757
log_group_name=log_group_name, log_stream_name=log_stream_name, aws_region=aws_region, **kwargs
5858
)
5959

60-
def _send_log_event(self, log_event: Dict[str, Any]):
60+
def _export(self, log_event: Dict[str, Any]):
6161
"""
6262
Send a log event to CloudWatch Logs using the log client.
6363

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/base_emf_exporter.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class BaseEmfExporter(MetricExporter, ABC):
6666
Base class for OpenTelemetry metrics exporters that convert to CloudWatch EMF format.
6767
6868
This class contains all the common logic for converting OTel metrics into CloudWatch EMF logs.
69-
Subclasses need to implement the _send_log_event method to define where the EMF logs are sent.
69+
Subclasses need to implement the _export method to define where the EMF logs are sent.
7070
7171
https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html
7272
@@ -504,7 +504,7 @@ def _create_emf_log(
504504
return emf_log
505505

506506
@abstractmethod
507-
def _send_log_event(self, log_event: Dict[str, Any]):
507+
def _export(self, log_event: Dict[str, Any]):
508508
"""
509509
Send a log event to the destination (CloudWatch Logs, console, etc.).
510510
@@ -513,7 +513,6 @@ def _send_log_event(self, log_event: Dict[str, Any]):
513513
Args:
514514
log_event: The log event to send
515515
"""
516-
pass
517516

518517
# pylint: disable=too-many-nested-blocks,unused-argument,too-many-branches
519518
def export(
@@ -580,7 +579,7 @@ def export(
580579
len(metric_records),
581580
timestamp_ms,
582581
)
583-
self._send_log_event(
582+
self._export(
584583
{
585584
"message": json.dumps(
586585
self._create_emf_log(metric_records, resource_metrics.resource, timestamp_ms)

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/console_emf_exporter.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
# pylint: disable=no-self-use
55

66
import logging
7-
import sys
87
from typing import Any, Dict, Optional
98

109
from opentelemetry.sdk.metrics.export import AggregationTemporality
@@ -47,17 +46,17 @@ def __init__(
4746
namespace = "default"
4847
super().__init__(namespace, preferred_temporality, preferred_aggregation)
4948

50-
def _send_log_event(self, log_event: Dict[str, Any]) -> None:
49+
def _export(self, log_event: Dict[str, Any]) -> None:
5150
"""
52-
Send a log event to stdout for console output.
51+
Send a log event message to stdout for console output.
5352
5453
This method writes the EMF log message to stdout, making it easy to
5554
capture and redirect the output for processing or debugging purposes.
5655
5756
Args:
5857
log_event: The log event dictionary containing 'message' and 'timestamp'
5958
keys, where 'message' is the JSON-serialized EMF log
60-
59+
6160
Raises:
6261
No exceptions are raised - errors are logged and handled gracefully
6362
"""
@@ -68,10 +67,8 @@ def _send_log_event(self, log_event: Dict[str, Any]) -> None:
6867
print(message, flush=True)
6968
else:
7069
logger.warning("Empty message in log event: %s", log_event)
71-
except (KeyError, TypeError) as e:
72-
logger.error("Invalid log event format: %s. Error: %s", log_event, e)
73-
except Exception as e:
74-
logger.error("Failed to write EMF log to console: %s", e)
70+
except Exception as error: # pylint: disable=broad-exception-caught
71+
logger.error("Failed to write EMF log to console. Log event: %s. Error: %s", log_event, error)
7572

7673
def force_flush(self, timeout_millis: int = 10000) -> bool:
7774
"""

aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/exporter/aws/metrics/test_console_emf_exporter.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,34 @@ def test_namespace_initialization(self):
1616
# Test default namespace
1717
exporter = ConsoleEmfExporter()
1818
self.assertEqual(exporter.namespace, "default")
19-
19+
2020
# Test custom namespace
2121
exporter = ConsoleEmfExporter(namespace="CustomNamespace")
2222
self.assertEqual(exporter.namespace, "CustomNamespace")
23-
23+
2424
# Test None namespace (should default to 'default')
2525
exporter = ConsoleEmfExporter(namespace=None)
2626
self.assertEqual(exporter.namespace, "default")
2727

2828
def test_send_log_event(self):
2929
"""Test that log events are properly sent to console output."""
3030
exporter = ConsoleEmfExporter()
31-
31+
3232
# Create a simple log event with EMF-formatted message
33-
test_message = '{"_aws":{"Timestamp":1640995200000,"CloudWatchMetrics":[{"Namespace":"TestNamespace","Dimensions":[["Service"]],"Metrics":[{"Name":"TestMetric","Unit":"Count"}]}]},"Service":"test-service","TestMetric":42}'
33+
test_message = (
34+
'{"_aws":{"Timestamp":1640995200000,"CloudWatchMetrics":[{"Namespace":"TestNamespace",'
35+
'"Dimensions":[["Service"]],"Metrics":[{"Name":"TestMetric","Unit":"Count"}]}]},'
36+
'"Service":"test-service","TestMetric":42}'
37+
)
3438
log_event = {
3539
"message": test_message,
3640
"timestamp": 1640995200000
3741
}
38-
42+
3943
# Capture stdout to verify the output
4044
with patch('sys.stdout', new_callable=StringIO) as mock_stdout:
41-
exporter._send_log_event(log_event)
42-
45+
exporter._export(log_event)
46+
4347
# Verify the message was printed to stdout
4448
captured_output = mock_stdout.getvalue().strip()
4549
self.assertEqual(captured_output, test_message)

0 commit comments

Comments
 (0)