1515# pylint: skip-file
1616from __future__ import annotations
1717
18- from logging import WARNING , getLogger
18+ from logging import (
19+ DEBUG ,
20+ ERROR ,
21+ INFO ,
22+ NOTSET ,
23+ WARNING ,
24+ getLogger ,
25+ Formatter ,
26+ )
1927from os import environ
2028from typing import Iterable , Optional , Sequence
2129from unittest import TestCase , mock
3240 _EXPORTER_OTLP_PROTO_HTTP ,
3341 _get_exporter_names ,
3442 _get_id_generator ,
43+ _get_log_level ,
3544 _get_sampler ,
3645 _import_config_components ,
3746 _import_exporters ,
7483from opentelemetry .util .types import Attributes
7584
7685
86+ CUSTOM_LOG_FORMAT = "CUSTOM FORMAT %(levelname)s:%(name)s:%(message)s"
87+
88+
7789class Provider :
7890 def __init__ (self , resource = None , sampler = None , id_generator = None ):
7991 self .sampler = sampler
@@ -665,9 +677,151 @@ def test_logging_init_exporter(self):
665677 getLogger (__name__ ).error ("hello" )
666678 self .assertTrue (provider .processor .exporter .export_called )
667679
680+ @patch .dict (environ , {}, clear = True )
681+ def test_otel_log_level_by_name_default (self ):
682+ self .assertEqual (_get_log_level (), NOTSET )
683+
684+ @patch .dict (environ , {"OTEL_LOG_LEVEL" : "NOTSET " }, clear = True )
685+ def test_otel_log_level_by_name_notset (self ):
686+ self .assertEqual (_get_log_level (), NOTSET )
687+
688+ @patch .dict (environ , {"OTEL_LOG_LEVEL" : " DeBug " }, clear = True )
689+ def test_otel_log_level_by_name_debug (self ):
690+ self .assertEqual (_get_log_level (), DEBUG )
691+
692+ @patch .dict (environ , {"OTEL_LOG_LEVEL" : " info " }, clear = True )
693+ def test_otel_log_level_by_name_info (self ):
694+ self .assertEqual (_get_log_level (), INFO )
695+
696+ @patch .dict (environ , {"OTEL_LOG_LEVEL" : " warn" }, clear = True )
697+ def test_otel_log_level_by_name_warn (self ):
698+ self .assertEqual (_get_log_level (), WARNING )
699+
700+ @patch .dict (environ , {"OTEL_LOG_LEVEL" : " warnING " }, clear = True )
701+ def test_otel_log_level_by_name_warning (self ):
702+ self .assertEqual (_get_log_level (), WARNING )
703+
704+ @patch .dict (environ , {"OTEL_LOG_LEVEL" : " eRroR" }, clear = True )
705+ def test_otel_log_level_by_name_error (self ):
706+ self .assertEqual (_get_log_level (), ERROR )
707+
708+
668709 @patch .dict (
669710 environ ,
670- {"OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" },
711+ {
712+ "OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" ,
713+ "OTEL_LOG_LEVEL" : "CUSTOM_LOG_LEVEL" ,
714+ },
715+ clear = True ,
716+ )
717+ @patch ("opentelemetry.sdk._configuration._get_log_level" , return_value = 39 )
718+ def test_logging_init_exporter_level_under (self , log_level_mock ):
719+ # log_level_mock.return_value = 39
720+ resource = Resource .create ({})
721+ _init_logging (
722+ {"otlp" : DummyOTLPLogExporter },
723+ resource = resource ,
724+ )
725+ self .assertEqual (self .set_provider_mock .call_count , 1 )
726+ provider = self .set_provider_mock .call_args [0 ][0 ]
727+ self .assertIsInstance (provider , DummyLoggerProvider )
728+ self .assertIsInstance (provider .resource , Resource )
729+ self .assertEqual (
730+ provider .resource .attributes .get ("service.name" ),
731+ "otlp-service" ,
732+ )
733+ self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
734+ self .assertIsInstance (
735+ provider .processor .exporter , DummyOTLPLogExporter
736+ )
737+ getLogger (__name__ ).error ("hello" )
738+ self .assertTrue (provider .processor .exporter .export_called )
739+ root_logger = getLogger ()
740+ handler_present = False
741+ for handler in root_logger .handlers :
742+ if isinstance (handler , LoggingHandler ):
743+ handler_present = True
744+ self .assertEqual (handler .level , 39 )
745+ self .assertTrue (handler_present )
746+
747+ @patch .dict (
748+ environ ,
749+ {
750+ "OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" ,
751+ "OTEL_LOG_LEVEL" : "CUSTOM_LOG_LEVEL" ,
752+ },
753+ clear = True ,
754+ )
755+ @patch ("opentelemetry.sdk._configuration._get_log_level" , return_value = 41 )
756+ def test_logging_init_exporter_level_over (self , log_level_mock ):
757+ resource = Resource .create ({})
758+ _init_logging (
759+ {"otlp" : DummyOTLPLogExporter },
760+ resource = resource ,
761+ )
762+ self .assertEqual (self .set_provider_mock .call_count , 1 )
763+ provider = self .set_provider_mock .call_args [0 ][0 ]
764+ self .assertIsInstance (provider , DummyLoggerProvider )
765+ self .assertIsInstance (provider .resource , Resource )
766+ self .assertEqual (
767+ provider .resource .attributes .get ("service.name" ),
768+ "otlp-service" ,
769+ )
770+ self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
771+ self .assertIsInstance (
772+ provider .processor .exporter , DummyOTLPLogExporter
773+ )
774+ getLogger (__name__ ).error ("hello" )
775+ self .assertFalse (provider .processor .exporter .export_called )
776+ root_logger = getLogger ()
777+ handler_present = False
778+ for handler in root_logger .handlers :
779+ if isinstance (handler , LoggingHandler ):
780+ handler_present = True
781+ self .assertEqual (handler .level , 41 )
782+ self .assertTrue (handler_present )
783+
784+ @patch .dict (
785+ environ ,
786+ {
787+ "OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" ,
788+ "OTEL_PYTHON_LOG_FORMAT" : CUSTOM_LOG_FORMAT ,
789+ },
790+ )
791+ def test_logging_init_exporter_format (self ):
792+ resource = Resource .create ({})
793+ _init_logging (
794+ {"otlp" : DummyOTLPLogExporter },
795+ resource = resource ,
796+ )
797+ self .assertEqual (self .set_provider_mock .call_count , 1 )
798+ provider = self .set_provider_mock .call_args [0 ][0 ]
799+ self .assertIsInstance (provider , DummyLoggerProvider )
800+ self .assertIsInstance (provider .resource , Resource )
801+ self .assertEqual (
802+ provider .resource .attributes .get ("service.name" ),
803+ "otlp-service" ,
804+ )
805+ self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
806+ self .assertIsInstance (
807+ provider .processor .exporter , DummyOTLPLogExporter
808+ )
809+ getLogger (__name__ ).error ("hello" )
810+ self .assertTrue (provider .processor .exporter .export_called )
811+ root_logger = getLogger ()
812+ self .assertEqual (root_logger .level , WARNING )
813+ handler_present = False
814+ for handler in root_logger .handlers :
815+ if isinstance (handler , LoggingHandler ):
816+ self .assertEqual (handler .formatter ._fmt , CUSTOM_LOG_FORMAT )
817+ handler_present = True
818+ self .assertTrue (handler_present )
819+
820+ @patch .dict (
821+ environ ,
822+ {
823+ "OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" ,
824+ },
671825 )
672826 def test_logging_init_exporter_without_handler_setup (self ):
673827 resource = Resource .create ({})
@@ -690,6 +844,11 @@ def test_logging_init_exporter_without_handler_setup(self):
690844 )
691845 getLogger (__name__ ).error ("hello" )
692846 self .assertFalse (provider .processor .exporter .export_called )
847+ root_logger = getLogger ()
848+ self .assertEqual (root_logger .level , WARNING )
849+ for handler in root_logger .handlers :
850+ if isinstance (handler , LoggingHandler ):
851+ self .fail ()
693852
694853 @patch .dict (
695854 environ ,
@@ -841,6 +1000,101 @@ def test_initialize_components_kwargs(
8411000 True ,
8421001 )
8431002
1003+ @patch .dict (
1004+ environ ,
1005+ {
1006+ "OTEL_TRACES_EXPORTER" : _EXPORTER_OTLP ,
1007+ "OTEL_METRICS_EXPORTER" : _EXPORTER_OTLP_PROTO_GRPC ,
1008+ "OTEL_LOGS_EXPORTER" : _EXPORTER_OTLP_PROTO_HTTP ,
1009+ },
1010+ )
1011+ @patch .dict (
1012+ environ ,
1013+ {
1014+ "OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service, custom.key.1=env-value" ,
1015+ "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED" : "False" ,
1016+ },
1017+ )
1018+ @patch ("opentelemetry.sdk._configuration.Resource" )
1019+ @patch ("opentelemetry.sdk._configuration._import_exporters" )
1020+ @patch ("opentelemetry.sdk._configuration._get_exporter_names" )
1021+ @patch ("opentelemetry.sdk._configuration._init_tracing" )
1022+ @patch ("opentelemetry.sdk._configuration._init_logging" )
1023+ @patch ("opentelemetry.sdk._configuration._init_metrics" )
1024+ def test_initialize_components_kwargs_disable_logging_handler (
1025+ self ,
1026+ metrics_mock ,
1027+ logging_mock ,
1028+ tracing_mock ,
1029+ exporter_names_mock ,
1030+ import_exporters_mock ,
1031+ resource_mock ,
1032+ ):
1033+ exporter_names_mock .return_value = [
1034+ "env_var_exporter_1" ,
1035+ "env_var_exporter_2" ,
1036+ ]
1037+ import_exporters_mock .return_value = (
1038+ "TEST_SPAN_EXPORTERS_DICT" ,
1039+ "TEST_METRICS_EXPORTERS_DICT" ,
1040+ "TEST_LOG_EXPORTERS_DICT" ,
1041+ )
1042+ resource_mock .create .return_value = "TEST_RESOURCE"
1043+ kwargs = {
1044+ "auto_instrumentation_version" : "auto-version" ,
1045+ "trace_exporter_names" : ["custom_span_exporter" ],
1046+ "metric_exporter_names" : ["custom_metric_exporter" ],
1047+ "log_exporter_names" : ["custom_log_exporter" ],
1048+ "sampler" : "TEST_SAMPLER" ,
1049+ "resource_attributes" : {
1050+ "custom.key.1" : "pass-in-value-1" ,
1051+ "custom.key.2" : "pass-in-value-2" ,
1052+ },
1053+ "id_generator" : "TEST_GENERATOR" ,
1054+ }
1055+ _initialize_components (** kwargs )
1056+
1057+ import_exporters_mock .assert_called_once_with (
1058+ [
1059+ "custom_span_exporter" ,
1060+ "env_var_exporter_1" ,
1061+ "env_var_exporter_2" ,
1062+ ],
1063+ [
1064+ "custom_metric_exporter" ,
1065+ "env_var_exporter_1" ,
1066+ "env_var_exporter_2" ,
1067+ ],
1068+ [
1069+ "custom_log_exporter" ,
1070+ "env_var_exporter_1" ,
1071+ "env_var_exporter_2" ,
1072+ ],
1073+ )
1074+ resource_mock .create .assert_called_once_with (
1075+ {
1076+ "telemetry.auto.version" : "auto-version" ,
1077+ "custom.key.1" : "pass-in-value-1" ,
1078+ "custom.key.2" : "pass-in-value-2" ,
1079+ }
1080+ )
1081+ # Resource is checked separates
1082+ tracing_mock .assert_called_once_with (
1083+ exporters = "TEST_SPAN_EXPORTERS_DICT" ,
1084+ id_generator = "TEST_GENERATOR" ,
1085+ sampler = "TEST_SAMPLER" ,
1086+ resource = "TEST_RESOURCE" ,
1087+ )
1088+ metrics_mock .assert_called_once_with (
1089+ "TEST_METRICS_EXPORTERS_DICT" ,
1090+ "TEST_RESOURCE" ,
1091+ )
1092+ logging_mock .assert_called_once_with (
1093+ "TEST_LOG_EXPORTERS_DICT" ,
1094+ "TEST_RESOURCE" ,
1095+ False ,
1096+ )
1097+
8441098
8451099class TestMetricsInit (TestCase ):
8461100 def setUp (self ):
0 commit comments