Skip to content

Commit 94e2588

Browse files
authored
feat(opentelemetry_nebulex): add database semantic convention attributes (#600)
Adds OpenTelemetry semantic convention attributes for better cache operation observability: - db.system: The database/cache backend system (e.g., :ets) - db.operation.name: The cache operation being performed (e.g., :get, :put) - db.query.text: Human-readable query showing the cache key being accessed This provides standardized attributes following OTel SemConv v1.27+ and improves debugging by making cache keys visible in traces.
1 parent 687f379 commit 94e2588

File tree

5 files changed

+70
-16
lines changed

5 files changed

+70
-16
lines changed

instrumentation/opentelemetry_nebulex/lib/opentelemetry_nebulex.ex

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ defmodule OpentelemetryNebulex do
44
from Nebulex command events.
55
"""
66

7+
alias OpenTelemetry.SemConv.Incubating.DBAttributes
8+
alias OpentelemetryNebulex.NebulexAttributes
9+
710
@tracer_id __MODULE__
811

912
@doc """
@@ -66,11 +69,13 @@ defmodule OpentelemetryNebulex do
6669

6770
attributes =
6871
%{
69-
"nebulex.cache": metadata.adapter_meta.cache
72+
NebulexAttributes.nebulex_cache() => metadata.adapter_meta.cache,
73+
DBAttributes.db_system() => metadata.adapter_meta[:backend],
74+
DBAttributes.db_operation_name() => db_operation(metadata),
75+
DBAttributes.db_query_text() => db_statement(metadata)
7076
}
71-
|> maybe_put(:"nebulex.backend", metadata.adapter_meta[:backend])
72-
|> maybe_put(:"nebulex.keyslot", metadata.adapter_meta[:keyslot])
73-
|> maybe_put(:"nebulex.model", metadata.adapter_meta[:model])
77+
|> maybe_put(NebulexAttributes.nebulex_keyslot(), metadata.adapter_meta[:keyslot])
78+
|> maybe_put(NebulexAttributes.nebulex_model(), metadata.adapter_meta[:model])
7479

7580
OpentelemetryTelemetry.start_telemetry_span(@tracer_id, span_name, metadata, %{
7681
attributes: attributes
@@ -82,7 +87,7 @@ defmodule OpentelemetryNebulex do
8287
ctx = OpentelemetryTelemetry.set_current_telemetry_span(@tracer_id, metadata)
8388

8489
if action = extract_action(metadata) do
85-
OpenTelemetry.Span.set_attribute(ctx, :"nebulex.action", action)
90+
OpenTelemetry.Span.set_attribute(ctx, NebulexAttributes.nebulex_action(), action)
8691
end
8792

8893
OpentelemetryTelemetry.end_telemetry_span(@tracer_id, metadata)
@@ -108,4 +113,11 @@ defmodule OpentelemetryNebulex do
108113

109114
defp format_error(exception) when is_exception(exception), do: Exception.message(exception)
110115
defp format_error(error), do: inspect(error)
116+
117+
defp db_operation(%{function_name: operation}), do: operation
118+
defp db_operation(_), do: nil
119+
120+
defp db_statement(%{function_name: :get, args: [key]}), do: "GET #{inspect(key)}"
121+
defp db_statement(%{function_name: :put, args: [key | _tail]}), do: "PUT #{inspect(key)}"
122+
defp db_statement(_), do: nil
111123
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
defmodule OpentelemetryNebulex.NebulexAttributes do
2+
@moduledoc false
3+
4+
# Nebulex-specific OpenTelemetry Semantic Conventions attributes.
5+
#
6+
# Naming Conventions:
7+
# - Prefix with `nebulex.` to avoid conflicts with standard OTel attributes
8+
# - Use `snake_case` for attribute names
9+
# - Use dot notation for namespacing (e.g., `nebulex.cache`)
10+
11+
@doc """
12+
The name of the Nebulex cache being accessed.
13+
"""
14+
@spec nebulex_cache() :: :"nebulex.cache"
15+
def nebulex_cache, do: :"nebulex.cache"
16+
17+
@doc """
18+
The keyslot module used for partitioned caches.
19+
"""
20+
@spec nebulex_keyslot() :: :"nebulex.keyslot"
21+
def nebulex_keyslot, do: :"nebulex.keyslot"
22+
23+
@doc """
24+
The cache model used by multilevel caches.
25+
"""
26+
@spec nebulex_model() :: :"nebulex.model"
27+
def nebulex_model, do: :"nebulex.model"
28+
29+
@doc """
30+
The result of a cache operation (`:hit` or `:miss`).
31+
"""
32+
@spec nebulex_action() :: :"nebulex.action"
33+
def nebulex_action, do: :"nebulex.action"
34+
end

instrumentation/opentelemetry_nebulex/mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ defmodule OpentelemetryNebulex.MixProject do
6060
{:opentelemetry, "~> 1.5", only: [:dev, :test]},
6161
{:opentelemetry_api, "~> 1.4"},
6262
{:opentelemetry_exporter, "~> 1.8", only: [:dev, :test]},
63+
{:opentelemetry_semantic_conventions, "~> 1.27"},
6364
{:opentelemetry_telemetry, "~> 1.1"},
6465
{:telemetry, "~> 1.0"}
6566
]

instrumentation/opentelemetry_nebulex/mix.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"opentelemetry": {:hex, :opentelemetry, "1.5.0", "7dda6551edfc3050ea4b0b40c0d2570423d6372b97e9c60793263ef62c53c3c2", [:rebar3], [{:opentelemetry_api, "~> 1.4", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "cdf4f51d17b592fc592b9a75f86a6f808c23044ba7cf7b9534debbcc5c23b0ee"},
1818
"opentelemetry_api": {:hex, :opentelemetry_api, "1.4.0", "63ca1742f92f00059298f478048dfb826f4b20d49534493d6919a0db39b6db04", [:mix, :rebar3], [], "hexpm", "3dfbbfaa2c2ed3121c5c483162836c4f9027def469c41578af5ef32589fcfc58"},
1919
"opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.8.0", "5d546123230771ef4174e37bedfd77e3374913304cd6ea3ca82a2add49cd5d56", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.5.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.4.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.18", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "a1f9f271f8d3b02b81462a6bfef7075fd8457fdb06adff5d2537df5e2264d9af"},
20+
"opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "1.27.0", "acd0194a94a1e57d63da982ee9f4a9f88834ae0b31b0bd850815fe9be4bbb45f", [:mix, :rebar3], [], "hexpm", "9681ccaa24fd3d810b4461581717661fd85ff7019b082c2dff89c7d5b1fc2864"},
2021
"opentelemetry_telemetry": {:hex, :opentelemetry_telemetry, "1.1.2", "410ab4d76b0921f42dbccbe5a7c831b8125282850be649ee1f70050d3961118a", [:mix, :rebar3], [{:opentelemetry_api, "~> 1.3", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "641ab469deb181957ac6d59bce6e1321d5fe2a56df444fc9c19afcad623ab253"},
2122
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
2223
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},

instrumentation/opentelemetry_nebulex/test/opentelemetry_nebulex_test.exs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ defmodule OpentelemetryNebulexTest do
6767

6868
assert %{
6969
"nebulex.action": :miss,
70-
"nebulex.backend": :ets,
71-
"nebulex.cache": OpentelemetryNebulexTest.Local
70+
"nebulex.cache": OpentelemetryNebulexTest.Local,
71+
"db.system": :ets,
72+
"db.operation.name": :get,
73+
"db.query.text": "GET :my_key"
7274
} = :otel_attributes.map(attributes)
7375

7476
# write
@@ -77,8 +79,10 @@ defmodule OpentelemetryNebulexTest do
7779
assert_receive {:span, span(name: "nebulex put", kind: :internal, attributes: attributes)}
7880

7981
assert %{
80-
"nebulex.backend": :ets,
81-
"nebulex.cache": OpentelemetryNebulexTest.Local
82+
"nebulex.cache": OpentelemetryNebulexTest.Local,
83+
"db.system": :ets,
84+
"db.operation.name": :put,
85+
"db.query.text": "PUT :my_key"
8286
} = :otel_attributes.map(attributes)
8387

8488
# hit
@@ -88,8 +92,10 @@ defmodule OpentelemetryNebulexTest do
8892

8993
assert %{
9094
"nebulex.action": :hit,
91-
"nebulex.backend": :ets,
92-
"nebulex.cache": OpentelemetryNebulexTest.Local
95+
"nebulex.cache": OpentelemetryNebulexTest.Local,
96+
"db.system": :ets,
97+
"db.operation.name": :get,
98+
"db.query.text": "GET :my_key"
9399
} = :otel_attributes.map(attributes)
94100
end
95101

@@ -106,7 +112,7 @@ defmodule OpentelemetryNebulexTest do
106112

107113
assert %{
108114
"nebulex.action": :miss,
109-
"nebulex.backend": :ets,
115+
"db.system": :ets,
110116
"nebulex.cache": OpentelemetryNebulexTest.Partitioned.Primary
111117
} = :otel_attributes.map(attributes)
112118

@@ -124,7 +130,7 @@ defmodule OpentelemetryNebulexTest do
124130
assert_receive {:span, span(name: "nebulex put", kind: :internal, attributes: attributes)}
125131

126132
assert %{
127-
"nebulex.backend": :ets,
133+
"db.system": :ets,
128134
"nebulex.cache": OpentelemetryNebulexTest.Partitioned.Primary
129135
} = :otel_attributes.map(attributes)
130136

@@ -142,7 +148,7 @@ defmodule OpentelemetryNebulexTest do
142148

143149
assert %{
144150
"nebulex.action": :hit,
145-
"nebulex.backend": :ets,
151+
"db.system": :ets,
146152
"nebulex.cache": OpentelemetryNebulexTest.Partitioned.Primary
147153
} = :otel_attributes.map(attributes)
148154

@@ -176,7 +182,7 @@ defmodule OpentelemetryNebulexTest do
176182
assert_receive {:span, span(name: "nebulex put", kind: :internal, attributes: attributes)}
177183

178184
assert %{
179-
"nebulex.backend": :ets,
185+
"db.system": :ets,
180186
"nebulex.cache": OpentelemetryNebulexTest.Multilevel.L1
181187
} = :otel_attributes.map(attributes)
182188

@@ -200,7 +206,7 @@ defmodule OpentelemetryNebulexTest do
200206

201207
assert %{
202208
"nebulex.action": :hit,
203-
"nebulex.backend": :ets,
209+
"db.system": :ets,
204210
"nebulex.cache": OpentelemetryNebulexTest.Multilevel.L1
205211
} = :otel_attributes.map(attributes)
206212

0 commit comments

Comments
 (0)