Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions solarwinds_apm/k8s.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
from contextlib import suppress

from opentelemetry.sdk.resources import Resource, ResourceDetector
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv.attributes.k8s_attributes import (
K8S_NAMESPACE_NAME,
K8S_POD_NAME,
K8S_POD_UID,
)

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -132,16 +136,16 @@ def detect(self) -> Resource:

namespace = _pod_namespace(self._namespace)
if namespace:
attributes[ResourceAttributes.K8S_NAMESPACE_NAME] = namespace
attributes[K8S_NAMESPACE_NAME] = namespace
else:
return Resource.get_empty()

uid = _pod_uid(self._mountinfo)
if uid:
attributes[ResourceAttributes.K8S_POD_UID] = uid
attributes[K8S_POD_UID] = uid

name = _pod_name()
if name:
attributes[ResourceAttributes.K8S_POD_NAME] = name
attributes[K8S_POD_NAME] = name

return Resource(attributes)
21 changes: 12 additions & 9 deletions solarwinds_apm/trace/response_time_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@

from opentelemetry.metrics import get_meter
from opentelemetry.sdk.trace import SpanProcessor
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv._incubating.attributes.http_attributes import (
HTTP_METHOD,
HTTP_STATUS_CODE,
)
from opentelemetry.semconv.attributes.http_attributes import (
HTTP_REQUEST_METHOD,
HTTP_RESPONSE_STATUS_CODE,
)
from opentelemetry.trace import SpanKind, StatusCode

