diff --git a/.changelog/5283.changed b/.changelog/5283.changed new file mode 100644 index 0000000000..f7b3a94391 --- /dev/null +++ b/.changelog/5283.changed @@ -0,0 +1 @@ +metrics: clarify instrument name validation error message to reflect spec constraints (start with a letter, allowed chars, max length 255) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/instrument.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/instrument.py index 946cdf1df1..8b558e6beb 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/instrument.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/instrument.py @@ -45,7 +45,12 @@ _logger = getLogger(__name__) -_ERROR_MESSAGE = ( +_NAME_ERROR_MESSAGE = ( + "Instrument name must be an ASCII string, start with a letter, " + "contain only letters, digits, '_', '.', '-', '/' and be at most 255 characters; got {}" +) + +_UNIT_ERROR_MESSAGE = ( "Expected ASCII string of maximum length 63 characters but got {}" ) @@ -74,11 +79,11 @@ def __init__( if result["name"] is None: # pylint: disable=broad-exception-raised - raise Exception(_ERROR_MESSAGE.format(name)) + raise Exception(_NAME_ERROR_MESSAGE.format(name)) if result["unit"] is None: # pylint: disable=broad-exception-raised - raise Exception(_ERROR_MESSAGE.format(unit)) + raise Exception(_UNIT_ERROR_MESSAGE.format(unit)) name = result["name"] unit = result["unit"] @@ -113,11 +118,11 @@ def __init__( if result["name"] is None: # pylint: disable=broad-exception-raised - raise Exception(_ERROR_MESSAGE.format(name)) + raise Exception(_NAME_ERROR_MESSAGE.format(name)) if result["unit"] is None: # pylint: disable=broad-exception-raised - raise Exception(_ERROR_MESSAGE.format(unit)) + raise Exception(_UNIT_ERROR_MESSAGE.format(unit)) name = result["name"] unit = result["unit"] diff --git a/opentelemetry-sdk/tests/metrics/test_instrument_error_message.py b/opentelemetry-sdk/tests/metrics/test_instrument_error_message.py new file mode 100644 index 0000000000..9e3cc778c3 --- /dev/null +++ b/opentelemetry-sdk/tests/metrics/test_instrument_error_message.py @@ -0,0 +1,26 @@ +import unittest + +from opentelemetry.sdk.metrics._internal.instrument import _Synchronous +from opentelemetry.sdk.util.instrumentation import InstrumentationScope + +class TestInstrumentErrorMessage(unittest.TestCase): + def test_invalid_name_error_message(self): + scope = InstrumentationScope("test") + with self.assertRaises(Exception) as cm: + _Synchronous("1invalid", scope, object()) + msg = str(cm.exception) + self.assertIn("start with a letter", msg) + self.assertIn("255", msg) + + def test_invalid_unit_error_message(self): + scope = InstrumentationScope("test") + # name valid, unit invalid (non-ASCII) + with self.assertRaises(Exception) as cm: + _Synchronous("validname", scope, object(), unit="Ñ") + msg = str(cm.exception) + self.assertIn("maximum length 63", msg) + self.assertIn("ASCII", msg) + + +if __name__ == "__main__": + unittest.main()