Skip to content

Commit f259212

Browse files
authored
Merge branch 'main' into compressed-console-log-exporter
2 parents 0c008b0 + b6fb638 commit f259212

File tree

9 files changed

+1584
-686
lines changed

9 files changed

+1584
-686
lines changed

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

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,14 @@ class OtlpLogHeaderSetting(NamedTuple):
125125
log_group: Optional[str]
126126
log_stream: Optional[str]
127127
namespace: Optional[str]
128-
is_valid: bool
128+
129+
def is_valid(self) -> bool:
130+
"""Check if the log header setting is valid by ensuring both log_group and log_stream are present."""
131+
return self.log_group is not None and self.log_stream is not None
132+
133+
134+
# Singleton cache for OtlpLogHeaderSetting
135+
_otlp_log_header_setting_cache: Optional[OtlpLogHeaderSetting] = None
129136

130137

131138
class AwsOpenTelemetryConfigurator(_OTelSDKConfigurator):
@@ -446,7 +453,7 @@ def _customize_logs_exporter(log_exporter: LogExporter) -> LogExporter:
446453

447454
if isinstance(log_exporter, OTLPLogExporter):
448455

449-
if _validate_and_fetch_logs_header().is_valid:
456+
if _fetch_logs_header().is_valid():
450457
endpoint, region = _extract_endpoint_and_region_from_otlp_endpoint(logs_endpoint)
451458
# Setting default compression mode to Gzip as this is the behavior in upstream's
452459
# collector otlp http exporter:
@@ -633,18 +640,23 @@ def _extract_endpoint_and_region_from_otlp_endpoint(endpoint: str):
633640
return endpoint, region
634641

635642

636-
def _validate_and_fetch_logs_header() -> OtlpLogHeaderSetting:
637-
"""Checks if x-aws-log-group and x-aws-log-stream are present in the headers in order to send logs to
638-
AWS OTLP Logs endpoint."""
643+
def _fetch_logs_header() -> OtlpLogHeaderSetting:
644+
"""Returns the OTLP log header setting as a singleton instance."""
645+
global _otlp_log_header_setting_cache # pylint: disable=global-statement
646+
647+
if _otlp_log_header_setting_cache is not None:
648+
return _otlp_log_header_setting_cache
639649

640650
logs_headers = os.environ.get(OTEL_EXPORTER_OTLP_LOGS_HEADERS)
641651

642652
if not logs_headers:
643-
_logger.warning(
644-
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS "
645-
"to include x-aws-log-group and x-aws-log-stream"
646-
)
647-
return OtlpLogHeaderSetting(None, None, None, False)
653+
if not _is_lambda_environment():
654+
_logger.warning(
655+
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS "
656+
"to include x-aws-log-group and x-aws-log-stream"
657+
)
658+
_otlp_log_header_setting_cache = OtlpLogHeaderSetting(None, None, None)
659+
return _otlp_log_header_setting_cache
648660

649661
log_group = None
650662
log_stream = None
@@ -662,9 +674,14 @@ def _validate_and_fetch_logs_header() -> OtlpLogHeaderSetting:
662674
elif key == AWS_EMF_METRICS_NAMESPACE and value:
663675
namespace = value
664676

665-
is_valid = log_group is not None and log_stream is not None
677+
_otlp_log_header_setting_cache = OtlpLogHeaderSetting(log_group, log_stream, namespace)
678+
return _otlp_log_header_setting_cache
679+
666680

667-
return OtlpLogHeaderSetting(log_group, log_stream, namespace, is_valid)
681+
def _clear_logs_header_cache():
682+
"""Clear the singleton cache for OtlpLogHeaderSetting. Used primarily for testing."""
683+
global _otlp_log_header_setting_cache # pylint: disable=global-statement
684+
_otlp_log_header_setting_cache = None
668685

669686

670687
def _get_metric_export_interval():
@@ -779,8 +796,25 @@ def _check_emf_exporter_enabled() -> bool:
779796

780797

781798
def _create_emf_exporter():
782-
"""Create and configure the CloudWatch EMF exporter."""
799+
"""
800+
Create the appropriate EMF exporter based on the environment and configuration.
801+
802+
Returns:
803+
ConsoleEmfExporter for Lambda without log headers log group and stream
804+
AwsCloudWatchEmfExporter for other cases (when conditions are met)
805+
None if CloudWatch exporter cannot be created
806+
"""
783807
try:
808+
log_header_setting = _fetch_logs_header()
809+
810+
# Lambda without valid logs http headers - use Console EMF exporter
811+
if _is_lambda_environment() and not log_header_setting.is_valid():
812+
# pylint: disable=import-outside-toplevel
813+
from amazon.opentelemetry.distro.exporter.aws.metrics.console_emf_exporter import ConsoleEmfExporter
814+
815+
return ConsoleEmfExporter(namespace=log_header_setting.namespace)
816+
817+
# For non-Lambda environment or Lambda with valid headers - use CloudWatch EMF exporter
784818
session = get_aws_session()
785819
# Check if botocore is available before importing the EMF exporter
786820
if not session:
@@ -792,9 +826,7 @@ def _create_emf_exporter():
792826
AwsCloudWatchEmfExporter,
793827
)
794828

795-
log_header_setting = _validate_and_fetch_logs_header()
796-
797-
if not log_header_setting.is_valid:
829+
if not log_header_setting.is_valid():
798830
return None
799831

800832
return AwsCloudWatchEmfExporter(

0 commit comments

Comments
 (0)