15
15
# pylint: skip-file
16
16
from __future__ import annotations
17
17
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
+ )
19
27
from os import environ
20
28
from typing import Iterable , Optional , Sequence
21
29
from unittest import TestCase , mock
32
40
_EXPORTER_OTLP_PROTO_HTTP ,
33
41
_get_exporter_names ,
34
42
_get_id_generator ,
43
+ _get_log_level ,
35
44
_get_sampler ,
36
45
_import_config_components ,
37
46
_import_exporters ,
74
83
from opentelemetry .util .types import Attributes
75
84
76
85
86
+ CUSTOM_LOG_FORMAT = "CUSTOM FORMAT %(levelname)s:%(name)s:%(message)s"
87
+
88
+
77
89
class Provider :
78
90
def __init__ (self , resource = None , sampler = None , id_generator = None ):
79
91
self .sampler = sampler
@@ -665,9 +677,151 @@ def test_logging_init_exporter(self):
665
677
getLogger (__name__ ).error ("hello" )
666
678
self .assertTrue (provider .processor .exporter .export_called )
667
679
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
+
668
709
@patch .dict (
669
710
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
+ },
671
825
)
672
826
def test_logging_init_exporter_without_handler_setup (self ):
673
827
resource = Resource .create ({})
@@ -690,6 +844,11 @@ def test_logging_init_exporter_without_handler_setup(self):
690
844
)
691
845
getLogger (__name__ ).error ("hello" )
692
846
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 ()
693
852
694
853
@patch .dict (
695
854
environ ,
@@ -841,6 +1000,101 @@ def test_initialize_components_kwargs(
841
1000
True ,
842
1001
)
843
1002
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
+
844
1098
845
1099
class TestMetricsInit (TestCase ):
846
1100
def setUp (self ):
0 commit comments