diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 66903dc75..fe155b512 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ on: - 'release/*' pull_request: env: - CORE_REPO_SHA: 6bd163f6d670319eba6693b8465a068a1828f484 + CORE_REPO_SHA: 3af190ca973ccef33d8e0816f79ae47b52824a98 jobs: build: diff --git a/exporter/opentelemetry-exporter-datadog/setup.cfg b/exporter/opentelemetry-exporter-datadog/setup.cfg index 915c1cdc1..d2510724a 100644 --- a/exporter/opentelemetry-exporter-datadog/setup.cfg +++ b/exporter/opentelemetry-exporter-datadog/setup.cfg @@ -41,6 +41,7 @@ install_requires = ddtrace>=0.34.0,<0.47.0 opentelemetry-api == 1.0.1.dev0 opentelemetry-sdk == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 [options.packages.find] where = src diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py index da1794aff..10693d0a8 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py @@ -30,6 +30,7 @@ from opentelemetry.exporter.datadog.constants import ( ) from opentelemetry.sdk.trace import sampling from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult +from opentelemetry.semconv.trace import SpanAttributes logger = logging.getLogger(__name__) @@ -225,12 +226,12 @@ def _get_span_name(span): def _get_resource(span): """Get resource name for span""" - if "http.method" in span.attributes: - route = span.attributes.get("http.route") + if SpanAttributes.HTTP_METHOD in span.attributes: + route = span.attributes.get(SpanAttributes.HTTP_ROUTE) return ( - span.attributes["http.method"] + " " + route + span.attributes[SpanAttributes.HTTP_METHOD] + " " + route if route - else span.attributes["http.method"] + else span.attributes[SpanAttributes.HTTP_METHOD] ) return span.name diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py index 9cc7ccbb2..406732615 100644 --- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py +++ b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py @@ -27,6 +27,7 @@ from opentelemetry.exporter import datadog from opentelemetry.sdk import trace from opentelemetry.sdk.trace import Resource, sampling from opentelemetry.sdk.util.instrumentation import InstrumentationInfo +from opentelemetry.semconv.trace import SpanAttributes class MockDatadogSpanExporter(datadog.DatadogSpanExporter): @@ -302,8 +303,14 @@ class TestDatadogSpanExporter(unittest.TestCase): def test_resources(self): test_attributes = [ {}, - {"http.method": "GET", "http.route": "/foo/"}, - {"http.method": "GET", "http.target": "/foo/200"}, + { + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_ROUTE: "/foo/", + }, + { + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_TARGET: "/foo/200", + }, ] for index, test in enumerate(test_attributes): diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg b/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg index 29e2f25b7..ebae507e0 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 aiohttp ~= 3.0 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py index 18de3e84e..18519d9ce 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py @@ -77,6 +77,7 @@ from opentelemetry.instrumentation.utils import ( unwrap, ) from opentelemetry.propagate import inject +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, TracerProvider, get_tracer from opentelemetry.trace.status import Status, StatusCode @@ -169,8 +170,10 @@ def create_trace_config( if trace_config_ctx.span.is_recording(): attributes = { - "http.method": http_method, - "http.url": trace_config_ctx.url_filter(params.url) + SpanAttributes.HTTP_METHOD: http_method, + SpanAttributes.HTTP_URL: trace_config_ctx.url_filter( + params.url + ) if callable(trace_config_ctx.url_filter) else str(params.url), } @@ -196,7 +199,7 @@ def create_trace_config( Status(http_status_to_status_code(int(params.response.status))) ) trace_config_ctx.span.set_attribute( - "http.status_code", params.response.status + SpanAttributes.HTTP_STATUS_CODE, params.response.status ) _end_trace(trace_config_ctx) diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py index 8df65597f..530245bab 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py @@ -30,6 +30,7 @@ from opentelemetry.instrumentation import aiohttp_client from opentelemetry.instrumentation.aiohttp_client import ( AioHttpClientInstrumentor, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -129,11 +130,13 @@ class TestAioHttpIntegration(TestBase): "HTTP GET", (span_status, None), { - "http.method": "GET", - "http.url": "http://{}:{}/test-path?query=param#foobar".format( + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: "http://{}:{}/test-path?query=param#foobar".format( host, port ), - "http.status_code": int(status_code), + SpanAttributes.HTTP_STATUS_CODE: int( + status_code + ), }, ) ] @@ -185,11 +188,13 @@ class TestAioHttpIntegration(TestBase): expected, (StatusCode.UNSET, None), { - "http.method": method, - "http.url": "http://{}:{}{}".format( + SpanAttributes.HTTP_METHOD: method, + SpanAttributes.HTTP_URL: "http://{}:{}{}".format( host, port, path ), - "http.status_code": int(HTTPStatus.OK), + SpanAttributes.HTTP_STATUS_CODE: int( + HTTPStatus.OK + ), }, ) ] @@ -215,11 +220,11 @@ class TestAioHttpIntegration(TestBase): "HTTP GET", (StatusCode.UNSET, None), { - "http.method": "GET", - "http.url": "http://{}:{}/some/path".format( + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: "http://{}:{}/some/path".format( host, port ), - "http.status_code": int(HTTPStatus.OK), + SpanAttributes.HTTP_STATUS_CODE: int(HTTPStatus.OK), }, ) ] @@ -250,7 +255,10 @@ class TestAioHttpIntegration(TestBase): ( "HTTP GET", (expected_status, None), - {"http.method": "GET", "http.url": url}, + { + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: url, + }, ) ] ) @@ -275,8 +283,8 @@ class TestAioHttpIntegration(TestBase): "HTTP GET", (StatusCode.ERROR, None), { - "http.method": "GET", - "http.url": "http://{}:{}/test_timeout".format( + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: "http://{}:{}/test_timeout".format( host, port ), }, @@ -304,8 +312,8 @@ class TestAioHttpIntegration(TestBase): "HTTP GET", (StatusCode.ERROR, None), { - "http.method": "GET", - "http.url": "http://{}:{}/test_too_many_redirects".format( + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: "http://{}:{}/test_too_many_redirects".format( host, port ), }, @@ -352,12 +360,12 @@ class TestAioHttpClientInstrumentor(TestBase): self.get_default_request(), self.URL, self.default_handler ) span = self.assert_spans(1) - self.assertEqual("GET", span.attributes["http.method"]) + self.assertEqual("GET", span.attributes[SpanAttributes.HTTP_METHOD]) self.assertEqual( "http://{}:{}/test-path".format(host, port), - span.attributes["http.url"], + span.attributes[SpanAttributes.HTTP_URL], ) - self.assertEqual(200, span.attributes["http.status_code"]) + self.assertEqual(200, span.attributes[SpanAttributes.HTTP_STATUS_CODE]) def test_instrument_with_existing_trace_config(self): trace_config = aiohttp.TraceConfig() @@ -458,7 +466,7 @@ class TestAioHttpClientInstrumentor(TestBase): span = self.assert_spans(1) self.assertEqual( "http://{}:{}/test-path".format(host, port), - span.attributes["http.url"], + span.attributes[SpanAttributes.HTTP_URL], ) def test_span_name(self): diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg b/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg index 33b41c136..60f7fa85e 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation-dbapi == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 aiopg >= 0.13.0 diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py index 50766aee6..571fba522 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py @@ -26,6 +26,7 @@ from opentelemetry.instrumentation.aiopg.aiopg_integration import ( AiopgIntegration, ) from opentelemetry.sdk import resources +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase @@ -258,16 +259,24 @@ class TestAiopgIntegration(TestBase): self.assertEqual(span.name, "Test") self.assertIs(span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(span.attributes["db.system"], "testcomponent") - self.assertEqual(span.attributes["db.name"], "testdatabase") - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "testcomponent" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_NAME], "testdatabase" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) self.assertEqual( span.attributes["db.statement.parameters"], "('param1Value', False)", ) - self.assertEqual(span.attributes["db.user"], "testuser") - self.assertEqual(span.attributes["net.peer.name"], "testhost") - self.assertEqual(span.attributes["net.peer.port"], 123) + self.assertEqual(span.attributes[SpanAttributes.DB_USER], "testuser") + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], "testhost" + ) + self.assertEqual(span.attributes[SpanAttributes.NET_PEER_PORT], 123) self.assertIs(span.status.status_code, trace_api.StatusCode.UNSET) def test_span_not_recording(self): @@ -314,7 +323,9 @@ class TestAiopgIntegration(TestBase): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) self.assertIs(span.status.status_code, trace_api.StatusCode.ERROR) self.assertEqual(span.status.description, "Exception: Test Exception") @@ -329,7 +340,9 @@ class TestAiopgIntegration(TestBase): self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) def test_callproc(self): db_integration = AiopgIntegration(self.tracer, "testcomponent") @@ -343,7 +356,8 @@ class TestAiopgIntegration(TestBase): self.assertEqual(len(spans_list), 1) span = spans_list[0] self.assertEqual( - span.attributes["db.statement"], "Test stored procedure" + span.attributes[SpanAttributes.DB_STATEMENT], + "Test stored procedure", ) def test_wrap_connect(self): diff --git a/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg b/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg index 470bf334e..48eb64142 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 asgiref ~= 3.0 diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 3fe15b506..8de64290d 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -30,6 +30,7 @@ from opentelemetry.instrumentation.asgi.version import __version__ # noqa from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.propagate import extract from opentelemetry.propagators.textmap import Getter +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode @@ -80,27 +81,29 @@ def collect_request_attributes(scope): http_url = http_url + ("?" + urllib.parse.unquote(query_string)) result = { - "http.scheme": scope.get("scheme"), - "http.host": server_host, - "net.host.port": port, - "http.flavor": scope.get("http_version"), - "http.target": scope.get("path"), - "http.url": http_url, + SpanAttributes.HTTP_SCHEME: scope.get("scheme"), + SpanAttributes.HTTP_HOST: server_host, + SpanAttributes.NET_HOST_PORT: port, + SpanAttributes.HTTP_FLAVOR: scope.get("http_version"), + SpanAttributes.HTTP_TARGET: scope.get("path"), + SpanAttributes.HTTP_URL: http_url, } http_method = scope.get("method") if http_method: - result["http.method"] = http_method + result[SpanAttributes.HTTP_METHOD] = http_method http_host_value_list = asgi_getter.get(scope, "host") if http_host_value_list: - result["http.server_name"] = ",".join(http_host_value_list) + result[SpanAttributes.HTTP_SERVER_NAME] = ",".join( + http_host_value_list + ) http_user_agent = asgi_getter.get(scope, "user-agent") if http_user_agent: - result["http.user_agent"] = http_user_agent[0] + result[SpanAttributes.HTTP_USER_AGENT] = http_user_agent[0] if "client" in scope and scope["client"] is not None: - result["net.peer.ip"] = scope.get("client")[0] - result["net.peer.port"] = scope.get("client")[1] + result[SpanAttributes.NET_PEER_IP] = scope.get("client")[0] + result[SpanAttributes.NET_PEER_PORT] = scope.get("client")[1] # remove None values result = {k: v for k, v in result.items() if v is not None} @@ -133,7 +136,7 @@ def set_status_code(span, status_code): ) ) else: - span.set_attribute("http.status_code", status_code) + span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) span.set_status(Status(http_status_to_status_code(status_code))) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py index 7c4ae20a7..0f1e8e7db 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py @@ -18,6 +18,7 @@ import unittest.mock as mock import opentelemetry.instrumentation.asgi as otel_asgi from opentelemetry import trace as trace_api +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.asgitestutil import ( AsgiTestBase, setup_testing_defaults, @@ -121,7 +122,7 @@ class TestAsgiApplication(AsgiTestBase): "name": "GET asgi.http.send", "kind": trace_api.SpanKind.INTERNAL, "attributes": { - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, "type": "http.response.start", }, }, @@ -134,15 +135,15 @@ class TestAsgiApplication(AsgiTestBase): "name": "GET asgi", "kind": trace_api.SpanKind.SERVER, "attributes": { - "http.method": "GET", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "127.0.0.1", - "http.flavor": "1.0", - "http.target": "/", - "http.url": "http://127.0.0.1/", - "net.peer.ip": "127.0.0.1", - "net.peer.port": 32767, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "127.0.0.1", + SpanAttributes.HTTP_FLAVOR: "1.0", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.HTTP_URL: "http://127.0.0.1/", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.NET_PEER_PORT: 32767, }, }, ] @@ -216,9 +217,9 @@ class TestAsgiApplication(AsgiTestBase): def update_expected_server(expected): expected[3]["attributes"].update( { - "http.host": "0.0.0.0", - "net.host.port": 80, - "http.url": "http://0.0.0.0/", + SpanAttributes.HTTP_HOST: "0.0.0.0", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_URL: "http://0.0.0.0/", } ) return expected @@ -236,7 +237,7 @@ class TestAsgiApplication(AsgiTestBase): def update_expected_server(expected): expected[3]["attributes"].update( - {"http.server_name": hostname.decode("utf8")} + {SpanAttributes.HTTP_SERVER_NAME: hostname.decode("utf8")} ) return expected @@ -253,7 +254,7 @@ class TestAsgiApplication(AsgiTestBase): def update_expected_user_agent(expected): expected[3]["attributes"].update( - {"http.user_agent": user_agent.decode("utf8")} + {SpanAttributes.HTTP_USER_AGENT: user_agent.decode("utf8")} ) return expected @@ -320,37 +321,43 @@ class TestAsgiAttributes(unittest.TestCase): self.assertDictEqual( attrs, { - "http.method": "GET", - "http.host": "127.0.0.1", - "http.target": "/", - "http.url": "http://127.0.0.1/?foo=bar", - "net.host.port": 80, - "http.scheme": "http", - "http.server_name": "test", - "http.flavor": "1.0", - "net.peer.ip": "127.0.0.1", - "net.peer.port": 32767, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_HOST: "127.0.0.1", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.HTTP_URL: "http://127.0.0.1/?foo=bar", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_SERVER_NAME: "test", + SpanAttributes.HTTP_FLAVOR: "1.0", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.NET_PEER_PORT: 32767, }, ) def test_query_string(self): self.scope["query_string"] = b"foo=bar" attrs = otel_asgi.collect_request_attributes(self.scope) - self.assertEqual(attrs["http.url"], "http://127.0.0.1/?foo=bar") + self.assertEqual( + attrs[SpanAttributes.HTTP_URL], "http://127.0.0.1/?foo=bar" + ) def test_query_string_percent_bytes(self): self.scope["query_string"] = b"foo%3Dbar" attrs = otel_asgi.collect_request_attributes(self.scope) - self.assertEqual(attrs["http.url"], "http://127.0.0.1/?foo=bar") + self.assertEqual( + attrs[SpanAttributes.HTTP_URL], "http://127.0.0.1/?foo=bar" + ) def test_query_string_percent_str(self): self.scope["query_string"] = "foo%3Dbar" attrs = otel_asgi.collect_request_attributes(self.scope) - self.assertEqual(attrs["http.url"], "http://127.0.0.1/?foo=bar") + self.assertEqual( + attrs[SpanAttributes.HTTP_URL], "http://127.0.0.1/?foo=bar" + ) def test_response_attributes(self): otel_asgi.set_status_code(self.span, 404) - expected = (mock.call("http.status_code", 404),) + expected = (mock.call(SpanAttributes.HTTP_STATUS_CODE, 404),) self.assertEqual(self.span.set_attribute.call_count, 1) self.assertEqual(self.span.set_attribute.call_count, 1) self.span.set_attribute.assert_has_calls(expected, any_order=True) diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg b/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg index 16b175f04..4873ada49 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 asyncpg >= 0.12.0 diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py index 0a558cb3d..3db2be0ef 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py @@ -42,6 +42,11 @@ from opentelemetry import trace from opentelemetry.instrumentation.asyncpg.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.semconv.trace import ( + DbSystemValues, + NetTransportValues, + SpanAttributes, +) from opentelemetry.trace import SpanKind from opentelemetry.trace.status import Status, StatusCode @@ -50,7 +55,9 @@ _APPLIED = "_opentelemetry_tracer" def _hydrate_span_from_args(connection, query, parameters) -> dict: """Get network and database attributes from connection.""" - span_attributes = {"db.system": "postgresql"} + span_attributes = { + SpanAttributes.DB_SYSTEM: DbSystemValues.POSTGRESQL.value + } # connection contains _params attribute which is a namedtuple ConnectionParameters. # https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L68 @@ -58,24 +65,28 @@ def _hydrate_span_from_args(connection, query, parameters) -> dict: params = getattr(connection, "_params", None) dbname = getattr(params, "database", None) if dbname: - span_attributes["db.name"] = dbname + span_attributes[SpanAttributes.DB_NAME] = dbname user = getattr(params, "user", None) if user: - span_attributes["db.user"] = user + span_attributes[SpanAttributes.DB_USER] = user # connection contains _addr attribute which is either a host/port tuple, or unix socket string # https://magicstack.github.io/asyncpg/current/_modules/asyncpg/connection.html addr = getattr(connection, "_addr", None) if isinstance(addr, tuple): - span_attributes["net.peer.name"] = addr[0] - span_attributes["net.peer.port"] = addr[1] - span_attributes["net.transport"] = "IP.TCP" + span_attributes[SpanAttributes.NET_PEER_NAME] = addr[0] + span_attributes[SpanAttributes.NET_PEER_PORT] = addr[1] + span_attributes[ + SpanAttributes.NET_TRANSPORT + ] = NetTransportValues.IP_TCP.value elif isinstance(addr, str): - span_attributes["net.peer.name"] = addr - span_attributes["net.transport"] = "Unix" + span_attributes[SpanAttributes.NET_PEER_NAME] = addr + span_attributes[ + SpanAttributes.NET_TRANSPORT + ] = NetTransportValues.UNIX.value if query is not None: - span_attributes["db.statement"] = query + span_attributes[SpanAttributes.DB_STATEMENT] = query if parameters is not None and len(parameters) > 0: span_attributes["db.statement.parameters"] = str(parameters) diff --git a/instrumentation/opentelemetry-instrumentation-boto/setup.cfg b/instrumentation/opentelemetry-instrumentation-boto/setup.cfg index a6aaafdbc..e2680322d 100644 --- a/instrumentation/opentelemetry-instrumentation-boto/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-boto/setup.cfg @@ -40,6 +40,7 @@ packages=find_namespace: install_requires = boto ~= 2.0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-instrumentation-botocore == 0.20.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py b/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py index 6921d60bc..6a0df422d 100644 --- a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py @@ -51,6 +51,7 @@ from opentelemetry.instrumentation.boto.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import unwrap from opentelemetry.sdk.trace import Resource +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer logger = logging.getLogger(__name__) @@ -147,9 +148,11 @@ class BotoInstrumentor(BaseInstrumentor): span.set_attribute(key, value) span.set_attribute( - "http.status_code", getattr(result, "status") + SpanAttributes.HTTP_STATUS_CODE, getattr(result, "status") + ) + span.set_attribute( + SpanAttributes.HTTP_METHOD, getattr(result, "_method") ) - span.set_attribute("http.method", getattr(result, "_method")) return result diff --git a/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py b/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py index ac052198b..dda22ba44 100644 --- a/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py @@ -28,12 +28,13 @@ from moto import ( # pylint: disable=import-error ) from opentelemetry.instrumentation.boto import BotoInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase def assert_span_http_status_code(span, code): """Assert on the span's 'http.status_code' tag""" - tag = span.attributes["http.status_code"] + tag = span.attributes[SpanAttributes.HTTP_STATUS_CODE] assert tag == code, "%r != %r" % (tag, code) @@ -59,7 +60,7 @@ class TestBotoInstrumentor(TestBase): span = spans[0] self.assertEqual(span.attributes["aws.operation"], "DescribeInstances") assert_span_http_status_code(span, 200) - self.assertEqual(span.attributes["http.method"], "POST") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "POST") self.assertEqual(span.attributes["aws.region"], "us-west-2") # Create an instance @@ -72,7 +73,7 @@ class TestBotoInstrumentor(TestBase): assert_span_http_status_code(span, 200) self.assertEqual(span.attributes["endpoint"], "ec2") self.assertEqual(span.attributes["http_method"], "runinstances") - self.assertEqual(span.attributes["http.method"], "POST") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "POST") self.assertEqual(span.attributes["aws.region"], "us-west-2") self.assertEqual(span.name, "ec2.command") @@ -119,7 +120,7 @@ class TestBotoInstrumentor(TestBase): self.assertEqual(len(spans), 1) span = spans[0] assert_span_http_status_code(span, 200) - self.assertEqual(span.attributes["http.method"], "GET") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET") self.assertEqual(span.attributes["aws.operation"], "get_all_buckets") # Create a bucket command @@ -129,7 +130,7 @@ class TestBotoInstrumentor(TestBase): self.assertEqual(len(spans), 2) span = spans[1] assert_span_http_status_code(span, 200) - self.assertEqual(span.attributes["http.method"], "PUT") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "PUT") self.assertEqual(span.attributes["path"], "/") self.assertEqual(span.attributes["aws.operation"], "create_bucket") @@ -142,7 +143,7 @@ class TestBotoInstrumentor(TestBase): assert_span_http_status_code(span, 200) self.assertEqual(span.attributes["endpoint"], "s3") self.assertEqual(span.attributes["http_method"], "head") - self.assertEqual(span.attributes["http.method"], "HEAD") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "HEAD") self.assertEqual(span.attributes["aws.operation"], "head_bucket") self.assertEqual(span.name, "s3.command") @@ -224,7 +225,7 @@ class TestBotoInstrumentor(TestBase): assert_span_http_status_code(span, 200) self.assertEqual(span.attributes["endpoint"], "lambda") self.assertEqual(span.attributes["http_method"], "get") - self.assertEqual(span.attributes["http.method"], "GET") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET") self.assertEqual(span.attributes["aws.region"], "us-east-2") self.assertEqual(span.attributes["aws.operation"], "list_functions") diff --git a/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg b/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg index 9b5bf010f..d1979ecde 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg @@ -40,6 +40,7 @@ packages=find_namespace: install_requires = botocore ~= 1.0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py index e418064c9..6f717660c 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py @@ -57,6 +57,7 @@ from opentelemetry.instrumentation.botocore.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import unwrap from opentelemetry.propagate import inject +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer logger = logging.getLogger(__name__) @@ -159,7 +160,8 @@ class BotocoreInstrumentor(BaseInstrumentor): if "HTTPStatusCode" in metadata: span.set_attribute( - "http.status_code", metadata["HTTPStatusCode"], + SpanAttributes.HTTP_STATUS_CODE, + metadata["HTTPStatusCode"], ) if error: diff --git a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py index f6f86d5aa..2f6707838 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py @@ -32,6 +32,7 @@ from opentelemetry import trace as trace_api from opentelemetry.context import attach, detach, set_value from opentelemetry.instrumentation.botocore import BotocoreInstrumentor from opentelemetry.propagate import get_global_textmap, set_global_textmap +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator from opentelemetry.test.test_base import TestBase @@ -70,7 +71,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": "fdcdcab1-ae5c-489e-9c33-4637c5dda355", "aws.service": "ec2", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) self.assertEqual(span.name, "ec2") @@ -116,7 +117,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-west-2", "aws.service": "s3", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -160,7 +161,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-west-2", "aws.service": "s3", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) put_object_attributes = spans[1].attributes @@ -171,7 +172,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-west-2", "aws.service": "s3", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) self.assertTrue("params.Body" not in spans[1].attributes.keys()) @@ -183,7 +184,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-west-2", "aws.service": "s3", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -207,7 +208,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": actual["aws.request_id"], "aws.service": "sqs", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -238,7 +239,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": create_queue_attributes["aws.request_id"], "aws.service": "sqs", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) send_msg_attributes = spans[1].attributes @@ -254,7 +255,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": send_msg_attributes["aws.request_id"], "aws.service": "sqs", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -277,7 +278,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-east-1", "aws.service": "kinesis", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -323,7 +324,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-east-1", "aws.service": "lambda", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -344,7 +345,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.region": "us-east-1", "aws.service": "kms", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -369,7 +370,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": "c6104cbe-af31-11e0-8154-cbc7ccf896c7", "aws.service": "sts", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -406,7 +407,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": "fdcdcab1-ae5c-489e-9c33-4637c5dda355", "aws.service": "ec2", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -475,7 +476,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.request_id": create_table_attributes["aws.request_id"], "aws.table_name": "test_table_name", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) put_item_attributes = spans[1].attributes @@ -491,7 +492,7 @@ class TestBotocoreInstrumentor(TestBase): "aws.service": "dynamodb", "aws.table_name": "test_table_name", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) get_item_attributes = spans[2].attributes @@ -507,6 +508,6 @@ class TestBotocoreInstrumentor(TestBase): "aws.service": "dynamodb", "aws.table_name": "test_table_name", "retry_attempts": 0, - "http.status_code": 200, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) diff --git a/instrumentation/opentelemetry-instrumentation-celery/setup.cfg b/instrumentation/opentelemetry-instrumentation-celery/setup.cfg index a27f32cac..f64a07cb8 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-celery/setup.cfg @@ -40,6 +40,7 @@ packages=find_namespace: install_requires = celery >= 4.0, < 6.0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py index cd12677a5..6518b6c2a 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py @@ -62,6 +62,7 @@ from opentelemetry.instrumentation.celery.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.propagate import extract, inject from opentelemetry.propagators.textmap import Getter +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode logger = logging.getLogger(__name__) @@ -75,7 +76,6 @@ _TASK_RETRY_REASON_KEY = "celery.retry.reason" _TASK_REVOKED_REASON_KEY = "celery.revoked.reason" _TASK_REVOKED_TERMINATED_SIGNAL_KEY = "celery.terminated.signal" _TASK_NAME_KEY = "celery.task_name" -_MESSAGE_ID_ATTRIBUTE_NAME = "messaging.message_id" class CeleryGetter(Getter): @@ -182,7 +182,7 @@ class CeleryInstrumentor(BaseInstrumentor): # apply some attributes here because most of the data is not available if span.is_recording(): span.set_attribute(_TASK_TAG_KEY, _TASK_APPLY_ASYNC) - span.set_attribute(_MESSAGE_ID_ATTRIBUTE_NAME, task_id) + span.set_attribute(SpanAttributes.MESSAGING_MESSAGE_ID, task_id) span.set_attribute(_TASK_NAME_KEY, task.name) utils.set_attributes_from_context(span, kwargs) diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py index 9a4413459..bdd9a5944 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py +++ b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py @@ -16,6 +16,8 @@ import logging from celery import registry # pylint: disable=no-name-in-module +from opentelemetry.semconv.trace import SpanAttributes + logger = logging.getLogger(__name__) # Celery Context key @@ -77,21 +79,23 @@ def set_attributes_from_context(span, context): # Get also destination from this routing_key = value.get("routing_key") if routing_key is not None: - span.set_attribute("messaging.destination", routing_key) + span.set_attribute( + SpanAttributes.MESSAGING_DESTINATION, routing_key + ) value = str(value) elif key == "id": - attribute_name = "messaging.message_id" + attribute_name = SpanAttributes.MESSAGING_MESSAGE_ID elif key == "correlation_id": - attribute_name = "messaging.conversation_id" + attribute_name = SpanAttributes.MESSAGING_CONVERSATION_ID elif key == "routing_key": - attribute_name = "messaging.destination" + attribute_name = SpanAttributes.MESSAGING_DESTINATION # according to https://docs.celeryproject.org/en/stable/userguide/routing.html#exchange-types elif key == "declare": - attribute_name = "messaging.destination_kind" + attribute_name = SpanAttributes.MESSAGING_DESTINATION_KIND for declare in value: if declare.exchange.type == "direct": value = "queue" diff --git a/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py b/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py index 3a05ebf33..17538aaf5 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py +++ b/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py @@ -16,6 +16,7 @@ import threading import time from opentelemetry.instrumentation.celery import CeleryInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import SpanKind @@ -54,7 +55,7 @@ class TestCeleryInstrumentation(TestBase): { "celery.action": "run", "celery.state": "SUCCESS", - "messaging.destination": "celery", + SpanAttributes.MESSAGING_DESTINATION: "celery", "celery.task_name": "tests.celery_test_tasks.task_add", }, ) @@ -68,8 +69,8 @@ class TestCeleryInstrumentation(TestBase): { "celery.action": "apply_async", "celery.task_name": "tests.celery_test_tasks.task_add", - "messaging.destination_kind": "queue", - "messaging.destination": "celery", + SpanAttributes.MESSAGING_DESTINATION_KIND: "queue", + SpanAttributes.MESSAGING_DESTINATION: "celery", }, ) diff --git a/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py b/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py index f48f06aaf..b04521eb0 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py +++ b/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py @@ -20,6 +20,7 @@ from celery import Celery from opentelemetry import trace as trace_api from opentelemetry.instrumentation.celery import utils from opentelemetry.sdk import trace +from opentelemetry.semconv.trace import SpanAttributes class TestUtils(unittest.TestCase): @@ -46,13 +47,15 @@ class TestUtils(unittest.TestCase): utils.set_attributes_from_context(span, context) self.assertEqual( - span.attributes.get("messaging.message_id"), "44b7f305" + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID), + "44b7f305", ) self.assertEqual( - span.attributes.get("messaging.conversation_id"), "44b7f305" + span.attributes.get(SpanAttributes.MESSAGING_CONVERSATION_ID), + "44b7f305", ) self.assertEqual( - span.attributes.get("messaging.destination"), "celery" + span.attributes.get(SpanAttributes.MESSAGING_DESTINATION), "celery" ) self.assertEqual( diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg b/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg index 072d178bf..a5170e5d2 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py index 7a99fc793..6ceb66cae 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py @@ -46,6 +46,7 @@ import wrapt from opentelemetry import trace as trace_api from opentelemetry.instrumentation.dbapi.version import __version__ from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, TracerProvider, get_tracer from opentelemetry.trace.status import Status, StatusCode @@ -278,13 +279,13 @@ class DatabaseApiIntegration: if user and isinstance(user, bytes): user = user.decode() if user is not None: - self.span_attributes["db.user"] = str(user) + self.span_attributes[SpanAttributes.DB_USER] = str(user) host = self.connection_props.get("host") if host is not None: - self.span_attributes["net.peer.name"] = host + self.span_attributes[SpanAttributes.NET_PEER_NAME] = host port = self.connection_props.get("port") if port is not None: - self.span_attributes["net.peer.port"] = port + self.span_attributes[SpanAttributes.NET_PEER_PORT] = port def get_traced_connection_proxy( @@ -325,10 +326,12 @@ class CursorTracer: return statement = self.get_statement(cursor, args) span.set_attribute( - "db.system", self._db_api_integration.database_system + SpanAttributes.DB_SYSTEM, self._db_api_integration.database_system ) - span.set_attribute("db.name", self._db_api_integration.database) - span.set_attribute("db.statement", statement) + span.set_attribute( + SpanAttributes.DB_NAME, self._db_api_integration.database + ) + span.set_attribute(SpanAttributes.DB_STATEMENT, statement) for ( attribute_key, diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py index 6ff25881d..5fa25a998 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py +++ b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py @@ -18,6 +18,7 @@ from unittest import mock from opentelemetry import trace as trace_api from opentelemetry.instrumentation import dbapi +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase @@ -53,13 +54,21 @@ class TestDBApiIntegration(TestBase): self.assertEqual(span.name, "Test") self.assertIs(span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(span.attributes["db.system"], "testcomponent") - self.assertEqual(span.attributes["db.name"], "testdatabase") - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "testcomponent" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_NAME], "testdatabase" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) self.assertFalse("db.statement.parameters" in span.attributes) - self.assertEqual(span.attributes["db.user"], "testuser") - self.assertEqual(span.attributes["net.peer.name"], "testhost") - self.assertEqual(span.attributes["net.peer.port"], 123) + self.assertEqual(span.attributes[SpanAttributes.DB_USER], "testuser") + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], "testhost" + ) + self.assertEqual(span.attributes[SpanAttributes.NET_PEER_PORT], 123) self.assertIs(span.status.status_code, trace_api.StatusCode.UNSET) def test_span_name(self): @@ -113,16 +122,24 @@ class TestDBApiIntegration(TestBase): self.assertEqual(span.name, "Test") self.assertIs(span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(span.attributes["db.system"], "testcomponent") - self.assertEqual(span.attributes["db.name"], "testdatabase") - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "testcomponent" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_NAME], "testdatabase" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) self.assertEqual( span.attributes["db.statement.parameters"], "('param1Value', False)", ) - self.assertEqual(span.attributes["db.user"], "testuser") - self.assertEqual(span.attributes["net.peer.name"], "testhost") - self.assertEqual(span.attributes["net.peer.port"], 123) + self.assertEqual(span.attributes[SpanAttributes.DB_USER], "testuser") + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], "testhost" + ) + self.assertEqual(span.attributes[SpanAttributes.NET_PEER_PORT], 123) self.assertIs(span.status.status_code, trace_api.StatusCode.UNSET) def test_span_not_recording(self): @@ -169,7 +186,9 @@ class TestDBApiIntegration(TestBase): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) self.assertIs(span.status.status_code, trace_api.StatusCode.ERROR) self.assertEqual(span.status.description, "Exception: Test Exception") @@ -185,7 +204,9 @@ class TestDBApiIntegration(TestBase): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.attributes["db.statement"], "Test query") + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "Test query" + ) def test_callproc(self): db_integration = dbapi.DatabaseApiIntegration( @@ -200,7 +221,8 @@ class TestDBApiIntegration(TestBase): self.assertEqual(len(spans_list), 1) span = spans_list[0] self.assertEqual( - span.attributes["db.statement"], "Test stored procedure" + span.attributes[SpanAttributes.DB_STATEMENT], + "Test stored procedure", ) @mock.patch("opentelemetry.instrumentation.dbapi") diff --git a/instrumentation/opentelemetry-instrumentation-django/setup.cfg b/instrumentation/opentelemetry-instrumentation-django/setup.cfg index 3ac01595c..9ed87ab53 100644 --- a/instrumentation/opentelemetry-instrumentation-django/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-django/setup.cfg @@ -43,6 +43,7 @@ install_requires = opentelemetry-instrumentation-wsgi == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 [options.extras_require] test = diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index 9b526c521..9d01da299 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -30,6 +30,7 @@ from opentelemetry.instrumentation.wsgi import ( wsgi_getter, ) from opentelemetry.propagate import extract +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import Span, SpanKind, get_tracer, use_span from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs @@ -48,10 +49,24 @@ except ImportError: _logger = getLogger(__name__) _attributes_by_preference = [ - ["http.scheme", "http.host", "http.target"], - ["http.scheme", "http.server_name", "net.host.port", "http.target"], - ["http.scheme", "net.host.name", "net.host.port", "http.target"], - ["http.url"], + [ + SpanAttributes.HTTP_SCHEME, + SpanAttributes.HTTP_HOST, + SpanAttributes.HTTP_TARGET, + ], + [ + SpanAttributes.HTTP_SCHEME, + SpanAttributes.HTTP_SERVER_NAME, + SpanAttributes.NET_HOST_PORT, + SpanAttributes.HTTP_TARGET, + ], + [ + SpanAttributes.HTTP_SCHEME, + SpanAttributes.NET_HOST_NAME, + SpanAttributes.NET_HOST_PORT, + SpanAttributes.HTTP_TARGET, + ], + [SpanAttributes.HTTP_URL], ] @@ -159,7 +174,7 @@ class _DjangoMiddleware(MiddlewareMixin): if match: route = getattr(match, "route") if route: - span.set_attribute("http.route", route) + span.set_attribute(SpanAttributes.HTTP_ROUTE, route) def process_exception(self, request, exception): if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index b6174e300..d57eaf72f 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -31,6 +31,7 @@ from opentelemetry.instrumentation.propagators import ( set_global_response_propagator, ) from opentelemetry.sdk.trace import Span +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.trace import ( @@ -119,17 +120,17 @@ class TestMiddleware(TestBase, WsgiTestBase): ) self.assertEqual(span.kind, SpanKind.SERVER) self.assertEqual(span.status.status_code, StatusCode.UNSET) - self.assertEqual(span.attributes["http.method"], "GET") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET") self.assertEqual( - span.attributes["http.url"], + span.attributes[SpanAttributes.HTTP_URL], "http://testserver/route/2020/template/", ) self.assertEqual( - span.attributes["http.route"], + span.attributes[SpanAttributes.HTTP_ROUTE], "^route/(?P[0-9]{4})/template/$", ) - self.assertEqual(span.attributes["http.scheme"], "http") - self.assertEqual(span.attributes["http.status_code"], 200) + self.assertEqual(span.attributes[SpanAttributes.HTTP_SCHEME], "http") + self.assertEqual(span.attributes[SpanAttributes.HTTP_STATUS_CODE], 200) def test_traced_get(self): Client().get("/traced/") @@ -144,13 +145,16 @@ class TestMiddleware(TestBase, WsgiTestBase): ) self.assertEqual(span.kind, SpanKind.SERVER) self.assertEqual(span.status.status_code, StatusCode.UNSET) - self.assertEqual(span.attributes["http.method"], "GET") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET") self.assertEqual( - span.attributes["http.url"], "http://testserver/traced/" + span.attributes[SpanAttributes.HTTP_URL], + "http://testserver/traced/", ) - self.assertEqual(span.attributes["http.route"], "^traced/") - self.assertEqual(span.attributes["http.scheme"], "http") - self.assertEqual(span.attributes["http.status_code"], 200) + self.assertEqual( + span.attributes[SpanAttributes.HTTP_ROUTE], "^traced/" + ) + self.assertEqual(span.attributes[SpanAttributes.HTTP_SCHEME], "http") + self.assertEqual(span.attributes[SpanAttributes.HTTP_STATUS_CODE], 200) def test_not_recording(self): mock_tracer = Mock() @@ -178,13 +182,16 @@ class TestMiddleware(TestBase, WsgiTestBase): ) self.assertEqual(span.kind, SpanKind.SERVER) self.assertEqual(span.status.status_code, StatusCode.UNSET) - self.assertEqual(span.attributes["http.method"], "POST") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "POST") self.assertEqual( - span.attributes["http.url"], "http://testserver/traced/" + span.attributes[SpanAttributes.HTTP_URL], + "http://testserver/traced/", ) - self.assertEqual(span.attributes["http.route"], "^traced/") - self.assertEqual(span.attributes["http.scheme"], "http") - self.assertEqual(span.attributes["http.status_code"], 200) + self.assertEqual( + span.attributes[SpanAttributes.HTTP_ROUTE], "^traced/" + ) + self.assertEqual(span.attributes[SpanAttributes.HTTP_SCHEME], "http") + self.assertEqual(span.attributes[SpanAttributes.HTTP_STATUS_CODE], 200) def test_error(self): with self.assertRaises(ValueError): @@ -200,19 +207,24 @@ class TestMiddleware(TestBase, WsgiTestBase): ) self.assertEqual(span.kind, SpanKind.SERVER) self.assertEqual(span.status.status_code, StatusCode.ERROR) - self.assertEqual(span.attributes["http.method"], "GET") + self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET") self.assertEqual( - span.attributes["http.url"], "http://testserver/error/" + span.attributes[SpanAttributes.HTTP_URL], + "http://testserver/error/", ) - self.assertEqual(span.attributes["http.route"], "^error/") - self.assertEqual(span.attributes["http.scheme"], "http") - self.assertEqual(span.attributes["http.status_code"], 500) + self.assertEqual(span.attributes[SpanAttributes.HTTP_ROUTE], "^error/") + self.assertEqual(span.attributes[SpanAttributes.HTTP_SCHEME], "http") + self.assertEqual(span.attributes[SpanAttributes.HTTP_STATUS_CODE], 500) self.assertEqual(len(span.events), 1) event = span.events[0] self.assertEqual(event.name, "exception") - self.assertEqual(event.attributes["exception.type"], "ValueError") - self.assertEqual(event.attributes["exception.message"], "error") + self.assertEqual( + event.attributes[SpanAttributes.EXCEPTION_TYPE], "ValueError" + ) + self.assertEqual( + event.attributes[SpanAttributes.EXCEPTION_MESSAGE], "error" + ) def test_exclude_lists(self): client = Client() diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg b/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg index 8049ad936..05a13a278 100644 --- a/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 wrapt >= 1.0.0, < 2.0.0 elasticsearch >= 2.0 diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py index 1dd245a8d..34c894a17 100644 --- a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py @@ -56,6 +56,7 @@ from wrapt import wrap_function_wrapper as _wrap from opentelemetry.instrumentation.elasticsearch.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer from opentelemetry.trace.status import Status, StatusCode @@ -124,14 +125,14 @@ def _wrap_perform_request(tracer, span_name_prefix): ) as span: if span.is_recording(): attributes = { - "db.system": "elasticsearch", + SpanAttributes.DB_SYSTEM: "elasticsearch", } if url: attributes["elasticsearch.url"] = url if method: attributes["elasticsearch.method"] = method if body: - attributes["db.statement"] = str(body) + attributes[SpanAttributes.DB_STATEMENT] = str(body) if params: attributes["elasticsearch.params"] = str(params) for key, value in attributes.items(): diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py index 885ce7003..49301a061 100644 --- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py +++ b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py @@ -27,6 +27,7 @@ from opentelemetry import trace from opentelemetry.instrumentation.elasticsearch import ( ElasticsearchInstrumentor, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -249,10 +250,10 @@ class TestElasticsearchIntegration(TestBase): self.assertEqual( span.attributes, { - "db.system": "elasticsearch", + SpanAttributes.DB_SYSTEM: "elasticsearch", "elasticsearch.url": "/test-index/_search", "elasticsearch.method": helpers.dsl_search_method, - "db.statement": str( + SpanAttributes.DB_STATEMENT: str( { "query": { "bool": { @@ -276,7 +277,7 @@ class TestElasticsearchIntegration(TestBase): self.assertEqual( span1.attributes, { - "db.system": "elasticsearch", + SpanAttributes.DB_SYSTEM: "elasticsearch", "elasticsearch.url": "/test-index", "elasticsearch.method": "HEAD", }, @@ -284,13 +285,13 @@ class TestElasticsearchIntegration(TestBase): self.assertEqual(span2.name, "Elasticsearch/test-index") attributes = { - "db.system": "elasticsearch", + SpanAttributes.DB_SYSTEM: "elasticsearch", "elasticsearch.url": "/test-index", "elasticsearch.method": "PUT", } self.assert_span_has_attributes(span2, attributes) self.assertEqual( - literal_eval(span2.attributes["db.statement"]), + literal_eval(span2.attributes[SpanAttributes.DB_STATEMENT]), helpers.dsl_create_statement, ) @@ -310,13 +311,13 @@ class TestElasticsearchIntegration(TestBase): span = spans[0] self.assertEqual(span.name, helpers.dsl_index_span_name) attributes = { - "db.system": "elasticsearch", + SpanAttributes.DB_SYSTEM: "elasticsearch", "elasticsearch.url": helpers.dsl_index_url, "elasticsearch.method": "PUT", } self.assert_span_has_attributes(span, attributes) self.assertEqual( - literal_eval(span.attributes["db.statement"]), + literal_eval(span.attributes[SpanAttributes.DB_STATEMENT]), { "body": "A few words here, a few words there", "title": "About searching", diff --git a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg index 3f9989549..cf9d9075e 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg @@ -44,6 +44,7 @@ install_requires = opentelemetry-util-http == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 [options.extras_require] test = diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py index e5b6bae7d..6eea16e04 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -108,6 +108,7 @@ from opentelemetry.instrumentation.utils import ( http_status_to_status_code, ) from opentelemetry.propagate import extract +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status from opentelemetry.util._time import _time_ns from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs @@ -270,7 +271,7 @@ class _TraceMiddleware: except ValueError: pass finally: - span.set_attribute("http.status_code", status_code) + span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) span.set_status( Status( status_code=http_status_to_status_code(status_code), diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py index 016529a42..0789bed8b 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py @@ -22,6 +22,7 @@ from opentelemetry.instrumentation.propagators import ( get_global_response_propagator, set_global_response_propagator, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode, format_span_id, format_trace_id from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs @@ -104,17 +105,17 @@ class TestFalconInstrumentation(TestFalconBase): self.assert_span_has_attributes( span, { - "http.method": method, - "http.server_name": "falconframework.org", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "falconframework.org", - "http.target": "/", - "net.peer.ip": "127.0.0.1", - "net.peer.port": "65133", - "http.flavor": "1.1", + SpanAttributes.HTTP_METHOD: method, + SpanAttributes.HTTP_SERVER_NAME: "falconframework.org", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "falconframework.org", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.NET_PEER_PORT: "65133", + SpanAttributes.HTTP_FLAVOR: "1.1", "falcon.resource": "HelloWorldResource", - "http.status_code": 201, + SpanAttributes.HTTP_STATUS_CODE: 201, }, ) self.memory_exporter.clear() @@ -129,16 +130,16 @@ class TestFalconInstrumentation(TestFalconBase): self.assert_span_has_attributes( span, { - "http.method": "GET", - "http.server_name": "falconframework.org", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "falconframework.org", - "http.target": "/", - "net.peer.ip": "127.0.0.1", - "net.peer.port": "65133", - "http.flavor": "1.1", - "http.status_code": 404, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SERVER_NAME: "falconframework.org", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "falconframework.org", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.NET_PEER_PORT: "65133", + SpanAttributes.HTTP_FLAVOR: "1.1", + SpanAttributes.HTTP_STATUS_CODE: 404, }, ) @@ -160,16 +161,16 @@ class TestFalconInstrumentation(TestFalconBase): self.assert_span_has_attributes( span, { - "http.method": "GET", - "http.server_name": "falconframework.org", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "falconframework.org", - "http.target": "/", - "net.peer.ip": "127.0.0.1", - "net.peer.port": "65133", - "http.flavor": "1.1", - "http.status_code": 500, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SERVER_NAME: "falconframework.org", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "falconframework.org", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.NET_PEER_PORT: "65133", + SpanAttributes.HTTP_FLAVOR: "1.1", + SpanAttributes.HTTP_STATUS_CODE: 500, }, ) diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg index 3bd8a8e09..7c54e5dc4 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-instrumentation-asgi == 0.20.dev0 opentelemetry-util-http == 0.20.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py index 2936da187..99fa6cdc0 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -17,6 +17,7 @@ from starlette.routing import Match from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util.http import get_excluded_urls _excluded_urls = get_excluded_urls("FASTAPI") @@ -82,5 +83,5 @@ def _get_route_details(scope): span_name = route or scope.get("method", "") attributes = {} if route: - attributes["http.route"] = route + attributes[SpanAttributes.HTTP_ROUTE] = route return span_name, attributes diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index fe6c27928..39a317b05 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -19,6 +19,7 @@ import fastapi from fastapi.testclient import TestClient import opentelemetry.instrumentation.fastapi as otel_fastapi +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.util.http import get_excluded_urls @@ -65,11 +66,13 @@ class TestFastAPIManualInstrumentation(TestBase): for span in spans: self.assertIn("/user/{username}", span.name) self.assertEqual( - spans[-1].attributes["http.route"], "/user/{username}" + spans[-1].attributes[SpanAttributes.HTTP_ROUTE], "/user/{username}" ) # ensure that at least one attribute that is populated by # the asgi instrumentation is successfully feeding though. - self.assertEqual(spans[-1].attributes["http.flavor"], "1.1") + self.assertEqual( + spans[-1].attributes[SpanAttributes.HTTP_FLAVOR], "1.1" + ) def test_fastapi_excluded_urls(self): """Ensure that given fastapi routes are excluded.""" diff --git a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg index 92f75734d..56c46505e 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg @@ -43,6 +43,7 @@ install_requires = opentelemetry-instrumentation == 0.20.dev0 opentelemetry-instrumentation-wsgi == 0.20.dev0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 [options.extras_require] test = diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py index 2b114f682..030fd4cba 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -59,6 +59,7 @@ from opentelemetry.instrumentation.propagators import ( get_global_response_propagator, ) from opentelemetry.propagate import extract +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util._time import _time_ns from opentelemetry.util.http import get_excluded_urls @@ -144,7 +145,9 @@ def _wrapped_before_request(name_callback): if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. - attributes["http.route"] = flask.request.url_rule.rule + attributes[ + SpanAttributes.HTTP_ROUTE + ] = flask.request.url_rule.rule for key, value in attributes.items(): span.set_attribute(key, value) diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index aead569de..a83d074a8 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -23,6 +23,7 @@ from opentelemetry.instrumentation.propagators import ( get_global_response_propagator, set_global_response_propagator, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.util.http import get_excluded_urls @@ -33,14 +34,14 @@ from .base_test import InstrumentationTest def expected_attributes(override_attributes): default_attributes = { - "http.method": "GET", - "http.server_name": "localhost", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "localhost", - "http.target": "/", - "http.flavor": "1.1", - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SERVER_NAME: "localhost", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "localhost", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.HTTP_FLAVOR: "1.1", + SpanAttributes.HTTP_STATUS_CODE: 200, } for key, val in override_attributes.items(): default_attributes[key] = val @@ -114,7 +115,10 @@ class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase): def test_simple(self): expected_attrs = expected_attributes( - {"http.target": "/hello/123", "http.route": "/hello/"} + { + SpanAttributes.HTTP_TARGET: "/hello/123", + SpanAttributes.HTTP_ROUTE: "/hello/", + } ) self.client.get("/hello/123") @@ -165,9 +169,9 @@ class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase): def test_404(self): expected_attrs = expected_attributes( { - "http.method": "POST", - "http.target": "/bye", - "http.status_code": 404, + SpanAttributes.HTTP_METHOD: "POST", + SpanAttributes.HTTP_TARGET: "/bye", + SpanAttributes.HTTP_STATUS_CODE: 404, } ) @@ -183,9 +187,9 @@ class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase): def test_internal_error(self): expected_attrs = expected_attributes( { - "http.target": "/hello/500", - "http.route": "/hello/", - "http.status_code": 500, + SpanAttributes.HTTP_TARGET: "/hello/500", + SpanAttributes.HTTP_ROUTE: "/hello/", + SpanAttributes.HTTP_STATUS_CODE: 500, } ) resp = self.client.get("/hello/500") diff --git a/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg b/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg index 7ed0acfad..5073b78fd 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg @@ -40,6 +40,7 @@ packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 opentelemetry-sdk == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 grpcio ~= 1.27 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py index 5c0f95dc3..7d3d22e71 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py @@ -29,6 +29,7 @@ from opentelemetry.instrumentation.grpc import grpcext from opentelemetry.instrumentation.grpc._utilities import RpcInfo from opentelemetry.propagate import inject from opentelemetry.propagators.textmap import Setter +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode @@ -87,10 +88,10 @@ class OpenTelemetryClientInterceptor( def _start_span(self, method): service, meth = method.lstrip("/").split("/", 1) attributes = { - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], - "rpc.method": meth, - "rpc.service": service, + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[0], + SpanAttributes.RPC_METHOD: meth, + SpanAttributes.RPC_SERVICE: service, } return self._tracer.start_as_current_span( @@ -144,7 +145,7 @@ class OpenTelemetryClientInterceptor( Status(StatusCode.ERROR) ) guarded_span.generated_span.set_attribute( - "rpc.grpc.status_code", err.code().value[0] + SpanAttributes.RPC_GRPC_STATUS_CODE, err.code().value[0] ) raise err @@ -180,7 +181,9 @@ class OpenTelemetryClientInterceptor( yield response except grpc.RpcError as err: span.set_status(Status(StatusCode.ERROR)) - span.set_attribute("rpc.grpc.status_code", err.code().value[0]) + span.set_attribute( + SpanAttributes.RPC_GRPC_STATUS_CODE, err.code().value[0] + ) raise err def intercept_stream( @@ -215,7 +218,7 @@ class OpenTelemetryClientInterceptor( Status(StatusCode.ERROR) ) guarded_span.generated_span.set_attribute( - "rpc.grpc.status_code", err.code().value[0], + SpanAttributes.RPC_GRPC_STATUS_CODE, err.code().value[0], ) raise err diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py index 39ff47f27..8516db14e 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py @@ -29,6 +29,7 @@ import grpc from opentelemetry import trace from opentelemetry.context import attach, detach from opentelemetry.propagate import extract +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode logger = logging.getLogger(__name__) @@ -116,7 +117,9 @@ class _OpenTelemetryServicerContext(grpc.ServicerContext): def abort(self, code, details): self.code = code self.details = details - self._active_span.set_attribute("rpc.grpc.status_code", code.value[0]) + self._active_span.set_attribute( + SpanAttributes.RPC_GRPC_STATUS_CODE, code.value[0] + ) self._active_span.set_status( Status( status_code=StatusCode.ERROR, @@ -132,7 +135,9 @@ class _OpenTelemetryServicerContext(grpc.ServicerContext): self.code = code # use details if we already have it, otherwise the status description details = self.details or code.value[1] - self._active_span.set_attribute("rpc.grpc.status_code", code.value[0]) + self._active_span.set_attribute( + SpanAttributes.RPC_GRPC_STATUS_CODE, code.value[0] + ) if code != grpc.StatusCode.OK: self._active_span.set_status( Status( @@ -198,8 +203,8 @@ class OpenTelemetryServerInterceptor(grpc.ServerInterceptor): # standard attributes attributes = { - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[0], } # if we have details about the call, split into service and method @@ -207,7 +212,12 @@ class OpenTelemetryServerInterceptor(grpc.ServerInterceptor): service, method = handler_call_details.method.lstrip("/").split( "/", 1 ) - attributes.update({"rpc.method": method, "rpc.service": service}) + attributes.update( + { + SpanAttributes.RPC_METHOD: method, + SpanAttributes.RPC_SERVICE: service, + } + ) # add some attributes from the metadata metadata = dict(context.invocation_metadata()) @@ -224,11 +234,16 @@ class OpenTelemetryServerInterceptor(grpc.ServerInterceptor): ip, port = ( context.peer().split(",")[0].split(":", 1)[1].rsplit(":", 1) ) - attributes.update({"net.peer.ip": ip, "net.peer.port": port}) + attributes.update( + { + SpanAttributes.NET_PEER_IP: ip, + SpanAttributes.NET_PEER_PORT: port, + } + ) # other telemetry sources add this, so we will too if ip in ("[::1]", "127.0.0.1"): - attributes["net.peer.name"] = "localhost" + attributes[SpanAttributes.NET_PEER_NAME] = "localhost" except IndexError: logger.warning("Failed to parse peer address '%s'", context.peer()) diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py index c9466b631..f088f5cf8 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py @@ -27,6 +27,7 @@ from opentelemetry.instrumentation.grpc.grpcext._interceptor import ( _UnaryClientInfo, ) from opentelemetry.propagate import get_global_textmap, set_global_textmap +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator from opentelemetry.test.test_base import TestBase @@ -72,10 +73,12 @@ class TestClientProto(TestBase): self.assert_span_has_attributes( span, { - "rpc.method": "SimpleMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.RPC_METHOD: "SimpleMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -96,10 +99,12 @@ class TestClientProto(TestBase): self.assert_span_has_attributes( span, { - "rpc.method": "ServerStreamingMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.RPC_METHOD: "ServerStreamingMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -120,10 +125,12 @@ class TestClientProto(TestBase): self.assert_span_has_attributes( span, { - "rpc.method": "ClientStreamingMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.RPC_METHOD: "ClientStreamingMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -146,10 +153,12 @@ class TestClientProto(TestBase): self.assert_span_has_attributes( span, { - "rpc.method": "BidirectionalStreamingMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.RPC_METHOD: "BidirectionalStreamingMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py index 83305cab2..d37c5e771 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py @@ -27,6 +27,7 @@ from opentelemetry.instrumentation.grpc import ( server_interceptor, ) from opentelemetry.sdk import trace as trace_sdk +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -113,12 +114,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "handler", - "rpc.service": "TestServicer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "handler", + SpanAttributes.RPC_SERVICE: "TestServicer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -191,12 +194,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "SimpleMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "SimpleMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -258,12 +263,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( parent_span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "SimpleMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "SimpleMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -316,12 +323,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "ServerStreamingMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "ServerStreamingMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -383,12 +392,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( parent_span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "ServerStreamingMethod", - "rpc.service": "GRPCTestServer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "ServerStreamingMethod", + SpanAttributes.RPC_SERVICE: "GRPCTestServer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -478,12 +489,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "handler", - "rpc.service": "TestServicer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "handler", + SpanAttributes.RPC_SERVICE: "TestServicer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -547,12 +560,14 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "handler", - "rpc.service": "TestServicer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "handler", + SpanAttributes.RPC_SERVICE: "TestServicer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[ + 0 + ], }, ) @@ -613,12 +628,12 @@ class TestOpenTelemetryServerInterceptor(TestBase): self.assert_span_has_attributes( span, { - "net.peer.ip": "[::1]", - "net.peer.name": "localhost", - "rpc.method": "handler", - "rpc.service": "TestServicer", - "rpc.system": "grpc", - "rpc.grpc.status_code": grpc.StatusCode.FAILED_PRECONDITION.value[ + SpanAttributes.NET_PEER_IP: "[::1]", + SpanAttributes.NET_PEER_NAME: "localhost", + SpanAttributes.RPC_METHOD: "handler", + SpanAttributes.RPC_SERVICE: "TestServicer", + SpanAttributes.RPC_SYSTEM: "grpc", + SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.FAILED_PRECONDITION.value[ 0 ], }, diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg b/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg index 55ce1b082..21e972381 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 pymemcache ~= 1.3 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py index 7e1b597ef..a5ef627f1 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py @@ -46,21 +46,16 @@ from wrapt import wrap_function_wrapper as _wrap from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.pymemcache.version import __version__ from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.semconv.trace import ( + DbSystemValues, + NetTransportValues, + SpanAttributes, +) from opentelemetry.trace import SpanKind, get_tracer logger = logging.getLogger(__name__) -# Network attribute semantic convention here: -# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/span-general.md#general-network-connection-attributes -_HOST = "net.peer.name" -_PORT = "net.peer.port" -_TRANSPORT = "net.transport" -# Database semantic conventions here: -# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/database.md -_DB = "db.system" -_DEFAULT_SERVICE = "memcached" -_RAWCMD = "db.statement" COMMANDS = [ "set", "set_many", @@ -123,7 +118,7 @@ def _wrap_cmd(tracer, cmd, wrapped, instance, args, kwargs): vals = _get_query_string(args[0]) query = "{}{}{}".format(cmd, " " if vals else "", vals) - span.set_attribute(_RAWCMD, query) + span.set_attribute(SpanAttributes.DB_STATEMENT, query) _set_connection_attributes(span, instance) except Exception as ex: # pylint: disable=broad-except @@ -162,19 +157,23 @@ def _get_query_string(arg): def _get_address_attributes(instance): """Attempt to get host and port from Client instance.""" address_attributes = {} - address_attributes[_DB] = "memcached" + address_attributes[SpanAttributes.DB_SYSTEM] = "memcached" # client.base.Client contains server attribute which is either a host/port tuple, or unix socket path string # https://github.com/pinterest/pymemcache/blob/f02ddf73a28c09256589b8afbb3ee50f1171cac7/pymemcache/client/base.py#L228 if hasattr(instance, "server"): if isinstance(instance.server, tuple): host, port = instance.server - address_attributes[_HOST] = host - address_attributes[_PORT] = port - address_attributes[_TRANSPORT] = "IP.TCP" + address_attributes[SpanAttributes.NET_PEER_NAME] = host + address_attributes[SpanAttributes.NET_PEER_PORT] = port + address_attributes[ + SpanAttributes.NET_TRANSPORT + ] = NetTransportValues.IP_TCP.value elif isinstance(instance.server, str): - address_attributes[_HOST] = instance.server - address_attributes[_TRANSPORT] = "Unix" + address_attributes[SpanAttributes.NET_PEER_NAME] = instance.server + address_attributes[ + SpanAttributes.NET_TRANSPORT + ] = NetTransportValues.UNIX.value return address_attributes diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py index 64f249e10..c7a7b097d 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py @@ -24,6 +24,7 @@ from pymemcache.exceptions import ( from opentelemetry import trace as trace_api from opentelemetry.instrumentation.pymemcache import PymemcacheInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import get_tracer @@ -65,10 +66,18 @@ class PymemcacheClientTestCase( command, *_ = query.split(" ") self.assertEqual(span.name, command) self.assertIs(span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(span.attributes["net.peer.name"], TEST_HOST) - self.assertEqual(span.attributes["net.peer.port"], TEST_PORT) - self.assertEqual(span.attributes["db.system"], "memcached") - self.assertEqual(span.attributes["db.statement"], query) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], TEST_HOST + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_PORT], TEST_PORT + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "memcached" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], query + ) def test_set_success(self): client = self.make_client([b"STORED\r\n"]) @@ -207,8 +216,12 @@ class PymemcacheClientTestCase( spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 2) - self.assertEqual(spans[0].attributes["net.peer.name"], TEST_HOST) - self.assertEqual(spans[0].attributes["net.peer.port"], TEST_PORT) + self.assertEqual( + spans[0].attributes[SpanAttributes.NET_PEER_NAME], TEST_HOST + ) + self.assertEqual( + spans[0].attributes[SpanAttributes.NET_PEER_PORT], TEST_PORT + ) def test_append_stored(self): client = self.make_client([b"STORED\r\n"]) @@ -511,10 +524,18 @@ class PymemcacheHashClientTestCase(TestBase): command, *_ = query.split(" ") self.assertEqual(span.name, command) self.assertIs(span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(span.attributes["net.peer.name"], TEST_HOST) - self.assertEqual(span.attributes["net.peer.port"], TEST_PORT) - self.assertEqual(span.attributes["db.system"], "memcached") - self.assertEqual(span.attributes["db.statement"], query) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], TEST_HOST + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_PORT], TEST_PORT + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "memcached" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], query + ) def test_delete_many_found(self): client = self.make_client([b"STORED\r", b"\n", b"DELETED\r\n"]) diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg b/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg index cc618232e..c3047b595 100644 --- a/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 pymongo ~= 3.1 diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py b/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py index 39de8e32c..cd3743e39 100644 --- a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py @@ -42,11 +42,10 @@ from pymongo import monitoring from opentelemetry import trace from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.pymongo.version import __version__ +from opentelemetry.semconv.trace import DbSystemValues, SpanAttributes from opentelemetry.trace import SpanKind, get_tracer from opentelemetry.trace.status import Status, StatusCode -DATABASE_SYSTEM = "mongodb" - class CommandTracer(monitoring.CommandListener): def __init__(self, tracer): @@ -68,12 +67,18 @@ class CommandTracer(monitoring.CommandListener): try: span = self._tracer.start_span(name, kind=SpanKind.CLIENT) if span.is_recording(): - span.set_attribute("db.system", DATABASE_SYSTEM) - span.set_attribute("db.name", event.database_name) - span.set_attribute("db.statement", statement) + span.set_attribute( + SpanAttributes.DB_SYSTEM, DbSystemValues.MONGODB.value + ) + span.set_attribute(SpanAttributes.DB_NAME, event.database_name) + span.set_attribute(SpanAttributes.DB_STATEMENT, statement) if event.connection_id is not None: - span.set_attribute("net.peer.name", event.connection_id[0]) - span.set_attribute("net.peer.port", event.connection_id[1]) + span.set_attribute( + SpanAttributes.NET_PEER_NAME, event.connection_id[0] + ) + span.set_attribute( + SpanAttributes.NET_PEER_PORT, event.connection_id[1] + ) # Add Span to dictionary self._span_dict[_get_span_dict_key(event)] = span diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py b/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py index d18cbad2e..fc12a5696 100644 --- a/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py +++ b/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py @@ -19,6 +19,7 @@ from opentelemetry.instrumentation.pymongo import ( CommandTracer, PymongoInstrumentor, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase @@ -52,11 +53,17 @@ class TestPymongo(TestBase): span = command_tracer._pop_span(mock_event) self.assertIs(span.kind, trace_api.SpanKind.CLIENT) self.assertEqual(span.name, "command_name.find") - self.assertEqual(span.attributes["db.system"], "mongodb") - self.assertEqual(span.attributes["db.name"], "database_name") - self.assertEqual(span.attributes["db.statement"], "command_name find") - self.assertEqual(span.attributes["net.peer.name"], "test.com") - self.assertEqual(span.attributes["net.peer.port"], "1234") + self.assertEqual(span.attributes[SpanAttributes.DB_SYSTEM], "mongodb") + self.assertEqual( + span.attributes[SpanAttributes.DB_NAME], "database_name" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_STATEMENT], "command_name find" + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], "test.com" + ) + self.assertEqual(span.attributes[SpanAttributes.NET_PEER_PORT], "1234") def test_succeeded(self): mock_event = MockEvent({}) diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg index b6cf1b2e1..757afad67 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg @@ -41,6 +41,7 @@ install_requires = pyramid >= 1.7 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation-wsgi == 0.20.dev0 opentelemetry-util-http == 0.20.dev0 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py index 9e777623e..292c38e02 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py @@ -26,6 +26,7 @@ from opentelemetry.instrumentation.propagators import ( ) from opentelemetry.instrumentation.pyramid.version import __version__ from opentelemetry.propagate import extract +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util._time import _time_ns from opentelemetry.util.http import get_excluded_urls @@ -98,7 +99,9 @@ def _before_traversal(event): if span.is_recording(): attributes = otel_wsgi.collect_request_attributes(request_environ) if request.matched_route: - attributes["http.route"] = request.matched_route.pattern + attributes[ + SpanAttributes.HTTP_ROUTE + ] = request.matched_route.pattern for key, value in attributes.items(): span.set_attribute(key, value) diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py index ce4151ad9..a7a0260d4 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py @@ -23,6 +23,7 @@ from opentelemetry.instrumentation.propagators import ( set_global_response_propagator, ) from opentelemetry.instrumentation.pyramid import PyramidInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.util.http import get_excluded_urls @@ -33,14 +34,14 @@ from .pyramid_base_test import InstrumentationTest def expected_attributes(override_attributes): default_attributes = { - "http.method": "GET", - "http.server_name": "localhost", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "localhost", - "http.target": "/", - "http.flavor": "1.1", - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SERVER_NAME: "localhost", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "localhost", + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.HTTP_FLAVOR: "1.1", + SpanAttributes.HTTP_STATUS_CODE: 200, } for key, val in override_attributes.items(): default_attributes[key] = val @@ -94,7 +95,10 @@ class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase): def test_simple(self): expected_attrs = expected_attributes( - {"http.target": "/hello/123", "http.route": "/hello/{helloid}"} + { + SpanAttributes.HTTP_TARGET: "/hello/123", + SpanAttributes.HTTP_ROUTE: "/hello/{helloid}", + } ) self.client.get("/hello/123") span_list = self.memory_exporter.get_finished_spans() @@ -142,9 +146,9 @@ class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase): def test_404(self): expected_attrs = expected_attributes( { - "http.method": "POST", - "http.target": "/bye", - "http.status_code": 404, + SpanAttributes.HTTP_METHOD: "POST", + SpanAttributes.HTTP_TARGET: "/bye", + SpanAttributes.HTTP_STATUS_CODE: 404, } ) @@ -160,9 +164,9 @@ class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase): def test_internal_error(self): expected_attrs = expected_attributes( { - "http.target": "/hello/500", - "http.route": "/hello/{helloid}", - "http.status_code": 500, + SpanAttributes.HTTP_TARGET: "/hello/500", + SpanAttributes.HTTP_ROUTE: "/hello/{helloid}", + SpanAttributes.HTTP_STATUS_CODE: 500, } ) resp = self.client.get("/hello/500") diff --git a/instrumentation/opentelemetry-instrumentation-redis/setup.cfg b/instrumentation/opentelemetry-instrumentation-redis/setup.cfg index 81ed3f84a..9d460685b 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-redis/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 redis >= 2.6 wrapt >= 1.12.1 diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py index c5b8b70ed..3d02d982d 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py @@ -53,9 +53,9 @@ from opentelemetry.instrumentation.redis.util import ( ) from opentelemetry.instrumentation.redis.version import __version__ from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.semconv.trace import SpanAttributes _DEFAULT_SERVICE = "redis" -_RAWCMD = "db.statement" def _set_connection_attributes(span, conn): @@ -79,7 +79,7 @@ def _traced_execute_command(func, instance, args, kwargs): name, kind=trace.SpanKind.CLIENT ) as span: if span.is_recording(): - span.set_attribute(_RAWCMD, query) + span.set_attribute(SpanAttributes.DB_STATEMENT, query) _set_connection_attributes(span, instance) span.set_attribute("db.redis.args_length", len(args)) return func(*args, **kwargs) @@ -97,7 +97,7 @@ def _traced_execute_pipeline(func, instance, args, kwargs): span_name, kind=trace.SpanKind.CLIENT ) as span: if span.is_recording(): - span.set_attribute(_RAWCMD, resource) + span.set_attribute(SpanAttributes.DB_STATEMENT, resource) _set_connection_attributes(span, instance) span.set_attribute( "db.redis.pipeline_length", len(instance.command_stack) diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py index 5679f2994..3419848eb 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py +++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py @@ -15,23 +15,36 @@ """ Some utils used by the redis integration """ +from opentelemetry.semconv.trace import ( + DbSystemValues, + NetTransportValues, + SpanAttributes, +) def _extract_conn_attributes(conn_kwargs): """ Transform redis conn info into dict """ attributes = { - "db.system": "redis", + SpanAttributes.DB_SYSTEM: DbSystemValues.REDIS.value, } db = conn_kwargs.get("db", 0) - attributes["db.name"] = db - attributes["db.redis.database_index"] = db + attributes[SpanAttributes.DB_NAME] = db + attributes[SpanAttributes.DB_REDIS_DATABASE_INDEX] = db try: - attributes["net.peer.name"] = conn_kwargs.get("host", "localhost") - attributes["net.peer.port"] = conn_kwargs.get("port", 6379) - attributes["net.transport"] = "IP.TCP" + attributes[SpanAttributes.NET_PEER_NAME] = conn_kwargs.get( + "host", "localhost" + ) + attributes[SpanAttributes.NET_PEER_PORT] = conn_kwargs.get( + "port", 6379 + ) + attributes[ + SpanAttributes.NET_TRANSPORT + ] = NetTransportValues.IP_TCP.value except KeyError: - attributes["net.peer.name"] = conn_kwargs.get("path", "") - attributes["net.transport"] = "Unix" + attributes[SpanAttributes.NET_PEER_NAME] = conn_kwargs.get("path", "") + attributes[ + SpanAttributes.NET_TRANSPORT + ] = NetTransportValues.UNIX.value return attributes diff --git a/instrumentation/opentelemetry-instrumentation-requests/setup.cfg b/instrumentation/opentelemetry-instrumentation-requests/setup.cfg index f8fbe61b0..411978a1b 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-requests/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 requests ~= 2.0 diff --git a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py index e70a6cf9d..29cf67d0c 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py @@ -45,6 +45,7 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.requests.version import __version__ from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.propagate import inject +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer from opentelemetry.trace.status import Status @@ -122,16 +123,16 @@ def _instrument(tracer_provider=None, span_callback=None, name_callback=None): span_name = get_default_span_name(method) labels = {} - labels["http.method"] = method - labels["http.url"] = url + labels[SpanAttributes.HTTP_METHOD] = method + labels[SpanAttributes.HTTP_URL] = url with get_tracer( __name__, __version__, tracer_provider ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span: exception = None if span.is_recording(): - span.set_attribute("http.method", method) - span.set_attribute("http.url", url) + span.set_attribute(SpanAttributes.HTTP_METHOD, method) + span.set_attribute(SpanAttributes.HTTP_URL, url) headers = get_or_create_headers() inject(headers) @@ -149,13 +150,17 @@ def _instrument(tracer_provider=None, span_callback=None, name_callback=None): if isinstance(result, Response): if span.is_recording(): - span.set_attribute("http.status_code", result.status_code) + span.set_attribute( + SpanAttributes.HTTP_STATUS_CODE, result.status_code + ) span.set_status( Status(http_status_to_status_code(result.status_code)) ) - labels["http.status_code"] = str(result.status_code) + labels[SpanAttributes.HTTP_STATUS_CODE] = str( + result.status_code + ) if result.raw and result.raw.version: - labels["http.flavor"] = ( + labels[SpanAttributes.HTTP_FLAVOR] = ( str(result.raw.version)[:1] + "." + str(result.raw.version)[:-1] diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py index a777cd538..08562f6a3 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py +++ b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py @@ -23,6 +23,7 @@ from opentelemetry import context, trace from opentelemetry.instrumentation.requests import RequestsInstrumentor from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.sdk import resources +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -79,9 +80,9 @@ class RequestsIntegrationTestBase(abc.ABC): self.assertEqual( span.attributes, { - "http.method": "GET", - "http.url": self.URL, - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -125,7 +126,9 @@ class RequestsIntegrationTestBase(abc.ABC): span = self.assert_span() - self.assertEqual(span.attributes.get("http.status_code"), 404) + self.assertEqual( + span.attributes.get(SpanAttributes.HTTP_STATUS_CODE), 404 + ) self.assertIs( span.status.status_code, trace.StatusCode.ERROR, @@ -230,9 +233,9 @@ class RequestsIntegrationTestBase(abc.ABC): self.assertEqual( span.attributes, { - "http.method": "GET", - "http.url": self.URL, - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + SpanAttributes.HTTP_STATUS_CODE: 200, "http.response.body": "Hello!", }, ) @@ -260,7 +263,11 @@ class RequestsIntegrationTestBase(abc.ABC): span = self.assert_span() self.assertEqual( - span.attributes, {"http.method": "GET", "http.url": self.URL} + span.attributes, + { + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + }, ) self.assertEqual(span.status.status_code, StatusCode.ERROR) @@ -278,7 +285,11 @@ class RequestsIntegrationTestBase(abc.ABC): span = self.assert_span() self.assertEqual( - span.attributes, {"http.method": "GET", "http.url": self.URL} + span.attributes, + { + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + }, ) self.assertEqual(span.status.status_code, StatusCode.ERROR) @@ -298,9 +309,9 @@ class RequestsIntegrationTestBase(abc.ABC): self.assertEqual( span.attributes, { - "http.method": "GET", - "http.url": self.URL, - "http.status_code": 500, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + SpanAttributes.HTTP_STATUS_CODE: 500, }, ) self.assertEqual(span.status.status_code, StatusCode.ERROR) @@ -341,7 +352,8 @@ class TestRequestsIntegration(RequestsIntegrationTestBase, TestBase): self.assertEqual(span.name, "HTTP POST") self.assertEqual( - span.attributes, {"http.method": "POST", "http.url": url} + span.attributes, + {SpanAttributes.HTTP_METHOD: "POST", SpanAttributes.HTTP_URL: url}, ) self.assertEqual(span.status.status_code, StatusCode.ERROR) diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg b/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg index c854539ee..40ea0cd26 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 wrapt >= 1.11.2 sqlalchemy diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py index 683af77e4..f2beb024d 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py @@ -19,18 +19,9 @@ from sqlalchemy.event import listen # pylint: disable=no-name-in-module from opentelemetry import trace from opentelemetry.instrumentation.sqlalchemy.version import __version__ +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode -# Network attribute semantic convention here: -# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/span-general.md#general-network-connection-attributes -_HOST = "net.peer.name" -_PORT = "net.peer.port" -# Database semantic conventions here: -# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/database.md -_STMT = "db.statement" -_DB = "db.name" -_USER = "db.user" - def _normalize_vendor(vendor): """Return a canonical name for a type of database.""" @@ -105,7 +96,7 @@ class EngineTracer: if not found: attrs = _get_attributes_from_cursor(self.vendor, cursor, attrs) - db_name = attrs.get(_DB, "") + db_name = attrs.get(SpanAttributes.DB_NAME, "") span = self.tracer.start_span( self._operation_name(db_name, statement), kind=trace.SpanKind.CLIENT, @@ -113,8 +104,8 @@ class EngineTracer: self.current_thread_span = self.cursor_mapping[cursor] = span with trace.use_span(span, end_on_exit=False): if span.is_recording(): - span.set_attribute(_STMT, statement) - span.set_attribute("db.system", self.vendor) + span.set_attribute(SpanAttributes.DB_STATEMENT, statement) + span.set_attribute(SpanAttributes.DB_SYSTEM, self.vendor) for key, value in attrs.items(): span.set_attribute(key, value) @@ -144,13 +135,13 @@ def _get_attributes_from_url(url): """Set connection tags from the url. return true if successful.""" attrs = {} if url.host: - attrs[_HOST] = url.host + attrs[SpanAttributes.NET_PEER_NAME] = url.host if url.port: - attrs[_PORT] = url.port + attrs[SpanAttributes.NET_PEER_PORT] = url.port if url.database: - attrs[_DB] = url.database + attrs[SpanAttributes.DB_NAME] = url.database if url.username: - attrs[_USER] = url.username + attrs[SpanAttributes.DB_USER] = url.username return attrs, bool(url.host) @@ -164,7 +155,7 @@ def _get_attributes_from_cursor(vendor, cursor, attrs): dsn = getattr(cursor.connection, "dsn", None) if dsn: data = parse_dsn(dsn) - attrs[_DB] = data.get("dbname") - attrs[_HOST] = data.get("host") - attrs[_PORT] = int(data.get("port")) + attrs[SpanAttributes.DB_NAME] = data.get("dbname") + attrs[SpanAttributes.NET_PEER_NAME] = data.get("host") + attrs[SpanAttributes.NET_PEER_PORT] = int(data.get("port")) return attrs diff --git a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg index 9aff5eab6..e6ba93494 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-instrumentation-asgi == 0.20.dev0 opentelemetry-util-http == 0.20.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py index d595beadc..2e3fe9e45 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -17,6 +17,7 @@ from starlette.routing import Match from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util.http import get_excluded_urls _excluded_urls = get_excluded_urls("STARLETTE") @@ -82,5 +83,5 @@ def _get_route_details(scope): span_name = route or scope.get("method", "") attributes = {} if route: - attributes["http.route"] = route + attributes[SpanAttributes.HTTP_ROUTE] = route return span_name, attributes diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py index 56116c5a0..3aaeefcbc 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py @@ -21,6 +21,7 @@ from starlette.routing import Route from starlette.testclient import TestClient import opentelemetry.instrumentation.starlette as otel_starlette +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.util.http import get_excluded_urls @@ -67,11 +68,13 @@ class TestStarletteManualInstrumentation(TestBase): for span in spans: self.assertIn("/user/{username}", span.name) self.assertEqual( - spans[-1].attributes["http.route"], "/user/{username}" + spans[-1].attributes[SpanAttributes.HTTP_ROUTE], "/user/{username}" ) # ensure that at least one attribute that is populated by # the asgi instrumentation is successfully feeding though. - self.assertEqual(spans[-1].attributes["http.flavor"], "1.1") + self.assertEqual( + spans[-1].attributes[SpanAttributes.HTTP_FLAVOR], "1.1" + ) def test_starlette_excluded_urls(self): """Ensure that givem starlette routes are excluded.""" diff --git a/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg b/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg index f6cd5aac7..a934bda81 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg @@ -40,6 +40,7 @@ install_requires = tornado >= 6.0 opentelemetry-instrumentation == 0.20.dev0 opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-util-http == 0.20.dev0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py index d7cf74b93..e13d24c97 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py @@ -94,6 +94,7 @@ from opentelemetry.instrumentation.utils import ( unwrap, ) from opentelemetry.propagate import extract +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status from opentelemetry.util._time import _time_ns from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs @@ -222,17 +223,17 @@ def _log_exception(tracer, func, handler, args, kwargs): def _get_attributes_from_request(request): attrs = { - "http.method": request.method, - "http.scheme": request.protocol, - "http.host": request.host, - "http.target": request.path, + SpanAttributes.HTTP_METHOD: request.method, + SpanAttributes.HTTP_SCHEME: request.protocol, + SpanAttributes.HTTP_HOST: request.host, + SpanAttributes.HTTP_TARGET: request.path, } if request.host: - attrs["http.host"] = request.host + attrs[SpanAttributes.HTTP_HOST] = request.host if request.remote_ip: - attrs["net.peer.ip"] = request.remote_ip + attrs[SpanAttributes.NET_PEER_IP] = request.remote_ip return extract_attributes_from_object( request, _traced_request_attrs, attrs @@ -297,7 +298,7 @@ def _finish_span(tracer, handler, error=None): return if ctx.span.is_recording(): - ctx.span.set_attribute("http.status_code", status_code) + ctx.span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) ctx.span.set_status( Status( status_code=http_status_to_status_code(status_code), diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py index 214f1768a..6bdcd58b7 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py @@ -19,6 +19,7 @@ from tornado.httpclient import HTTPError, HTTPRequest from opentelemetry import trace from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.propagate import inject +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status from opentelemetry.util._time import _time_ns @@ -60,8 +61,8 @@ def fetch_async(tracer, request_hook, response_hook, func, _, args, kwargs): if span.is_recording(): attributes = { - "http.url": request.url, - "http.method": request.method, + SpanAttributes.HTTP_URL: request.url, + SpanAttributes.HTTP_METHOD: request.method, } for key, value in attributes.items(): span.set_attribute(key, value) @@ -91,7 +92,7 @@ def _finish_tracing_callback(future, span, response_hook): status_code = future.result().code if status_code is not None: - span.set_attribute("http.status_code", status_code) + span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) span.set_status( Status( status_code=http_status_to_status_code(status_code), diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py index 003f54400..605dde2ab 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py @@ -28,6 +28,7 @@ from opentelemetry.instrumentation.tornado import ( patch_handler_class, unpatch_handler_class, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import SpanKind from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs @@ -136,12 +137,13 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( server, { - "http.method": method, - "http.scheme": "http", - "http.host": "127.0.0.1:" + str(self.get_http_port()), - "http.target": "/", - "net.peer.ip": "127.0.0.1", - "http.status_code": 201, + SpanAttributes.HTTP_METHOD: method, + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_HOST: "127.0.0.1:" + + str(self.get_http_port()), + SpanAttributes.HTTP_TARGET: "/", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.HTTP_STATUS_CODE: 201, }, ) @@ -152,9 +154,9 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( client, { - "http.url": self.get_url("/"), - "http.method": method, - "http.status_code": 201, + SpanAttributes.HTTP_URL: self.get_url("/"), + SpanAttributes.HTTP_METHOD: method, + SpanAttributes.HTTP_STATUS_CODE: 201, }, ) @@ -208,12 +210,13 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( server, { - "http.method": "GET", - "http.scheme": "http", - "http.host": "127.0.0.1:" + str(self.get_http_port()), - "http.target": url, - "net.peer.ip": "127.0.0.1", - "http.status_code": 201, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_HOST: "127.0.0.1:" + + str(self.get_http_port()), + SpanAttributes.HTTP_TARGET: url, + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.HTTP_STATUS_CODE: 201, }, ) @@ -224,9 +227,9 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( client, { - "http.url": self.get_url(url), - "http.method": "GET", - "http.status_code": 201, + SpanAttributes.HTTP_URL: self.get_url(url), + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_STATUS_CODE: 201, }, ) @@ -243,12 +246,13 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( server, { - "http.method": "GET", - "http.scheme": "http", - "http.host": "127.0.0.1:" + str(self.get_http_port()), - "http.target": "/error", - "net.peer.ip": "127.0.0.1", - "http.status_code": 500, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_HOST: "127.0.0.1:" + + str(self.get_http_port()), + SpanAttributes.HTTP_TARGET: "/error", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.HTTP_STATUS_CODE: 500, }, ) @@ -257,9 +261,9 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( client, { - "http.url": self.get_url("/error"), - "http.method": "GET", - "http.status_code": 500, + SpanAttributes.HTTP_URL: self.get_url("/error"), + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_STATUS_CODE: 500, }, ) @@ -276,12 +280,13 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( server, { - "http.method": "GET", - "http.scheme": "http", - "http.host": "127.0.0.1:" + str(self.get_http_port()), - "http.target": "/missing-url", - "net.peer.ip": "127.0.0.1", - "http.status_code": 404, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_HOST: "127.0.0.1:" + + str(self.get_http_port()), + SpanAttributes.HTTP_TARGET: "/missing-url", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.HTTP_STATUS_CODE: 404, }, ) @@ -290,9 +295,9 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( client, { - "http.url": self.get_url("/missing-url"), - "http.method": "GET", - "http.status_code": 404, + SpanAttributes.HTTP_URL: self.get_url("/missing-url"), + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_STATUS_CODE: 404, }, ) @@ -319,12 +324,13 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( server, { - "http.method": "GET", - "http.scheme": "http", - "http.host": "127.0.0.1:" + str(self.get_http_port()), - "http.target": "/dyna", - "net.peer.ip": "127.0.0.1", - "http.status_code": 202, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_HOST: "127.0.0.1:" + + str(self.get_http_port()), + SpanAttributes.HTTP_TARGET: "/dyna", + SpanAttributes.NET_PEER_IP: "127.0.0.1", + SpanAttributes.HTTP_STATUS_CODE: 202, }, ) @@ -335,9 +341,9 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( client, { - "http.url": self.get_url("/dyna"), - "http.method": "GET", - "http.status_code": 202, + SpanAttributes.HTTP_URL: self.get_url("/dyna"), + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_STATUS_CODE: 202, }, ) @@ -354,9 +360,9 @@ class TestTornadoInstrumentation(TornadoTest): self.assert_span_has_attributes( client, { - "http.url": self.get_url(path), - "http.method": "GET", - "http.status_code": 200, + SpanAttributes.HTTP_URL: self.get_url(path), + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) self.memory_exporter.clear() diff --git a/instrumentation/opentelemetry-instrumentation-urllib/setup.cfg b/instrumentation/opentelemetry-instrumentation-urllib/setup.cfg index 2bd282f93..bdf0b2148 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-urllib/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py index 958f32685..5a586317e 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py @@ -50,6 +50,7 @@ from opentelemetry.instrumentation.urllib.version import ( # pylint: disable=no ) from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.propagate import inject +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer from opentelemetry.trace.status import Status @@ -138,8 +139,8 @@ def _instrument(tracer_provider=None, span_callback=None, name_callback=None): span_name = get_default_span_name(method) labels = { - "http.method": method, - "http.url": url, + SpanAttributes.HTTP_METHOD: method, + SpanAttributes.HTTP_URL: url, } with get_tracer( @@ -147,8 +148,8 @@ def _instrument(tracer_provider=None, span_callback=None, name_callback=None): ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span: exception = None if span.is_recording(): - span.set_attribute("http.method", method) - span.set_attribute("http.url", url) + span.set_attribute(SpanAttributes.HTTP_METHOD, method) + span.set_attribute(SpanAttributes.HTTP_URL, url) headers = get_or_create_headers() inject(headers) @@ -167,15 +168,17 @@ def _instrument(tracer_provider=None, span_callback=None, name_callback=None): if result is not None: code_ = result.getcode() - labels["http.status_code"] = str(code_) + labels[SpanAttributes.HTTP_STATUS_CODE] = str(code_) if span.is_recording(): - span.set_attribute("http.status_code", code_) + span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, code_) span.set_status(Status(http_status_to_status_code(code_))) ver_ = str(getattr(result, "version", "")) if ver_: - labels["http.flavor"] = "{}.{}".format(ver_[:1], ver_[:-1]) + labels[SpanAttributes.HTTP_FLAVOR] = "{}.{}".format( + ver_[:1], ver_[:-1] + ) if span_callback is not None: span_callback(span, result) diff --git a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py index 2d8bfd1a5..b05fe0001 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py @@ -30,6 +30,7 @@ from opentelemetry.instrumentation.urllib import ( # pylint: disable=no-name-in ) from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.sdk import resources +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -104,9 +105,9 @@ class RequestsIntegrationTestBase(abc.ABC): self.assertEqual( span.attributes, { - "http.method": "GET", - "http.url": self.URL, - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + SpanAttributes.HTTP_STATUS_CODE: 200, }, ) @@ -156,7 +157,9 @@ class RequestsIntegrationTestBase(abc.ABC): span = self.assert_span() - self.assertEqual(span.attributes.get("http.status_code"), 404) + self.assertEqual( + span.attributes.get(SpanAttributes.HTTP_STATUS_CODE), 404 + ) self.assertIs( span.status.status_code, trace.StatusCode.ERROR, @@ -264,9 +267,9 @@ class RequestsIntegrationTestBase(abc.ABC): self.assertEqual( span.attributes, { - "http.method": "GET", - "http.url": self.URL, - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: self.URL, + SpanAttributes.HTTP_STATUS_CODE: 200, "http.response.body": "Hello!", }, ) @@ -293,9 +296,9 @@ class RequestsIntegrationTestBase(abc.ABC): self.assertEqual( dict(span.attributes), { - "http.method": "GET", - "http.url": "http://httpbin.org/status/500", - "http.status_code": 500, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: "http://httpbin.org/status/500", + SpanAttributes.HTTP_STATUS_CODE: 500, }, ) self.assertEqual(span.status.status_code, StatusCode.ERROR) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/setup.cfg b/instrumentation/opentelemetry-instrumentation-urllib3/setup.cfg index ebbe54ddf..54e7ee568 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-urllib3/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 urllib3 >= 1.0.0, < 2.0.0 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py index 33e6ffa67..0885656cd 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py @@ -58,6 +58,7 @@ from opentelemetry.instrumentation.utils import ( unwrap, ) from opentelemetry.propagate import inject +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import Span, SpanKind, TracerProvider, get_tracer from opentelemetry.trace.status import Status @@ -110,8 +111,8 @@ def _instrument( span_name = _get_span_name(span_name_or_callback, method, url, headers) span_attributes = { - "http.method": method, - "http.url": url, + SpanAttributes.HTTP_METHOD: method, + SpanAttributes.HTTP_URL: url, } with get_tracer( @@ -202,7 +203,7 @@ def _apply_response(span: Span, response: urllib3.response.HTTPResponse): if not span.is_recording(): return - span.set_attribute("http.status_code", response.status) + span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, response.status) span.set_status(Status(http_status_to_status_code(response.status))) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py b/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py index ee878b97d..843679f93 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py @@ -22,6 +22,7 @@ import urllib3.exceptions from opentelemetry import context, trace from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor from opentelemetry.propagate import get_global_textmap, set_global_textmap +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator from opentelemetry.test.test_base import TestBase @@ -69,9 +70,9 @@ class TestURLLib3Instrumentor(TestBase): self.assertEqual("HTTP GET", span.name) attributes = { - "http.method": "GET", - "http.url": url, - "http.status_code": 200, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: url, + SpanAttributes.HTTP_STATUS_CODE: 200, } self.assertEqual(attributes, span.attributes) @@ -79,8 +80,8 @@ class TestURLLib3Instrumentor(TestBase): span = self.assert_span() attributes = { - "http.method": "GET", - "http.url": url, + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_URL: url, } self.assertEqual(attributes, span.attributes) self.assertEqual( @@ -125,7 +126,9 @@ class TestURLLib3Instrumentor(TestBase): self.assertEqual(404, response.status) span = self.assert_span() - self.assertEqual(404, span.attributes.get("http.status_code")) + self.assertEqual( + 404, span.attributes.get(SpanAttributes.HTTP_STATUS_CODE) + ) self.assertIs(trace.status.StatusCode.ERROR, span.status.status_code) def test_basic_http_non_default_port(self): diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg b/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg index 1db11f2af..34c22f83e 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 1.0.1.dev0 + opentelemetry-semantic-conventions == 0.20.dev0 opentelemetry-instrumentation == 0.20.dev0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index bb5226ab6..1d04ab7a8 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -63,6 +63,7 @@ from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.instrumentation.wsgi.version import __version__ from opentelemetry.propagate import extract from opentelemetry.propagators.textmap import Getter +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode _HTTP_VERSION_PREFIX = "HTTP/" @@ -111,41 +112,43 @@ def collect_request_attributes(environ): WSGI environ and returns a dictionary to be used as span creation attributes.""" result = { - "http.method": environ.get("REQUEST_METHOD"), - "http.server_name": environ.get("SERVER_NAME"), - "http.scheme": environ.get("wsgi.url_scheme"), + SpanAttributes.HTTP_METHOD: environ.get("REQUEST_METHOD"), + SpanAttributes.HTTP_SERVER_NAME: environ.get("SERVER_NAME"), + SpanAttributes.HTTP_SCHEME: environ.get("wsgi.url_scheme"), } host_port = environ.get("SERVER_PORT") if host_port is not None: - result.update({"net.host.port": int(host_port)}) + result.update({SpanAttributes.NET_HOST_PORT: int(host_port)}) - setifnotnone(result, "http.host", environ.get("HTTP_HOST")) + setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get("HTTP_HOST")) target = environ.get("RAW_URI") if target is None: # Note: `"" or None is None` target = environ.get("REQUEST_URI") if target is not None: - result["http.target"] = target + result[SpanAttributes.HTTP_TARGET] = target else: - result["http.url"] = wsgiref_util.request_uri(environ) + result[SpanAttributes.HTTP_URL] = wsgiref_util.request_uri(environ) remote_addr = environ.get("REMOTE_ADDR") if remote_addr: - result["net.peer.ip"] = remote_addr + result[SpanAttributes.NET_PEER_IP] = remote_addr remote_host = environ.get("REMOTE_HOST") if remote_host and remote_host != remote_addr: - result["net.peer.name"] = remote_host + result[SpanAttributes.NET_PEER_NAME] = remote_host user_agent = environ.get("HTTP_USER_AGENT") if user_agent is not None and len(user_agent) > 0: - result["http.user_agent"] = user_agent + result[SpanAttributes.HTTP_USER_AGENT] = user_agent - setifnotnone(result, "net.peer.port", environ.get("REMOTE_PORT")) + setifnotnone( + result, SpanAttributes.NET_PEER_PORT, environ.get("REMOTE_PORT") + ) flavor = environ.get("SERVER_PROTOCOL", "") if flavor.upper().startswith(_HTTP_VERSION_PREFIX): flavor = flavor[len(_HTTP_VERSION_PREFIX) :] if flavor: - result["http.flavor"] = flavor + result[SpanAttributes.HTTP_FLAVOR] = flavor return result @@ -169,7 +172,7 @@ def add_response_attributes( ) ) else: - span.set_attribute("http.status_code", status_code) + span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) span.set_status(Status(http_status_to_status_code(status_code))) diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py index 3f2d08e09..0fd2fa7f9 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py @@ -20,6 +20,7 @@ from urllib.parse import urlsplit import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import trace as trace_api +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.trace import StatusCode @@ -114,17 +115,17 @@ class TestWsgiApplication(WsgiTestBase): self.assertEqual(span_list[0].name, span_name) self.assertEqual(span_list[0].kind, trace_api.SpanKind.SERVER) expected_attributes = { - "http.server_name": "127.0.0.1", - "http.scheme": "http", - "net.host.port": 80, - "http.host": "127.0.0.1", - "http.flavor": "1.0", - "http.url": "http://127.0.0.1/", - "http.status_code": 200, + SpanAttributes.HTTP_SERVER_NAME: "127.0.0.1", + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_HOST: "127.0.0.1", + SpanAttributes.HTTP_FLAVOR: "1.0", + SpanAttributes.HTTP_URL: "http://127.0.0.1/", + SpanAttributes.HTTP_STATUS_CODE: 200, } expected_attributes.update(span_attributes or {}) if http_method is not None: - expected_attributes["http.method"] = http_method + expected_attributes[SpanAttributes.HTTP_METHOD] = http_method self.assertEqual(span_list[0].attributes, expected_attributes) def test_basic_wsgi_call(self): @@ -230,30 +231,32 @@ class TestWsgiAttributes(unittest.TestCase): self.assertDictEqual( attrs, { - "http.method": "GET", - "http.host": "127.0.0.1", - "http.url": "http://127.0.0.1/?foo=bar", - "net.host.port": 80, - "http.scheme": "http", - "http.server_name": "127.0.0.1", - "http.flavor": "1.0", + SpanAttributes.HTTP_METHOD: "GET", + SpanAttributes.HTTP_HOST: "127.0.0.1", + SpanAttributes.HTTP_URL: "http://127.0.0.1/?foo=bar", + SpanAttributes.NET_HOST_PORT: 80, + SpanAttributes.HTTP_SCHEME: "http", + SpanAttributes.HTTP_SERVER_NAME: "127.0.0.1", + SpanAttributes.HTTP_FLAVOR: "1.0", }, ) def validate_url(self, expected_url, raw=False, has_host=True): parts = urlsplit(expected_url) expected = { - "http.scheme": parts.scheme, - "net.host.port": parts.port + SpanAttributes.HTTP_SCHEME: parts.scheme, + SpanAttributes.NET_HOST_PORT: parts.port or (80 if parts.scheme == "http" else 443), - "http.server_name": parts.hostname, # Not true in the general case, but for all tests. + SpanAttributes.HTTP_SERVER_NAME: parts.hostname, # Not true in the general case, but for all tests. } if raw: - expected["http.target"] = expected_url.split(parts.netloc, 1)[1] + expected[SpanAttributes.HTTP_TARGET] = expected_url.split( + parts.netloc, 1 + )[1] else: - expected["http.url"] = expected_url + expected[SpanAttributes.HTTP_URL] = expected_url if has_host: - expected["http.host"] = parts.hostname + expected[SpanAttributes.HTTP_HOST] = parts.hostname attrs = otel_wsgi.collect_request_attributes(self.environ) self.assertGreaterEqual( @@ -309,9 +312,9 @@ class TestWsgiAttributes(unittest.TestCase): "HTTP_HOST" ] += ":8080" # Note that we do not correct SERVER_PORT expected = { - "http.host": "127.0.0.1:8080", - "http.url": "http://127.0.0.1:8080/", - "net.host.port": 80, + SpanAttributes.HTTP_HOST: "127.0.0.1:8080", + SpanAttributes.HTTP_URL: "http://127.0.0.1:8080/", + SpanAttributes.NET_HOST_PORT: 80, } self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), @@ -324,7 +327,7 @@ class TestWsgiAttributes(unittest.TestCase): def test_request_attributes_pathless(self): self.environ["RAW_URI"] = "" - expected = {"http.target": ""} + expected = {SpanAttributes.HTTP_TARGET: ""} self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), @@ -337,8 +340,8 @@ class TestWsgiAttributes(unittest.TestCase): "REQUEST_URI" ] = "127.0.0.1:8080" # Might happen in a CONNECT request expected = { - "http.host": "127.0.0.1:8080", - "http.target": "127.0.0.1:8080", + SpanAttributes.HTTP_HOST: "127.0.0.1:8080", + SpanAttributes.HTTP_TARGET: "127.0.0.1:8080", } self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), @@ -347,7 +350,7 @@ class TestWsgiAttributes(unittest.TestCase): def test_http_user_agent_attribute(self): self.environ["HTTP_USER_AGENT"] = "test-useragent" - expected = {"http.user_agent": "test-useragent"} + expected = {SpanAttributes.HTTP_USER_AGENT: "test-useragent"} self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), @@ -355,7 +358,7 @@ class TestWsgiAttributes(unittest.TestCase): def test_response_attributes(self): otel_wsgi.add_response_attributes(self.span, "404 Not Found", {}) - expected = (mock.call("http.status_code", 404),) + expected = (mock.call(SpanAttributes.HTTP_STATUS_CODE, 404),) self.assertEqual(self.span.set_attribute.call_count, len(expected)) self.span.set_attribute.assert_has_calls(expected, any_order=True) diff --git a/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py b/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py index f7c7ba553..9470f68b0 100644 --- a/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py +++ b/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py @@ -4,6 +4,7 @@ import os import asyncpg from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -42,11 +43,21 @@ class TestFunctionalAsyncPG(TestBase): AsyncPGInstrumentor().uninstrument() def check_span(self, span): - self.assertEqual(span.attributes["db.system"], "postgresql") - self.assertEqual(span.attributes["db.name"], POSTGRES_DB_NAME) - self.assertEqual(span.attributes["db.user"], POSTGRES_USER) - self.assertEqual(span.attributes["net.peer.name"], POSTGRES_HOST) - self.assertEqual(span.attributes["net.peer.port"], POSTGRES_PORT) + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "postgresql" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_NAME], POSTGRES_DB_NAME + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_USER], POSTGRES_USER + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], POSTGRES_HOST + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_PORT], POSTGRES_PORT + ) def test_instrumented_execute_method_without_arguments(self, *_, **__): async_call(self._connection.execute("SELECT 42;")) @@ -55,14 +66,18 @@ class TestFunctionalAsyncPG(TestBase): self.assertIs(StatusCode.UNSET, spans[0].status.status_code) self.check_span(spans[0]) self.assertEqual(spans[0].name, "SELECT 42;") - self.assertEqual(spans[0].attributes["db.statement"], "SELECT 42;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT 42;" + ) def test_instrumented_fetch_method_without_arguments(self, *_, **__): async_call(self._connection.fetch("SELECT 42;")) spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "SELECT 42;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT 42;" + ) def test_instrumented_transaction_method(self, *_, **__): async def _transaction_execute(): @@ -74,15 +89,21 @@ class TestFunctionalAsyncPG(TestBase): spans = self.memory_exporter.get_finished_spans() self.assertEqual(3, len(spans)) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "BEGIN;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "BEGIN;" + ) self.assertIs(StatusCode.UNSET, spans[0].status.status_code) self.check_span(spans[1]) - self.assertEqual(spans[1].attributes["db.statement"], "SELECT 42;") + self.assertEqual( + spans[1].attributes[SpanAttributes.DB_STATEMENT], "SELECT 42;" + ) self.assertIs(StatusCode.UNSET, spans[1].status.status_code) self.check_span(spans[2]) - self.assertEqual(spans[2].attributes["db.statement"], "COMMIT;") + self.assertEqual( + spans[2].attributes[SpanAttributes.DB_STATEMENT], "COMMIT;" + ) self.assertIs(StatusCode.UNSET, spans[2].status.status_code) def test_instrumented_failed_transaction_method(self, *_, **__): @@ -97,17 +118,22 @@ class TestFunctionalAsyncPG(TestBase): self.assertEqual(3, len(spans)) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "BEGIN;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "BEGIN;" + ) self.assertIs(StatusCode.UNSET, spans[0].status.status_code) self.check_span(spans[1]) self.assertEqual( - spans[1].attributes["db.statement"], "SELECT 42::uuid;" + spans[1].attributes[SpanAttributes.DB_STATEMENT], + "SELECT 42::uuid;", ) self.assertEqual(StatusCode.ERROR, spans[1].status.status_code) self.check_span(spans[2]) - self.assertEqual(spans[2].attributes["db.statement"], "ROLLBACK;") + self.assertEqual( + spans[2].attributes[SpanAttributes.DB_STATEMENT], "ROLLBACK;" + ) self.assertIs(StatusCode.UNSET, spans[2].status.status_code) def test_instrumented_method_doesnt_capture_parameters(self, *_, **__): @@ -116,7 +142,9 @@ class TestFunctionalAsyncPG(TestBase): self.assertEqual(len(spans), 1) self.assertIs(StatusCode.UNSET, spans[0].status.status_code) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT $1;" + ) class TestFunctionalAsyncPG_CaptureParameters(TestBase): @@ -144,11 +172,21 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase): AsyncPGInstrumentor().uninstrument() def check_span(self, span): - self.assertEqual(span.attributes["db.system"], "postgresql") - self.assertEqual(span.attributes["db.name"], POSTGRES_DB_NAME) - self.assertEqual(span.attributes["db.user"], POSTGRES_USER) - self.assertEqual(span.attributes["net.peer.name"], POSTGRES_HOST) - self.assertEqual(span.attributes["net.peer.port"], POSTGRES_PORT) + self.assertEqual( + span.attributes[SpanAttributes.DB_SYSTEM], "postgresql" + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_NAME], POSTGRES_DB_NAME + ) + self.assertEqual( + span.attributes[SpanAttributes.DB_USER], POSTGRES_USER + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], POSTGRES_HOST + ) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_PORT], POSTGRES_PORT + ) def test_instrumented_execute_method_with_arguments(self, *_, **__): async_call(self._connection.execute("SELECT $1;", "1")) @@ -158,7 +196,9 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase): self.check_span(spans[0]) self.assertEqual(spans[0].name, "SELECT $1;") - self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT $1;" + ) self.assertEqual( spans[0].attributes["db.statement.parameters"], "('1',)" ) @@ -169,7 +209,9 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase): self.assertEqual(len(spans), 1) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT $1;" + ) self.assertEqual( spans[0].attributes["db.statement.parameters"], "('1',)" ) @@ -180,7 +222,9 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase): self.assertEqual(len(spans), 1) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT $1;" + ) self.assertEqual( spans[0].attributes["db.statement.parameters"], "([['1'], ['2']],)" ) @@ -192,7 +236,9 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase): self.assertEqual(len(spans), 1) self.check_span(spans[0]) - self.assertEqual(spans[0].attributes["db.statement"], "SELECT 42;") + self.assertEqual( + spans[0].attributes[SpanAttributes.DB_STATEMENT], "SELECT 42;" + ) self.assertEqual( spans[0].attributes["db.statement.parameters"], "(1, 2, 3)" ) diff --git a/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py b/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py index 5195d88f5..45ffbbe38 100644 --- a/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py +++ b/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py @@ -22,6 +22,7 @@ from opentelemetry import trace as trace_api from opentelemetry.instrumentation.celery import CeleryInstrumentor from opentelemetry.sdk import resources from opentelemetry.sdk.trace import TracerProvider, export +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import StatusCode # set a high timeout for async executions due to issues in CI @@ -104,7 +105,9 @@ def test_fn_task_apply(celery_app, memory_exporter): assert span.status.is_ok is True assert span.name == "run/test_celery_functional.fn_task" - assert span.attributes.get("messaging.message_id") == t.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) == t.task_id + ) assert ( span.attributes.get("celery.task_name") == "test_celery_functional.fn_task" @@ -129,7 +132,9 @@ def test_fn_task_apply_bind(celery_app, memory_exporter): assert span.status.is_ok is True assert span.name == "run/test_celery_functional.fn_task" - assert span.attributes.get("messaging.message_id") == t.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) == t.task_id + ) assert ( span.attributes.get("celery.task_name") == "test_celery_functional.fn_task" @@ -162,7 +167,10 @@ def test_fn_task_apply_async(celery_app, memory_exporter): == "apply_async/test_celery_functional.fn_task_parameters" ) assert async_span.attributes.get("celery.action") == "apply_async" - assert async_span.attributes.get("messaging.message_id") == result.task_id + assert ( + async_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert ( async_span.attributes.get("celery.task_name") == "test_celery_functional.fn_task_parameters" @@ -172,7 +180,10 @@ def test_fn_task_apply_async(celery_app, memory_exporter): assert run_span.name == "test_celery_functional.fn_task_parameters" assert run_span.attributes.get("celery.action") == "run" assert run_span.attributes.get("celery.state") == "SUCCESS" - assert run_span.attributes.get("messaging.message_id") == result.task_id + assert ( + run_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert ( run_span.attributes.get("celery.task_name") == "test_celery_functional.fn_task_parameters" @@ -217,7 +228,10 @@ def test_fn_task_delay(celery_app, memory_exporter): == "apply_async/test_celery_functional.fn_task_parameters" ) assert async_span.attributes.get("celery.action") == "apply_async" - assert async_span.attributes.get("messaging.message_id") == result.task_id + assert ( + async_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert ( async_span.attributes.get("celery.task_name") == "test_celery_functional.fn_task_parameters" @@ -227,7 +241,10 @@ def test_fn_task_delay(celery_app, memory_exporter): assert run_span.name == "run/test_celery_functional.fn_task_parameters" assert run_span.attributes.get("celery.action") == "run" assert run_span.attributes.get("celery.state") == "SUCCESS" - assert run_span.attributes.get("messaging.message_id") == result.task_id + assert ( + run_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert ( run_span.attributes.get("celery.task_name") == "test_celery_functional.fn_task_parameters" @@ -258,7 +275,10 @@ def test_fn_exception(celery_app, memory_exporter): == "test_celery_functional.fn_exception" ) assert span.status.status_code == StatusCode.ERROR - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert "Task class is failing" in span.status.description @@ -286,7 +306,10 @@ def test_fn_exception_expected(celery_app, memory_exporter): span.attributes.get("celery.task_name") == "test_celery_functional.fn_exception" ) - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) def test_fn_retry_exception(celery_app, memory_exporter): @@ -313,7 +336,10 @@ def test_fn_retry_exception(celery_app, memory_exporter): span.attributes.get("celery.task_name") == "test_celery_functional.fn_exception" ) - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) def test_class_task(celery_app, memory_exporter): @@ -345,7 +371,10 @@ def test_class_task(celery_app, memory_exporter): ) assert span.attributes.get("celery.action") == "run" assert span.attributes.get("celery.state") == "SUCCESS" - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) def test_class_task_exception(celery_app, memory_exporter): @@ -378,7 +407,10 @@ def test_class_task_exception(celery_app, memory_exporter): assert span.attributes.get("celery.action") == "run" assert span.attributes.get("celery.state") == "FAILURE" assert span.status.status_code == StatusCode.ERROR - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert "Task class is failing" in span.status.description @@ -410,7 +442,10 @@ def test_class_task_exception_excepted(celery_app, memory_exporter): assert span.name == "run/test_celery_functional.BaseTask" assert span.attributes.get("celery.action") == "run" assert span.attributes.get("celery.state") == "FAILURE" - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) def test_shared_task(celery_app, memory_exporter): @@ -435,7 +470,10 @@ def test_shared_task(celery_app, memory_exporter): ) assert span.attributes.get("celery.action") == "run" assert span.attributes.get("celery.state") == "SUCCESS" - assert span.attributes.get("messaging.message_id") == result.task_id + assert ( + span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) @pytest.mark.skip(reason="inconsistent test results") @@ -484,7 +522,10 @@ def test_apply_async_previous_style_tasks( ) assert run_span.attributes.get("celery.action") == "run" assert run_span.attributes.get("celery.state") == "SUCCESS" - assert run_span.attributes.get("messaging.message_id") == result.task_id + assert ( + run_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + == result.task_id + ) assert async_run_span.status.is_ok is True assert async_run_span.name == "run/test_celery_functional.CelerySubClass" @@ -495,7 +536,8 @@ def test_apply_async_previous_style_tasks( assert async_run_span.attributes.get("celery.action") == "run" assert async_run_span.attributes.get("celery.state") == "SUCCESS" assert ( - async_run_span.attributes.get("messaging.message_id") != result.task_id + async_run_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + != result.task_id ) assert async_span.status.is_ok is True @@ -507,10 +549,13 @@ def test_apply_async_previous_style_tasks( == "test_celery_functional.CelerySubClass" ) assert async_span.attributes.get("celery.action") == "apply_async" - assert async_span.attributes.get("messaging.message_id") != result.task_id + assert ( + async_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) + != result.task_id + ) assert async_span.attributes.get( - "messaging.message_id" - ) == async_run_span.attributes.get("messaging.message_id") + SpanAttributes.MESSAGING_MESSAGE_ID + ) == async_run_span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID) def test_custom_tracer_provider(celery_app, memory_exporter): diff --git a/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py b/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py index df818ab13..59cf401e0 100644 --- a/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py +++ b/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py @@ -18,6 +18,7 @@ import mysql.connector from opentelemetry import trace as trace_api from opentelemetry.instrumentation.mysql import MySQLInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase MYSQL_USER = os.getenv("MYSQL_USER", "testuser") @@ -70,11 +71,19 @@ class TestFunctionalMysql(TestBase): self.assertIsNotNone(db_span.parent) self.assertIs(db_span.parent, root_span.get_span_context()) self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(db_span.attributes["db.system"], "mysql") - self.assertEqual(db_span.attributes["db.name"], MYSQL_DB_NAME) - self.assertEqual(db_span.attributes["db.user"], MYSQL_USER) - self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST) - self.assertEqual(db_span.attributes["net.peer.port"], MYSQL_PORT) + self.assertEqual(db_span.attributes[SpanAttributes.DB_SYSTEM], "mysql") + self.assertEqual( + db_span.attributes[SpanAttributes.DB_NAME], MYSQL_DB_NAME + ) + self.assertEqual( + db_span.attributes[SpanAttributes.DB_USER], MYSQL_USER + ) + self.assertEqual( + db_span.attributes[SpanAttributes.NET_PEER_NAME], MYSQL_HOST + ) + self.assertEqual( + db_span.attributes[SpanAttributes.NET_PEER_PORT], MYSQL_PORT + ) def test_execute(self): """Should create a child span for execute""" diff --git a/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py b/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py index 6519f9ac7..5f1d20bdc 100644 --- a/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py +++ b/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py @@ -20,6 +20,7 @@ import pytest from opentelemetry import trace as trace_api from opentelemetry.instrumentation.aiopg import AiopgInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase POSTGRES_HOST = os.getenv("POSTGRESQL_HOST", "127.0.0.1") @@ -78,11 +79,21 @@ class TestFunctionalAiopgConnect(TestBase): self.assertIsNotNone(child_span.parent) self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(child_span.attributes["db.system"], "postgresql") - self.assertEqual(child_span.attributes["db.name"], POSTGRES_DB_NAME) - self.assertEqual(child_span.attributes["db.user"], POSTGRES_USER) - self.assertEqual(child_span.attributes["net.peer.name"], POSTGRES_HOST) - self.assertEqual(child_span.attributes["net.peer.port"], POSTGRES_PORT) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_SYSTEM], "postgresql" + ) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_NAME], POSTGRES_DB_NAME + ) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_USER], POSTGRES_USER + ) + self.assertEqual( + child_span.attributes[SpanAttributes.NET_PEER_NAME], POSTGRES_HOST + ) + self.assertEqual( + child_span.attributes[SpanAttributes.NET_PEER_PORT], POSTGRES_PORT + ) def test_execute(self): """Should create a child span for execute method""" @@ -160,11 +171,21 @@ class TestFunctionalAiopgCreatePool(TestBase): self.assertIsNotNone(child_span.parent) self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(child_span.attributes["db.system"], "postgresql") - self.assertEqual(child_span.attributes["db.name"], POSTGRES_DB_NAME) - self.assertEqual(child_span.attributes["db.user"], POSTGRES_USER) - self.assertEqual(child_span.attributes["net.peer.name"], POSTGRES_HOST) - self.assertEqual(child_span.attributes["net.peer.port"], POSTGRES_PORT) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_SYSTEM], "postgresql" + ) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_NAME], POSTGRES_DB_NAME + ) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_USER], POSTGRES_USER + ) + self.assertEqual( + child_span.attributes[SpanAttributes.NET_PEER_NAME], POSTGRES_HOST + ) + self.assertEqual( + child_span.attributes[SpanAttributes.NET_PEER_PORT], POSTGRES_PORT + ) def test_execute(self): """Should create a child span for execute method""" diff --git a/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py b/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py index 53fe3cacf..e007bb7e8 100644 --- a/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py +++ b/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py @@ -19,6 +19,7 @@ from psycopg2 import sql from opentelemetry import trace as trace_api from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase POSTGRES_HOST = os.getenv("POSTGRESQL_HOST", "localhost") @@ -71,11 +72,21 @@ class TestFunctionalPsycopg(TestBase): self.assertIsNotNone(child_span.parent) self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(child_span.attributes["db.system"], "postgresql") - self.assertEqual(child_span.attributes["db.name"], POSTGRES_DB_NAME) - self.assertEqual(child_span.attributes["db.user"], POSTGRES_USER) - self.assertEqual(child_span.attributes["net.peer.name"], POSTGRES_HOST) - self.assertEqual(child_span.attributes["net.peer.port"], POSTGRES_PORT) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_SYSTEM], "postgresql" + ) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_NAME], POSTGRES_DB_NAME + ) + self.assertEqual( + child_span.attributes[SpanAttributes.DB_USER], POSTGRES_USER + ) + self.assertEqual( + child_span.attributes[SpanAttributes.NET_PEER_NAME], POSTGRES_HOST + ) + self.assertEqual( + child_span.attributes[SpanAttributes.NET_PEER_PORT], POSTGRES_PORT + ) def test_execute(self): """Should create a child span for execute method""" @@ -141,6 +152,6 @@ class TestFunctionalPsycopg(TestBase): span = spans[2] self.assertEqual(span.name, "SELECT") self.assertEqual( - span.attributes["db.statement"], + span.attributes[SpanAttributes.DB_STATEMENT], 'SELECT FROM "users" where "name"=\'"abc"\'', ) diff --git a/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py b/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py index d662014f1..a716cd8de 100644 --- a/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py +++ b/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py @@ -18,6 +18,7 @@ from pymongo import MongoClient from opentelemetry import trace as trace_api from opentelemetry.instrumentation.pymongo import PymongoInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase MONGODB_HOST = os.getenv("MONGODB_HOST", "localhost") @@ -53,12 +54,14 @@ class TestFunctionalPymongo(TestBase): self.assertIsNotNone(pymongo_span.parent) self.assertIs(pymongo_span.parent, root_span.get_span_context()) self.assertIs(pymongo_span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(pymongo_span.attributes["db.name"], MONGODB_DB_NAME) self.assertEqual( - pymongo_span.attributes["net.peer.name"], MONGODB_HOST + pymongo_span.attributes[SpanAttributes.DB_NAME], MONGODB_DB_NAME ) self.assertEqual( - pymongo_span.attributes["net.peer.port"], MONGODB_PORT + pymongo_span.attributes[SpanAttributes.NET_PEER_NAME], MONGODB_HOST + ) + self.assertEqual( + pymongo_span.attributes[SpanAttributes.NET_PEER_PORT], MONGODB_PORT ) def test_insert(self): diff --git a/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py b/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py index 278bfc4d4..881ef05d2 100644 --- a/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py +++ b/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py @@ -18,6 +18,7 @@ import pymysql as pymy from opentelemetry import trace as trace_api from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase MYSQL_USER = os.getenv("MYSQL_USER", "testuser") @@ -67,11 +68,19 @@ class TestFunctionalPyMysql(TestBase): self.assertIsNotNone(db_span.parent) self.assertIs(db_span.parent, root_span.get_span_context()) self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT) - self.assertEqual(db_span.attributes["db.system"], "mysql") - self.assertEqual(db_span.attributes["db.name"], MYSQL_DB_NAME) - self.assertEqual(db_span.attributes["db.user"], MYSQL_USER) - self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST) - self.assertEqual(db_span.attributes["net.peer.port"], MYSQL_PORT) + self.assertEqual(db_span.attributes[SpanAttributes.DB_SYSTEM], "mysql") + self.assertEqual( + db_span.attributes[SpanAttributes.DB_NAME], MYSQL_DB_NAME + ) + self.assertEqual( + db_span.attributes[SpanAttributes.DB_USER], MYSQL_USER + ) + self.assertEqual( + db_span.attributes[SpanAttributes.NET_PEER_NAME], MYSQL_HOST + ) + self.assertEqual( + db_span.attributes[SpanAttributes.NET_PEER_PORT], MYSQL_PORT + ) def test_execute(self): """Should create a child span for execute""" diff --git a/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py b/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py index 06a54b90a..b5a4b1702 100644 --- a/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py +++ b/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py @@ -16,6 +16,7 @@ import redis from opentelemetry import trace from opentelemetry.instrumentation.redis import RedisInstrumentor +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase @@ -33,9 +34,11 @@ class TestRedisInstrument(TestBase): def _check_span(self, span, name): self.assertEqual(span.name, name) self.assertIs(span.status.status_code, trace.StatusCode.UNSET) - self.assertEqual(span.attributes.get("db.name"), 0) - self.assertEqual(span.attributes["net.peer.name"], "localhost") - self.assertEqual(span.attributes["net.peer.port"], 6379) + self.assertEqual(span.attributes.get(SpanAttributes.DB_NAME), 0) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], "localhost" + ) + self.assertEqual(span.attributes[SpanAttributes.NET_PEER_PORT], 6379) def test_long_command(self): self.redis_client.mget(*range(1000)) @@ -45,9 +48,13 @@ class TestRedisInstrument(TestBase): span = spans[0] self._check_span(span, "MGET") self.assertTrue( - span.attributes.get("db.statement").startswith("MGET 0 1 2 3") + span.attributes.get(SpanAttributes.DB_STATEMENT).startswith( + "MGET 0 1 2 3" + ) + ) + self.assertTrue( + span.attributes.get(SpanAttributes.DB_STATEMENT).endswith("...") ) - self.assertTrue(span.attributes.get("db.statement").endswith("...")) def test_basics(self): self.assertIsNone(self.redis_client.get("cheese")) @@ -55,7 +62,9 @@ class TestRedisInstrument(TestBase): self.assertEqual(len(spans), 1) span = spans[0] self._check_span(span, "GET") - self.assertEqual(span.attributes.get("db.statement"), "GET cheese") + self.assertEqual( + span.attributes.get(SpanAttributes.DB_STATEMENT), "GET cheese" + ) self.assertEqual(span.attributes.get("db.redis.args_length"), 2) def test_pipeline_traced(self): @@ -70,7 +79,7 @@ class TestRedisInstrument(TestBase): span = spans[0] self._check_span(span, "SET RPUSH HGETALL") self.assertEqual( - span.attributes.get("db.statement"), + span.attributes.get(SpanAttributes.DB_STATEMENT), "SET blah 32\nRPUSH foo éé\nHGETALL xxx", ) self.assertEqual(span.attributes.get("db.redis.pipeline_length"), 3) @@ -87,7 +96,9 @@ class TestRedisInstrument(TestBase): self.assertEqual(len(spans), 2) span = spans[0] self._check_span(span, "SET") - self.assertEqual(span.attributes.get("db.statement"), "SET b 2") + self.assertEqual( + span.attributes.get(SpanAttributes.DB_STATEMENT), "SET b 2" + ) def test_parent(self): """Ensure OpenTelemetry works with redis.""" @@ -124,9 +135,13 @@ class TestRedisDBIndexInstrument(TestBase): def _check_span(self, span, name): self.assertEqual(span.name, name) self.assertIs(span.status.status_code, trace.StatusCode.UNSET) - self.assertEqual(span.attributes["net.peer.name"], "localhost") - self.assertEqual(span.attributes["net.peer.port"], 6379) - self.assertEqual(span.attributes["db.redis.database_index"], 10) + self.assertEqual( + span.attributes[SpanAttributes.NET_PEER_NAME], "localhost" + ) + self.assertEqual(span.attributes[SpanAttributes.NET_PEER_PORT], 6379) + self.assertEqual( + span.attributes[SpanAttributes.DB_REDIS_DATABASE_INDEX], 10 + ) def test_get(self): self.assertIsNone(self.redis_client.get("foo")) @@ -134,4 +149,6 @@ class TestRedisDBIndexInstrument(TestBase): self.assertEqual(len(spans), 1) span = spans[0] self._check_span(span, "GET") - self.assertEqual(span.attributes.get("db.statement"), "GET foo") + self.assertEqual( + span.attributes.get(SpanAttributes.DB_STATEMENT), "GET foo" + ) diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py index 76707bb6d..ccf37ae42 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py @@ -20,7 +20,7 @@ from sqlalchemy.orm import sessionmaker from opentelemetry import trace from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor -from opentelemetry.instrumentation.sqlalchemy.engine import _DB, _STMT +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase Base = declarative_base() @@ -113,7 +113,9 @@ class SQLAlchemyTestMixin(TestBase): if self.SQL_DB: name = "{0} {1}".format(name, self.SQL_DB) self.assertEqual(span.name, name) - self.assertEqual(span.attributes.get(_DB), self.SQL_DB) + self.assertEqual( + span.attributes.get(SpanAttributes.DB_NAME), self.SQL_DB + ) self.assertIs(span.status.status_code, trace.StatusCode.UNSET) self.assertGreater((span.end_time - span.start_time), 0) @@ -127,12 +129,15 @@ class SQLAlchemyTestMixin(TestBase): self.assertEqual(len(spans), 1) span = spans[0] stmt = "INSERT INTO players (id, name) VALUES " - if span.attributes.get("db.system") == "sqlite": + if span.attributes.get(SpanAttributes.DB_SYSTEM) == "sqlite": stmt += "(?, ?)" else: stmt += "(%(id)s, %(name)s)" self._check_span(span, "INSERT") - self.assertIn("INSERT INTO players", span.attributes.get(_STMT)) + self.assertIn( + "INSERT INTO players", + span.attributes.get(SpanAttributes.DB_STATEMENT), + ) self.check_meta(span) def test_session_query(self): @@ -144,14 +149,14 @@ class SQLAlchemyTestMixin(TestBase): self.assertEqual(len(spans), 1) span = spans[0] stmt = "SELECT players.id AS players_id, players.name AS players_name \nFROM players \nWHERE players.name = " - if span.attributes.get("db.system") == "sqlite": + if span.attributes.get(SpanAttributes.DB_SYSTEM) == "sqlite": stmt += "?" else: stmt += "%(name_1)s" self._check_span(span, "SELECT") self.assertIn( "SELECT players.id AS players_id, players.name AS players_name \nFROM players \nWHERE players.name", - span.attributes.get(_STMT), + span.attributes.get(SpanAttributes.DB_STATEMENT), ) self.check_meta(span) @@ -166,7 +171,10 @@ class SQLAlchemyTestMixin(TestBase): self.assertEqual(len(spans), 1) span = spans[0] self._check_span(span, "SELECT") - self.assertEqual(span.attributes.get(_STMT), "SELECT * FROM players") + self.assertEqual( + span.attributes.get(SpanAttributes.DB_STATEMENT), + "SELECT * FROM players", + ) self.check_meta(span) def test_parent(self): diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py index eb3a99f16..c9e0a8dd1 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py @@ -19,13 +19,7 @@ import pytest from sqlalchemy.exc import ProgrammingError from opentelemetry import trace -from opentelemetry.instrumentation.sqlalchemy.engine import ( - _DB, - _HOST, - _PORT, - _STMT, - _USER, -) +from opentelemetry.semconv.trace import SpanAttributes from .mixins import SQLAlchemyTestMixin @@ -52,10 +46,21 @@ class MysqlConnectorTestCase(SQLAlchemyTestMixin): def check_meta(self, span): # check database connection tags - self.assertEqual(span.attributes.get(_HOST), MYSQL_CONFIG["host"]) - self.assertEqual(span.attributes.get(_PORT), MYSQL_CONFIG["port"]) - self.assertEqual(span.attributes.get(_DB), MYSQL_CONFIG["database"]) - self.assertEqual(span.attributes.get(_USER), MYSQL_CONFIG["user"]) + self.assertEqual( + span.attributes.get(SpanAttributes.NET_PEER_NAME), + MYSQL_CONFIG["host"], + ) + self.assertEqual( + span.attributes.get(SpanAttributes.NET_PEER_PORT), + MYSQL_CONFIG["port"], + ) + self.assertEqual( + span.attributes.get(SpanAttributes.DB_NAME), + MYSQL_CONFIG["database"], + ) + self.assertEqual( + span.attributes.get(SpanAttributes.DB_USER), MYSQL_CONFIG["user"] + ) def test_engine_execute_errors(self): # ensures that SQL errors are reported @@ -69,9 +74,12 @@ class MysqlConnectorTestCase(SQLAlchemyTestMixin): # span fields self.assertEqual(span.name, "SELECT opentelemetry-tests") self.assertEqual( - span.attributes.get(_STMT), "SELECT * FROM a_wrong_table" + span.attributes.get(SpanAttributes.DB_STATEMENT), + "SELECT * FROM a_wrong_table", + ) + self.assertEqual( + span.attributes.get(SpanAttributes.DB_NAME), self.SQL_DB ) - self.assertEqual(span.attributes.get(_DB), self.SQL_DB) self.check_meta(span) self.assertTrue(span.end_time - span.start_time > 0) # check the error diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py index ab14612db..d72791d97 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py @@ -20,12 +20,7 @@ import pytest from sqlalchemy.exc import ProgrammingError from opentelemetry import trace -from opentelemetry.instrumentation.sqlalchemy.engine import ( - _DB, - _HOST, - _PORT, - _STMT, -) +from opentelemetry.semconv.trace import SpanAttributes from .mixins import SQLAlchemyTestMixin @@ -52,8 +47,14 @@ class PostgresTestCase(SQLAlchemyTestMixin): def check_meta(self, span): # check database connection tags - self.assertEqual(span.attributes.get(_HOST), POSTGRES_CONFIG["host"]) - self.assertEqual(span.attributes.get(_PORT), POSTGRES_CONFIG["port"]) + self.assertEqual( + span.attributes.get(SpanAttributes.NET_PEER_NAME), + POSTGRES_CONFIG["host"], + ) + self.assertEqual( + span.attributes.get(SpanAttributes.NET_PEER_PORT), + POSTGRES_CONFIG["port"], + ) def test_engine_execute_errors(self): # ensures that SQL errors are reported @@ -67,9 +68,12 @@ class PostgresTestCase(SQLAlchemyTestMixin): # span fields self.assertEqual(span.name, "SELECT opentelemetry-tests") self.assertEqual( - span.attributes.get(_STMT), "SELECT * FROM a_wrong_table" + span.attributes.get(SpanAttributes.DB_STATEMENT), + "SELECT * FROM a_wrong_table", + ) + self.assertEqual( + span.attributes.get(SpanAttributes.DB_NAME), self.SQL_DB ) - self.assertEqual(span.attributes.get(_DB), self.SQL_DB) self.check_meta(span) self.assertTrue(span.end_time - span.start_time > 0) # check the error diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py index 2b00b4a07..0acba0fec 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py @@ -18,7 +18,7 @@ import pytest from sqlalchemy.exc import OperationalError from opentelemetry import trace -from opentelemetry.instrumentation.sqlalchemy.engine import _DB, _STMT +from opentelemetry.semconv.trace import SpanAttributes from .mixins import SQLAlchemyTestMixin @@ -45,9 +45,12 @@ class SQLiteTestCase(SQLAlchemyTestMixin): # span fields self.assertEqual(span.name, "SELECT :memory:") self.assertEqual( - span.attributes.get(_STMT), "SELECT * FROM a_wrong_table" + span.attributes.get(SpanAttributes.DB_STATEMENT), + "SELECT * FROM a_wrong_table", + ) + self.assertEqual( + span.attributes.get(SpanAttributes.DB_NAME), self.SQL_DB ) - self.assertEqual(span.attributes.get(_DB), self.SQL_DB) self.assertTrue((span.end_time - span.start_time) > 0) # check the error self.assertIs( diff --git a/tox.ini b/tox.ini index 54bd2abc4..3aa585931 100644 --- a/tox.ini +++ b/tox.ini @@ -216,6 +216,7 @@ commands_pre = ; Install common packages for all the tests. These are not needed in all the ; cases but it saves a lot of boilerplate in this file. test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api + test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk test: pip install {toxinidir}/opentelemetry-python-core/tests/util @@ -308,6 +309,7 @@ deps = commands_pre = python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api + python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation python -m pip install {toxinidir}/util/opentelemetry-util-http @@ -334,6 +336,7 @@ deps = commands_pre = sudo apt-get install libsnappy-dev python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api + python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk python -m pip install {toxinidir}/opentelemetry-python-core/tests/util @@ -398,6 +401,7 @@ changedir = commands_pre = pip install -e {toxinidir}/opentelemetry-python-core/opentelemetry-api \ + -e {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions \ -e {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation \ -e {toxinidir}/opentelemetry-python-core/opentelemetry-sdk \ -e {toxinidir}/opentelemetry-python-core/tests/util \