ferruzzi commented on code in PR #43340:
URL: https://github.com/apache/airflow/pull/43340#discussion_r1821166636


##########
tests/core/test_otel_logger.py:
##########
@@ -358,108 +358,134 @@ def test_timer_start_and_stop_manually_send_true(self, 
mock_time, metrics_consis
         )
 
     def test_incr_counter(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 5
         tags = {"env": "prod"}
 
-        # Act
-        logger.incr(metric_name, count=count, tags=tags)
+        self.stats.incr(metric_name, count=count, tags=tags)
 
-        # Assert
-        counter = logger.metrics_map.get_counter(
-            full_name(prefix=logger.prefix, name=metric_name), attributes=tags
+        counter = self.stats.metrics_map.get_counter(
+            full_name(prefix=self.stats.prefix, name=metric_name), 
attributes=tags
         )
         counter.add.assert_called_with(count, attributes=tags)
 
     def test_decr_counter(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 3
         tags = {"env": "prod"}
 
-        # Act
-        logger.decr(metric_name, count=count, tags=tags)
+        self.stats.decr(metric_name, count=count, tags=tags)
 
-        # Assert
-        counter = logger.metrics_map.get_counter(
-            full_name(prefix=logger.prefix, name=metric_name), attributes=tags
+        counter = self.stats.metrics_map.get_counter(
+            full_name(prefix=self.stats.prefix, name=metric_name), 
attributes=tags
         )
         counter.add.assert_called_with(-count, attributes=tags)
 
     @pytest.mark.parametrize("expected_duration", [2.5, 1.0, 3.0])
     def test_timing(self, expected_duration):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         tags = {"env": "prod"}
 
         # Mocking time.perf_counter to simulate timing
         with mock.patch.object(time, "perf_counter", side_effect=[0.0, 
expected_duration]):
-            with logger.timer(metric_name, tags=tags) as timer:
+            with self.stats.timer(metric_name, tags=tags) as timer:
                 pass
 
-        # Assert
+        acceptable_margin = 0.1
         assert isinstance(timer.duration, float)
-        assert timer.duration >= expected_duration - 0.1
-        assert timer.duration <= expected_duration + 0.1
+        assert timer.duration >= expected_duration - acceptable_margin
+        assert timer.duration <= expected_duration + acceptable_margin
         assert self.meter.get_meter().create_observable_gauge.call_count == 1
         self.meter.get_meter().create_observable_gauge.assert_called_once_with(

Review Comment:
   You can actually drop the `call_count == 1` assertion here since 
`assert_called_once` also asserts exactly once.  
[[docs]](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_once_with)



##########
tests/core/test_otel_logger.py:
##########
@@ -358,108 +358,134 @@ def test_timer_start_and_stop_manually_send_true(self, 
mock_time, metrics_consis
         )
 
     def test_incr_counter(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 5
         tags = {"env": "prod"}
 
-        # Act
-        logger.incr(metric_name, count=count, tags=tags)
+        self.stats.incr(metric_name, count=count, tags=tags)
 
-        # Assert
-        counter = logger.metrics_map.get_counter(
-            full_name(prefix=logger.prefix, name=metric_name), attributes=tags
+        counter = self.stats.metrics_map.get_counter(
+            full_name(prefix=self.stats.prefix, name=metric_name), 
attributes=tags
         )
         counter.add.assert_called_with(count, attributes=tags)
 
     def test_decr_counter(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 3
         tags = {"env": "prod"}
 
-        # Act
-        logger.decr(metric_name, count=count, tags=tags)
+        self.stats.decr(metric_name, count=count, tags=tags)
 
-        # Assert
-        counter = logger.metrics_map.get_counter(
-            full_name(prefix=logger.prefix, name=metric_name), attributes=tags
+        counter = self.stats.metrics_map.get_counter(
+            full_name(prefix=self.stats.prefix, name=metric_name), 
attributes=tags
         )
         counter.add.assert_called_with(-count, attributes=tags)
 
     @pytest.mark.parametrize("expected_duration", [2.5, 1.0, 3.0])
     def test_timing(self, expected_duration):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         tags = {"env": "prod"}
 
         # Mocking time.perf_counter to simulate timing
         with mock.patch.object(time, "perf_counter", side_effect=[0.0, 
expected_duration]):
-            with logger.timer(metric_name, tags=tags) as timer:
+            with self.stats.timer(metric_name, tags=tags) as timer:
                 pass
 
-        # Assert
+        acceptable_margin = 0.1
         assert isinstance(timer.duration, float)
-        assert timer.duration >= expected_duration - 0.1
-        assert timer.duration <= expected_duration + 0.1
+        assert timer.duration >= expected_duration - acceptable_margin
+        assert timer.duration <= expected_duration + acceptable_margin
         assert self.meter.get_meter().create_observable_gauge.call_count == 1
         self.meter.get_meter().create_observable_gauge.assert_called_once_with(
-            name=full_name(prefix=logger.prefix, name=metric_name), 
callbacks=ANY
+            name=full_name(prefix=self.stats.prefix, name=metric_name), 
callbacks=ANY
         )
 
     def test_gauge_set(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         value = 42
         tags = {"env": "prod"}
 
-        # Act
-        logger.gauge(metric_name, value, tags=tags)
+        self.stats.gauge(metric_name, value, tags=tags)
 
-        # Assert
-        current_value = 
logger.metrics_map.poke_gauge(full_name(prefix=logger.prefix, 
name=metric_name), tags)
+        current_value = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
+        )
         assert current_value == value
 
     def test_gauge_increment(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 10
         tags = {"env": "prod"}
 
-        # Act
-        logger.gauge(metric_name, count, delta=True, tags=tags)  # Use 
delta=True to increment the gauge
+        self.stats.gauge(metric_name, count, delta=True, tags=tags)  # Use 
delta=True to increment the gauge
 
-        # Assert
         # Retrieve the current value using poke_gauge
-        current_value = 
logger.metrics_map.poke_gauge(full_name(prefix=logger.prefix, 
name=metric_name), tags)
+        current_value = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
+        )
         assert current_value == count
 
     def test_gauge_decrement(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 5
         tags = {"env": "prod"}
 
-        # Act: Increment the gauge by 'count'
-        logger.gauge(metric_name, count, delta=True, tags=tags)
+        self.stats.gauge(metric_name, count, delta=True, tags=tags)
 
-        # Assert: Check if the current value after incrementing is equal to 
'count'
-        current_value_after_increment = logger.metrics_map.poke_gauge(
-            full_name(prefix=logger.prefix, name=metric_name), tags
+        current_value_after_increment = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
         )
         assert current_value_after_increment == count  # Ensure the gauge 
value reflects the increment
 
-        # Act for decrement
-        logger.gauge(metric_name, -count, delta=True, tags=tags)  # Decrement 
the gauge by 'count'
+        self.stats.gauge(metric_name, -count, delta=True, tags=tags)  # 
Decrement the gauge by 'count'
 
-        # Assert: Ensure the gauge value reflects the decrement to zero
-        current_value_after_decrement = logger.metrics_map.poke_gauge(
-            full_name(prefix=logger.prefix, name=metric_name), tags
+        current_value_after_decrement = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
         )
         assert current_value_after_decrement == 0
+

Review Comment:
   Non-blocking nitpick/style suggestion, feel free not to implement this idea;
   
   You could combine all of the following new tests into one parametrized test 
which passes in the name being tested, the tags (or perhaps a bool indicating 
whether to use a set of tags which are defined in the test itself), and the 
expected exception message.   If you'd like to see what that might look like, 
check out 
[this](https://github.com/apache/airflow/blob/main/providers/tests/amazon/aws/operators/test_appflow.py#L212)
 test



##########
tests/core/test_otel_logger.py:
##########
@@ -358,108 +358,134 @@ def test_timer_start_and_stop_manually_send_true(self, 
mock_time, metrics_consis
         )
 
     def test_incr_counter(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 5
         tags = {"env": "prod"}
 
-        # Act
-        logger.incr(metric_name, count=count, tags=tags)
+        self.stats.incr(metric_name, count=count, tags=tags)
 
-        # Assert
-        counter = logger.metrics_map.get_counter(
-            full_name(prefix=logger.prefix, name=metric_name), attributes=tags
+        counter = self.stats.metrics_map.get_counter(
+            full_name(prefix=self.stats.prefix, name=metric_name), 
attributes=tags
         )
         counter.add.assert_called_with(count, attributes=tags)
 
     def test_decr_counter(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 3
         tags = {"env": "prod"}
 
-        # Act
-        logger.decr(metric_name, count=count, tags=tags)
+        self.stats.decr(metric_name, count=count, tags=tags)
 
-        # Assert
-        counter = logger.metrics_map.get_counter(
-            full_name(prefix=logger.prefix, name=metric_name), attributes=tags
+        counter = self.stats.metrics_map.get_counter(
+            full_name(prefix=self.stats.prefix, name=metric_name), 
attributes=tags
         )
         counter.add.assert_called_with(-count, attributes=tags)
 
     @pytest.mark.parametrize("expected_duration", [2.5, 1.0, 3.0])
     def test_timing(self, expected_duration):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         tags = {"env": "prod"}
 
         # Mocking time.perf_counter to simulate timing
         with mock.patch.object(time, "perf_counter", side_effect=[0.0, 
expected_duration]):
-            with logger.timer(metric_name, tags=tags) as timer:
+            with self.stats.timer(metric_name, tags=tags) as timer:
                 pass
 
-        # Assert
+        acceptable_margin = 0.1
         assert isinstance(timer.duration, float)
-        assert timer.duration >= expected_duration - 0.1
-        assert timer.duration <= expected_duration + 0.1
+        assert timer.duration >= expected_duration - acceptable_margin
+        assert timer.duration <= expected_duration + acceptable_margin
         assert self.meter.get_meter().create_observable_gauge.call_count == 1
         self.meter.get_meter().create_observable_gauge.assert_called_once_with(
-            name=full_name(prefix=logger.prefix, name=metric_name), 
callbacks=ANY
+            name=full_name(prefix=self.stats.prefix, name=metric_name), 
callbacks=ANY
         )
 
     def test_gauge_set(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         value = 42
         tags = {"env": "prod"}
 
-        # Act
-        logger.gauge(metric_name, value, tags=tags)
+        self.stats.gauge(metric_name, value, tags=tags)
 
-        # Assert
-        current_value = 
logger.metrics_map.poke_gauge(full_name(prefix=logger.prefix, 
name=metric_name), tags)
+        current_value = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
+        )
         assert current_value == value
 
     def test_gauge_increment(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 10
         tags = {"env": "prod"}
 
-        # Act
-        logger.gauge(metric_name, count, delta=True, tags=tags)  # Use 
delta=True to increment the gauge
+        self.stats.gauge(metric_name, count, delta=True, tags=tags)  # Use 
delta=True to increment the gauge
 
-        # Assert
         # Retrieve the current value using poke_gauge
-        current_value = 
logger.metrics_map.poke_gauge(full_name(prefix=logger.prefix, 
name=metric_name), tags)
+        current_value = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
+        )
         assert current_value == count
 
     def test_gauge_decrement(self):
-        # Arrange
-        logger = self.stats
         metric_name = "test_metric"
         count = 5
         tags = {"env": "prod"}
 
-        # Act: Increment the gauge by 'count'
-        logger.gauge(metric_name, count, delta=True, tags=tags)
+        self.stats.gauge(metric_name, count, delta=True, tags=tags)
 
-        # Assert: Check if the current value after incrementing is equal to 
'count'
-        current_value_after_increment = logger.metrics_map.poke_gauge(
-            full_name(prefix=logger.prefix, name=metric_name), tags
+        current_value_after_increment = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
         )
         assert current_value_after_increment == count  # Ensure the gauge 
value reflects the increment
 
-        # Act for decrement
-        logger.gauge(metric_name, -count, delta=True, tags=tags)  # Decrement 
the gauge by 'count'
+        self.stats.gauge(metric_name, -count, delta=True, tags=tags)  # 
Decrement the gauge by 'count'
 
-        # Assert: Ensure the gauge value reflects the decrement to zero
-        current_value_after_decrement = logger.metrics_map.poke_gauge(
-            full_name(prefix=logger.prefix, name=metric_name), tags
+        current_value_after_decrement = self.stats.metrics_map.poke_gauge(
+            full_name(prefix=self.stats.prefix, name=metric_name), tags
         )
         assert current_value_after_decrement == 0
+

Review Comment:
   Nitpick, non-blocking: Consider combining the following test cases into one 
parameterized test which accepts `(test_name, test_tags, expected_message)`,  
For an example of what that could look like, check out [this 
test](https://github.com/apache/airflow/blob/main/providers/tests/amazon/aws/operators/test_appflow.py#L212)



##########
airflow/metrics/otel_logger.py:
##########
@@ -241,8 +239,8 @@ def decr(
             raise ValueError("count must be a positive value.")
 
         full_metric_name = self.get_name(metric_name, tags)
-        if self.metrics_validator.test(full_metric_name) and 
name_is_otel_safe(self.prefix, full_metric_name):
-            counter = 
self.metrics_map.get_counter(full_name(prefix=self.prefix, 
name=full_metric_name))

Review Comment:
   So much cleaner :heart_eyes:   I love it when existing code can be 
streamlined.



##########
airflow/metrics/otel_logger.py:
##########
@@ -212,10 +212,8 @@ def incr(
 
         full_metric_name = self.get_name(metric_name, tags)
 
-        if self.metrics_validator.test(full_metric_name) and 
name_is_otel_safe(self.prefix, full_metric_name):
-            counter = self.metrics_map.get_counter(
-                full_name(prefix=self.prefix, name=full_metric_name), 
attributes=tags
-            )
+        if self.metrics_validator.test(full_metric_name):

Review Comment:
   I see what you tried to do but this ends up being a breaking change.  By 
moving the `full_name()` call into the `get_name()`, we are now passing the 
full name (with prefix) into the validator.test() call which will break all 
user's Allow/Block lists.
   
   If you choose to add the `full_name()` call in there then you must strip 
`prefix` and `delimiter` off before passing it into `validator.test()`, OR add 
some logic to test() which does that before checking the name/pattern match.  
Those both feel like acceptable options, but maybe feel like more work than 
leaving the `full_name()` calls where they are.
   
   Which, in hindsight, brings up the naming of the variable 
`full_metric_name`.  If it includes the prefix, that sounds good, but without 
the prefix then maybe that needs to be renamed.  Naming is one of the hardest 
parts of the job.  Perhaps `base_name` since it gets the prefix added later?



##########
airflow/metrics/statsd_logger.py:
##########
@@ -51,26 +51,22 @@ def prepare_metric_name_with_tags(fn: T) -> T:
 
     @wraps(fn)
     def wrapper(
-        self, metric_name: str | None = None, tags: dict[str, str | int] | 
None = None
+        self, metric_name: str | None = None, tags: dict[str, str] | None = 
None

Review Comment:
   If you are no longer accepting `int` as a value type here, then I don't 
think you need to do the casting on L60?   I'm, not sure why you had added 
`int` as a valid type and then removed it thought, so one or the other should 
be fixed.
   
   If `tags` is going to be a `dict[str, str]` then there is no need to cast it 
to a `dict[str, str]` on L60.  If it is going to be declared as `dict[str, str 
| int]` then we should keep the casing.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to