|
16 | 16 | import contextvars |
17 | 17 | import threading |
18 | 18 | import unittest |
| 19 | +from unittest.mock import patch |
19 | 20 |
|
20 | 21 | from opentelemetry.instrumentation._labeler import ( |
21 | 22 | Labeler, |
@@ -76,6 +77,123 @@ def test_clear_attributes(self): |
76 | 77 | self.assertEqual(labeler.get_attributes(), {}) |
77 | 78 | self.assertEqual(len(labeler), 0) |
78 | 79 |
|
| 80 | + def test_add_valid_types(self): |
| 81 | + labeler = Labeler() |
| 82 | + labeler.add("str_key", "string_value") |
| 83 | + labeler.add("int_key", 42) |
| 84 | + labeler.add("float_key", 3.14) |
| 85 | + labeler.add("bool_true_key", True) |
| 86 | + labeler.add("bool_false_key", False) |
| 87 | + |
| 88 | + attributes = labeler.get_attributes() |
| 89 | + expected = { |
| 90 | + "str_key": "string_value", |
| 91 | + "int_key": 42, |
| 92 | + "float_key": 3.14, |
| 93 | + "bool_true_key": True, |
| 94 | + "bool_false_key": False, |
| 95 | + } |
| 96 | + self.assertEqual(attributes, expected) |
| 97 | + self.assertEqual(len(labeler), 5) |
| 98 | + |
| 99 | + def test_add_invalid_types_logs_warning_and_skips(self): |
| 100 | + labeler = Labeler() |
| 101 | + |
| 102 | + with patch( |
| 103 | + "opentelemetry.instrumentation._labeler._internal._logger.warning" |
| 104 | + ) as mock_warning: |
| 105 | + labeler.add("valid", "value") |
| 106 | + |
| 107 | + labeler.add("dict_key", {"nested": "dict"}) |
| 108 | + labeler.add("list_key", [1, 2, 3]) |
| 109 | + labeler.add("none_key", None) |
| 110 | + labeler.add("tuple_key", (1, 2)) |
| 111 | + labeler.add("set_key", {1, 2, 3}) |
| 112 | + |
| 113 | + labeler.add("another_valid", 123) |
| 114 | + |
| 115 | + self.assertEqual(mock_warning.call_count, 5) |
| 116 | + warning_calls = [call[0] for call in mock_warning.call_args_list] |
| 117 | + self.assertIn("dict_key", str(warning_calls[0])) |
| 118 | + self.assertIn("dict", str(warning_calls[0])) |
| 119 | + self.assertIn("list_key", str(warning_calls[1])) |
| 120 | + self.assertIn("list", str(warning_calls[1])) |
| 121 | + self.assertIn("none_key", str(warning_calls[2])) |
| 122 | + self.assertIn("NoneType", str(warning_calls[2])) |
| 123 | + |
| 124 | + attributes = labeler.get_attributes() |
| 125 | + expected = {"valid": "value", "another_valid": 123} |
| 126 | + self.assertEqual(attributes, expected) |
| 127 | + self.assertEqual(len(labeler), 2) |
| 128 | + |
| 129 | + def test_add_attributes_valid_types(self): |
| 130 | + labeler = Labeler() |
| 131 | + attrs = { |
| 132 | + "str_key": "string_value", |
| 133 | + "int_key": 42, |
| 134 | + "float_key": 3.14, |
| 135 | + "bool_true_key": True, |
| 136 | + "bool_false_key": False, |
| 137 | + } |
| 138 | + labeler.add_attributes(attrs) |
| 139 | + attributes = labeler.get_attributes() |
| 140 | + self.assertEqual(attributes, attrs) |
| 141 | + self.assertEqual(len(labeler), 5) |
| 142 | + |
| 143 | + def test_add_attributes_invalid_types_logs_and_skips(self): |
| 144 | + labeler = Labeler() |
| 145 | + |
| 146 | + with patch( |
| 147 | + "opentelemetry.instrumentation._labeler._internal._logger.warning" |
| 148 | + ) as mock_warning: |
| 149 | + mixed_attrs = { |
| 150 | + "valid_str": "value", |
| 151 | + "invalid_dict": {"nested": "dict"}, |
| 152 | + "valid_int": 42, |
| 153 | + "invalid_list": [1, 2, 3], |
| 154 | + "valid_bool": True, |
| 155 | + "invalid_none": None, |
| 156 | + } |
| 157 | + labeler.add_attributes(mixed_attrs) |
| 158 | + |
| 159 | + self.assertEqual(mock_warning.call_count, 3) |
| 160 | + warning_calls = [str(call) for call in mock_warning.call_args_list] |
| 161 | + self.assertTrue(any("invalid_dict" in call for call in warning_calls)) |
| 162 | + self.assertTrue(any("invalid_list" in call for call in warning_calls)) |
| 163 | + self.assertTrue(any("invalid_none" in call for call in warning_calls)) |
| 164 | + attributes = labeler.get_attributes() |
| 165 | + expected = { |
| 166 | + "valid_str": "value", |
| 167 | + "valid_int": 42, |
| 168 | + "valid_bool": True, |
| 169 | + } |
| 170 | + self.assertEqual(attributes, expected) |
| 171 | + self.assertEqual(len(labeler), 3) |
| 172 | + |
| 173 | + def test_add_attributes_all_invalid_types(self): |
| 174 | + """Test add_attributes when all types are invalid""" |
| 175 | + labeler = Labeler() |
| 176 | + |
| 177 | + with patch( |
| 178 | + "opentelemetry.instrumentation._labeler._internal._logger.warning" |
| 179 | + ) as mock_warning: |
| 180 | + invalid_attrs = { |
| 181 | + "dict_key": {"nested": "dict"}, |
| 182 | + "list_key": [1, 2, 3], |
| 183 | + "none_key": None, |
| 184 | + "custom_obj": object(), |
| 185 | + } |
| 186 | + |
| 187 | + labeler.add_attributes(invalid_attrs) |
| 188 | + |
| 189 | + # Should have logged warnings for all 4 invalid attributes |
| 190 | + self.assertEqual(mock_warning.call_count, 4) |
| 191 | + |
| 192 | + # No attributes should be stored |
| 193 | + attributes = labeler.get_attributes() |
| 194 | + self.assertEqual(attributes, {}) |
| 195 | + self.assertEqual(len(labeler), 0) |
| 196 | + |
79 | 197 | def test_thread_safety(self): |
80 | 198 | labeler = Labeler(max_custom_attrs=1100) # 11 * 100 |
81 | 199 | num_threads = 10 |
|
0 commit comments