From 65cf3e23255bf70453b404532eac3e42f1f207cf Mon Sep 17 00:00:00 2001 From: Pablo Collins Date: Fri, 13 Dec 2024 13:33:13 -0500 Subject: [PATCH 1/5] Add an example, import env var constants Tweak readme --- README.md | 2 +- examples/splunk_opentelemetry.py | 19 ++++++++++++++++ pyproject.toml | 2 +- src/splunk_otel/env.py | 39 +++++++++++++++++++++----------- 4 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 examples/splunk_opentelemetry.py diff --git a/README.md b/README.md index d378c2e..5d817fb 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ This distribution comes with the following defaults: ## Requirements -This Splunk Distribution of OpenTelemetry requires Python 3.7 or later. Supported +This Splunk Distribution of OpenTelemetry requires Python 3.8 or later. Supported libraries are listed [here](https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation). diff --git a/examples/splunk_opentelemetry.py b/examples/splunk_opentelemetry.py new file mode 100644 index 0000000..2ef2cdd --- /dev/null +++ b/examples/splunk_opentelemetry.py @@ -0,0 +1,19 @@ +import os +import time + +from opentelemetry import trace +from opentelemetry.sdk.environment_variables import OTEL_SERVICE_NAME +from splunk_otel import init_splunk_otel +from splunk_otel.env import SPLUNK_ACCESS_TOKEN, SPLUNK_REALM + +os.environ[OTEL_SERVICE_NAME] = "my-svc" +os.environ[SPLUNK_REALM] = "us1" +os.environ[SPLUNK_ACCESS_TOKEN] = "your-splunk-access-token-here" + +# The `init_splunk_otel` command sets up Splunk OTel Python. It is equivalent to running `opentelemetry-instrument`. +init_splunk_otel() + +tracer = trace.get_tracer("my-tracer") +for i in range(12): + with tracer.start_as_current_span(f"my-span-{i}"): + time.sleep(0.1) diff --git a/pyproject.toml b/pyproject.toml index 407ead2..f2063dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,5 +101,5 @@ exclude_lines = [ ] [tool.ruff.lint] -ignore = ["FA100", "ARG002"] +ignore = ["INP001", "FA100", "ARG002"] exclude = ["src/splunk_otel/profile_pb2.py"] diff --git a/src/splunk_otel/env.py b/src/splunk_otel/env.py index 81be7cf..c3f843c 100644 --- a/src/splunk_otel/env.py +++ b/src/splunk_otel/env.py @@ -14,20 +14,33 @@ import logging import os +from opentelemetry.environment_variables import OTEL_LOGS_EXPORTER, OTEL_METRICS_EXPORTER, OTEL_TRACES_EXPORTER +from opentelemetry.sdk.environment_variables import ( + OTEL_ATTRIBUTE_COUNT_LIMIT, + OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, + OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT, + OTEL_EXPERIMENTAL_RESOURCE_DETECTORS, + OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, + OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, + OTEL_SPAN_EVENT_COUNT_LIMIT, + OTEL_SPAN_LINK_COUNT_LIMIT, + OTEL_TRACES_SAMPLER, +) + DEFAULTS = { - "OTEL_PYTHON_LOG_CORRELATION": "true", # FIXME: revisit - "OTEL_TRACES_EXPORTER": "otlp", - "OTEL_METRICS_EXPORTER": "otlp", - "OTEL_LOGS_EXPORTER": "otlp", - "OTEL_ATTRIBUTE_COUNT_LIMIT": "", - "OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT": "", - "OTEL_SPAN_EVENT_COUNT_LIMIT": "", - "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT": "", - "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT": "", - "OTEL_SPAN_LINK_COUNT_LIMIT": "1000", - "OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT": "12000", - "OTEL_EXPERIMENTAL_RESOURCE_DETECTORS": "host,process", - "OTEL_TRACES_SAMPLER": "always_on", + "OTEL_PYTHON_LOG_CORRELATION": "true", # used by opentelemetry-instrumentation-logging (installed by bootstrap) + OTEL_TRACES_EXPORTER: "otlp", + OTEL_METRICS_EXPORTER: "otlp", + OTEL_LOGS_EXPORTER: "otlp", + OTEL_ATTRIBUTE_COUNT_LIMIT: "", + OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: "", + OTEL_SPAN_EVENT_COUNT_LIMIT: "", + OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT: "", + OTEL_LINK_ATTRIBUTE_COUNT_LIMIT: "", + OTEL_SPAN_LINK_COUNT_LIMIT: "1000", + OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT: "12000", + OTEL_EXPERIMENTAL_RESOURCE_DETECTORS: "host,process", + OTEL_TRACES_SAMPLER: "always_on", } OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED = "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED" From e1a883f03514ab3f3cd1820a124b16d63f440c09 Mon Sep 17 00:00:00 2001 From: Pablo Collins Date: Mon, 16 Dec 2024 18:52:04 -0500 Subject: [PATCH 2/5] Turn on otel logging by default --- src/splunk_otel/distro.py | 2 -- src/splunk_otel/env.py | 4 +-- tests/ott_logging.py | 56 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 tests/ott_logging.py diff --git a/src/splunk_otel/distro.py b/src/splunk_otel/distro.py index 0d8254e..3db9e31 100644 --- a/src/splunk_otel/distro.py +++ b/src/splunk_otel/distro.py @@ -29,7 +29,6 @@ from splunk_otel.__about__ import __version__ as version from splunk_otel.env import ( DEFAULTS, - OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, SPLUNK_ACCESS_TOKEN, SPLUNK_PROFILER_ENABLED, SPLUNK_PROFILER_LOGS_ENDPOINT, @@ -96,7 +95,6 @@ def set_env_defaults(self): def set_profiling_env(self): if self.env.is_true(SPLUNK_PROFILER_ENABLED, "false"): - self.env.setdefault(OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "true") logs_endpt = self.env.getval(SPLUNK_PROFILER_LOGS_ENDPOINT) if logs_endpt: self.env.setval(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, logs_endpt) diff --git a/src/splunk_otel/env.py b/src/splunk_otel/env.py index c3f843c..bc16ba9 100644 --- a/src/splunk_otel/env.py +++ b/src/splunk_otel/env.py @@ -28,7 +28,7 @@ ) DEFAULTS = { - "OTEL_PYTHON_LOG_CORRELATION": "true", # used by opentelemetry-instrumentation-logging (installed by bootstrap) + "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "true", OTEL_TRACES_EXPORTER: "otlp", OTEL_METRICS_EXPORTER: "otlp", OTEL_LOGS_EXPORTER: "otlp", @@ -43,8 +43,6 @@ OTEL_TRACES_SAMPLER: "always_on", } -OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED = "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED" - SPLUNK_OTEL_SYSTEM_METRICS_ENABLED = "SPLUNK_OTEL_SYSTEM_METRICS_ENABLED" SPLUNK_ACCESS_TOKEN = "SPLUNK_ACCESS_TOKEN" # noqa: S105 SPLUNK_TRACE_RESPONSE_HEADER_ENABLED = "SPLUNK_TRACE_RESPONSE_HEADER_ENABLED" diff --git a/tests/ott_logging.py b/tests/ott_logging.py new file mode 100644 index 0000000..dced7b2 --- /dev/null +++ b/tests/ott_logging.py @@ -0,0 +1,56 @@ +import logging + +from opentelemetry import trace + +from ott_lib import project_path + +MESSAGE = "uh oh!" +LOGGER_NAME = "logging-ott" + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + + tracer = trace.get_tracer(__file__) + logger = logging.getLogger(LOGGER_NAME) + with tracer.start_as_current_span("my-span"): + logger.warning(MESSAGE) + + +class LoggingOtelTest: + def requirements(self): + return project_path(), "opentelemetry-instrumentation-logging==0.49b2" + + def environment_variables(self): + return { + "OTEL_SERVICE_NAME": "mysvc", + "OTEL_PYTHON_DISABLED_INSTRUMENTATIONS": "system_metrics", + } + + def wrapper_command(self): + return "opentelemetry-instrument" + + def is_http(self): + return False + + def on_start(self): + return None + + def on_stop(self, telemetry, stdout: str, stderr: str, returncode: int) -> None: + records = get_scope_log_records(telemetry, LOGGER_NAME) + assert len(records) == 1 + record = records[0] + assert record.body.string_value == MESSAGE + assert record.trace_id + + +def get_scope_log_records(telemetry, scope_name): + from oteltest.telemetry import extract_leaves + + out = [] + scope_logs = extract_leaves( + telemetry, "log_requests", "pbreq", "resource_logs", "scope_logs" + ) + for scope_log in scope_logs: + if scope_log.scope.name == scope_name: + out.extend(scope_log.log_records) + return out From 9e1e9a6b24edadb6aa9860d83e2f346a9a9d27bd Mon Sep 17 00:00:00 2001 From: Pablo Collins Date: Mon, 16 Dec 2024 18:52:14 -0500 Subject: [PATCH 3/5] Lint --- tests/ott_logging.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/ott_logging.py b/tests/ott_logging.py index dced7b2..03b4851 100644 --- a/tests/ott_logging.py +++ b/tests/ott_logging.py @@ -1,7 +1,6 @@ import logging from opentelemetry import trace - from ott_lib import project_path MESSAGE = "uh oh!" @@ -47,9 +46,7 @@ def get_scope_log_records(telemetry, scope_name): from oteltest.telemetry import extract_leaves out = [] - scope_logs = extract_leaves( - telemetry, "log_requests", "pbreq", "resource_logs", "scope_logs" - ) + scope_logs = extract_leaves(telemetry, "log_requests", "pbreq", "resource_logs", "scope_logs") for scope_log in scope_logs: if scope_log.scope.name == scope_name: out.extend(scope_log.log_records) From 12bb7e4076ddfcedb361ee13aa6c9d5badae24bb Mon Sep 17 00:00:00 2001 From: Pablo Collins Date: Mon, 16 Dec 2024 18:55:48 -0500 Subject: [PATCH 4/5] Remove stale tests --- tests/test_distro.py | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/tests/test_distro.py b/tests/test_distro.py index e0598a3..8410d1c 100644 --- a/tests/test_distro.py +++ b/tests/test_distro.py @@ -74,26 +74,6 @@ def test_server_timing_resp_prop_false(): assert get_global_response_propagator() is None -def test_profiling_enabled(): - env_store = {"SPLUNK_PROFILER_ENABLED": "true"} - configure_distro(env_store) - assert env_store["OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED"] == "true" - - -def test_profiling_disabled(): - env_store = {"SPLUNK_PROFILER_ENABLED": "false"} - configure_distro(env_store) - assert "OTEL_LOGS_ENABLED" not in env_store - assert "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED" not in env_store - - -def test_profiling_notset(): - env_store = {} - configure_distro(env_store) - assert "OTEL_LOGS_ENABLED" not in env_store - assert "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED" not in env_store - - def test_profiling_endpt(): env_store = { "SPLUNK_PROFILER_ENABLED": "true", @@ -123,8 +103,14 @@ def test_service_name(caplog): def test_realm(): env_store = {"SPLUNK_REALM": "us2"} configure_distro(env_store) - assert env_store["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] == "https://ingest.us2.signalfx.com/v2/trace/otlp" - assert env_store["OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"] == "https://ingest.us2.signalfx.com/v2/datapoint/otlp" + assert ( + env_store["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] + == "https://ingest.us2.signalfx.com/v2/trace/otlp" + ) + assert ( + env_store["OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"] + == "https://ingest.us2.signalfx.com/v2/datapoint/otlp" + ) assert env_store["OTEL_EXPORTER_OTLP_PROTOCOL"] == "http/protobuf" From c798d03b8d5de85b308f41a5a6d1c1bc291e80de Mon Sep 17 00:00:00 2001 From: Pablo Collins Date: Mon, 16 Dec 2024 18:56:46 -0500 Subject: [PATCH 5/5] Lint --- tests/test_distro.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/test_distro.py b/tests/test_distro.py index 8410d1c..c11c40c 100644 --- a/tests/test_distro.py +++ b/tests/test_distro.py @@ -103,14 +103,8 @@ def test_service_name(caplog): def test_realm(): env_store = {"SPLUNK_REALM": "us2"} configure_distro(env_store) - assert ( - env_store["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] - == "https://ingest.us2.signalfx.com/v2/trace/otlp" - ) - assert ( - env_store["OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"] - == "https://ingest.us2.signalfx.com/v2/datapoint/otlp" - ) + assert env_store["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] == "https://ingest.us2.signalfx.com/v2/trace/otlp" + assert env_store["OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"] == "https://ingest.us2.signalfx.com/v2/datapoint/otlp" assert env_store["OTEL_EXPORTER_OTLP_PROTOCOL"] == "http/protobuf"