from solarwinds_apm.apm_constants import (
Expand All @@ -32,16 +39,12 @@ class ResponseTimeProcessor(SpanProcessor):
including response time, error status, and HTTP-specific attributes.
"""

_HTTP_REQUEST_METHOD = (
SpanAttributes.HTTP_REQUEST_METHOD
) # http.request.method
_HTTP_RESPONSE_STATUS_CODE = (
SpanAttributes.HTTP_RESPONSE_STATUS_CODE
) # "http.response.status_code"
_HTTP_REQUEST_METHOD = HTTP_REQUEST_METHOD # http.request.method
_HTTP_RESPONSE_STATUS_CODE = HTTP_RESPONSE_STATUS_CODE

# Deprecated, but potentially still used by some instrumentors
_HTTP_METHOD = SpanAttributes.HTTP_METHOD # "http.method"
_HTTP_STATUS_CODE = SpanAttributes.HTTP_STATUS_CODE # "http.status_code"
_HTTP_METHOD = HTTP_METHOD # "http.method"
_HTTP_STATUS_CODE = HTTP_STATUS_CODE # "http.status_code"

_HTTP_SPAN_STATUS_UNAVAILABLE = 0

Expand Down
13 changes: 8 additions & 5 deletions solarwinds_apm/trace/serviceentry_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

from opentelemetry import context
from opentelemetry.sdk.trace import Span, SpanProcessor
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv._incubating.attributes.faas_attributes import (
FAAS_NAME,
)
from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE
from opentelemetry.semconv.attributes.url_attributes import URL_PATH

from solarwinds_apm.apm_constants import (
INTL_SWO_OTEL_CONTEXT_ENTRY_SPAN,
Expand Down Expand Up @@ -107,10 +110,10 @@ def on_start(
# Calculate non-custom txn name for entry span if we can retrieve the URL
# or serverless name. Otherwise, use the span's name
sw_apm_txn_name = os.environ.get("SW_APM_TRANSACTION_NAME", None)
faas_name = span.attributes.get(ResourceAttributes.FAAS_NAME, None)
faas_name = span.attributes.get(FAAS_NAME, None)
lambda_function_name = os.environ.get("AWS_LAMBDA_FUNCTION_NAME", None)
http_route = span.attributes.get(SpanAttributes.HTTP_ROUTE, None)
url_path = span.attributes.get(SpanAttributes.URL_PATH, None)
http_route = span.attributes.get(HTTP_ROUTE, None)
url_path = span.attributes.get(URL_PATH, None)
if sw_apm_txn_name:
self.set_default_transaction_name(span, sw_apm_txn_name)
elif faas_name:
Expand Down
8 changes: 5 additions & 3 deletions solarwinds_apm/uams.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
set_value,
)
from opentelemetry.sdk.resources import Resource, ResourceDetector
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv._incubating.attributes.host_attributes import (
HOST_ID,
)

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -43,7 +45,7 @@ def _read_from_file(uams_file: str) -> dict:
uams_id = file.read().strip()
return {
ATTR_UAMS_CLIENT_ID: uams_id,
ResourceAttributes.HOST_ID: uams_id,
HOST_ID: uams_id,
}
except Exception as error: # pylint: disable=broad-exception-caught
logger.debug("file error", exc_info=error)
Expand All @@ -70,7 +72,7 @@ def _read_from_api() -> dict:
id = data[UAMS_CLIENT_ID_FIELD]
return {
ATTR_UAMS_CLIENT_ID: id,
ResourceAttributes.HOST_ID: id,
HOST_ID: id,
}
except Exception as error: # pylint: disable=broad-exception-caught
logger.debug("api response error", exc_info=error)
Expand Down
24 changes: 14 additions & 10 deletions tests/unit/test_k8s.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
from contextlib import suppress

import pytest
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv.attributes.k8s_attributes import (
K8S_NAMESPACE_NAME,
K8S_POD_NAME,
K8S_POD_UID,
)

from solarwinds_apm.k8s import K8sResourceDetector

Expand Down Expand Up @@ -89,9 +93,9 @@ def test_detects_attributes_from_env(mocker):
resource = k8s_detector.detect()

assert resource.attributes == {
ResourceAttributes.K8S_NAMESPACE_NAME: ENV_NAMESPACE,
ResourceAttributes.K8S_POD_UID: ENV_UID,
ResourceAttributes.K8S_POD_NAME: ENV_NAME,
K8S_NAMESPACE_NAME: ENV_NAMESPACE,
K8S_POD_UID: ENV_UID,
K8S_POD_NAME: ENV_NAME,
}


Expand All @@ -103,11 +107,11 @@ def test_detects_attributes_from_files():
resource = k8s_detector.detect()

expected_attributes = {
ResourceAttributes.K8S_NAMESPACE_NAME: FILE_NAMESPACE,
ResourceAttributes.K8S_POD_NAME: os.uname().nodename,
K8S_NAMESPACE_NAME: FILE_NAMESPACE,
K8S_POD_NAME: os.uname().nodename,
}
if os.name != "nt":
expected_attributes[ResourceAttributes.K8S_POD_UID] = FILE_UID
expected_attributes[K8S_POD_UID] = FILE_UID

assert resource.attributes == expected_attributes

Expand All @@ -128,9 +132,9 @@ def test_prefers_env_over_files(mocker):
resource = k8s_detector.detect()

assert resource.attributes == {
ResourceAttributes.K8S_NAMESPACE_NAME: ENV_NAMESPACE,
ResourceAttributes.K8S_POD_UID: ENV_UID,
ResourceAttributes.K8S_POD_NAME: ENV_NAME,
K8S_NAMESPACE_NAME: ENV_NAMESPACE,
K8S_POD_UID: ENV_UID,
K8S_POD_NAME: ENV_NAME,
}


Expand Down
45 changes: 16 additions & 29 deletions tests/unit/test_processors/test_response_time_processor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Copyright SolarWinds Worldwide, LLC.
# SPDX-License-Identifier: Apache-2.0

from opentelemetry.semconv._incubating.attributes.http_attributes import (
HTTP_METHOD,
)
from opentelemetry.semconv.attributes.http_attributes import (
HTTP_REQUEST_METHOD,
)
from opentelemetry.trace import SpanKind

from solarwinds_apm.trace import ResponseTimeProcessor


Expand Down Expand Up @@ -40,49 +48,28 @@ def test__init(self, mocker):
assert processor.lambda_function_name == "foo-lambda-name"

def test_is_span_http_true(self, mocker):
mock_spankind = mocker.patch(
"solarwinds_apm.trace.response_time_processor.SpanKind"
)
mock_spankind.configure_mock(SERVER="foo")
mock_spanattributes = mocker.patch(
"solarwinds_apm.trace.response_time_processor.SpanAttributes"
)
mock_spanattributes.configure_mock(
HTTP_REQUEST_METHOD="http.request.method"
)
mock_span = mocker.Mock()
mock_span.configure_mock(
kind="foo", attributes={"http.request.method": "bar"}
kind=SpanKind.SERVER,
attributes={HTTP_REQUEST_METHOD: "GET"},
)
processor = ResponseTimeProcessor(mocker.Mock())
assert processor.is_span_http(mock_span)

def test_is_span_http_true_old_attr(self, mocker):
mock_spankind = mocker.patch(
"solarwinds_apm.trace.response_time_processor.SpanKind"
)
mock_spankind.configure_mock(SERVER="foo")
mock_spanattributes = mocker.patch(
"solarwinds_apm.trace.response_time_processor.SpanAttributes"
)
mock_spanattributes.configure_mock(HTTP_METHOD="http.method")
mock_span = mocker.Mock()
mock_span.configure_mock(kind="foo", attributes={"http.method": "bar"})
mock_span.configure_mock(
kind=SpanKind.SERVER,
attributes={HTTP_METHOD: "GET"},
)
processor = ResponseTimeProcessor(mocker.Mock())
assert processor.is_span_http(mock_span)

def test_is_span_http_false_no_http_method(self, mocker):
mock_spankind = mocker.patch(
"solarwinds_apm.trace.response_time_processor.SpanKind"
)
mock_spankind.configure_mock(SERVER="foo")
mock_spanattributes = mocker.patch(
"solarwinds_apm.trace.response_time_processor.SpanAttributes"
)
mock_spanattributes.configure_mock(HTTP_METHOD="http.method")
mock_span = mocker.Mock()
mock_span.configure_mock(
kind="foo", attributes={"NOT.http.method.hehehehe": "bar"}
kind=SpanKind.SERVER,
attributes={"NOT.http.method.hehehehe": "bar"},
)
processor = ResponseTimeProcessor(mocker.Mock())
assert not processor.is_span_http(mock_span)
Expand Down
12 changes: 7 additions & 5 deletions tests/unit/test_uams.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
from unittest.mock import MagicMock, patch

import pytest
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv._incubating.attributes.host_attributes import (
HOST_ID,
)

from solarwinds_apm.uams import ATTR_UAMS_CLIENT_ID, UamsResourceDetector

Expand Down Expand Up @@ -41,7 +43,7 @@ def test_detects_id_from_file_when_file_present_and_api_running(
resource = detector.detect()
assert resource.attributes == {
ATTR_UAMS_CLIENT_ID: UAMS_FILE_ID,
ResourceAttributes.HOST_ID: UAMS_FILE_ID,
HOST_ID: UAMS_FILE_ID,
}
# Ensure the API was not called
mock_get.assert_not_called()
Expand All @@ -54,7 +56,7 @@ def test_detects_id_from_file_when_file_present_and_api_not_running(
resource = detector.detect()
assert resource.attributes == {
ATTR_UAMS_CLIENT_ID: UAMS_FILE_ID,
ResourceAttributes.HOST_ID: UAMS_FILE_ID,
HOST_ID: UAMS_FILE_ID,
}


Expand All @@ -72,7 +74,7 @@ def test_detects_id_from_file_when_file_present_and_unrelated_running(
resource = detector.detect()
assert resource.attributes == {
ATTR_UAMS_CLIENT_ID: UAMS_FILE_ID,
ResourceAttributes.HOST_ID: UAMS_FILE_ID,
HOST_ID: UAMS_FILE_ID,
}
# Ensure the API was not called
mock_get.assert_not_called()
Expand All @@ -90,7 +92,7 @@ def test_detects_id_from_api_when_file_not_present_and_api_running(mock_get):
resource = detector.detect()
assert resource.attributes == {
ATTR_UAMS_CLIENT_ID: UAMS_API_ID,
ResourceAttributes.HOST_ID: UAMS_API_ID,
HOST_ID: UAMS_API_ID,
}
# Ensure the API was called
mock_get.assert_called_once()
Expand Down
Loading