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