Skip to content

Commit c7e210d

Browse files
Update opentelemetry conventions (#245) (#249)
* update opentelemetry conventions * linter fixes * add response status codes * update requests URL for intersphinx (cherry picked from commit da5f360) Co-authored-by: Miguel Grinberg <miguel.grinberg@gmail.com>
1 parent 9833fc7 commit c7e210d

File tree

10 files changed

+45
-24
lines changed

10 files changed

+45
-24
lines changed

docs/sphinx/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,5 @@
4545

4646
intersphinx_mapping = {
4747
"python": ("https://docs.python.org/3", None),
48-
"requests": ("https://docs.python-requests.org/en/latest", None),
48+
"requests": ("https://requests.readthedocs.io/en/latest", None),
4949
}

elastic_transport/_async_transport.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ async def perform_request( # type: ignore[override, return]
260260
node: BaseAsyncNode = self.node_pool.get() # type: ignore[assignment]
261261
start_time = self._loop.time()
262262
try:
263-
otel_span.set_node_metadata(node.host, node.port, node.base_url, target)
263+
otel_span.set_node_metadata(
264+
node.host, node.port, node.base_url, target, method
265+
)
264266
resp = await node.perform_request(
265267
method,
266268
target,
@@ -364,6 +366,7 @@ async def perform_request( # type: ignore[override, return]
364366
# We either got a response we're happy with or
365367
# we've exhausted all of our retries so we return it.
366368
if not retry or attempt >= max_retries:
369+
otel_span.set_db_response(resp.meta.status)
367370
return TransportApiResponse(resp.meta, body)
368371
else:
369372
_logger.warning(

elastic_transport/_node/_http_aiohttp.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ async def perform_request( # type: ignore[override]
141141
headers: Optional[HttpHeaders] = None,
142142
request_timeout: Union[DefaultType, Optional[float]] = DEFAULT,
143143
) -> NodeApiResponse:
144-
global _AIOHTTP_FIXED_HEAD_BUG
145144
if self.session is None:
146145
self._create_aiohttp_session()
147146
assert self.session is not None

elastic_transport/_otel.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,25 @@ def __init__(
4949
self.body_strategy = body_strategy
5050
self.endpoint_id = endpoint_id
5151

52+
if self.otel_span:
53+
self.otel_span.set_attribute("db.system.name", "elasticsearch")
54+
if self.endpoint_id:
55+
self.otel_span.set_attribute("db.operation.name", self.endpoint_id)
56+
5257
def set_node_metadata(
53-
self, host: str, port: int, base_url: str, target: str
58+
self,
59+
host: str,
60+
port: int,
61+
base_url: str,
62+
target: str,
63+
method: str,
5464
) -> None:
5565
if self.otel_span is None:
5666
return
5767

5868
# url.full does not contain auth info which is passed as headers
5969
self.otel_span.set_attribute("url.full", base_url + target)
70+
self.otel_span.set_attribute("http.request.method", method)
6071
self.otel_span.set_attribute("server.address", host)
6172
self.otel_span.set_attribute("server.port", port)
6273

@@ -66,10 +77,10 @@ def set_elastic_cloud_metadata(self, headers: Mapping[str, str]) -> None:
6677

6778
cluster_name = headers.get("X-Found-Handling-Cluster")
6879
if cluster_name is not None:
69-
self.otel_span.set_attribute("db.elasticsearch.cluster.name", cluster_name)
80+
self.otel_span.set_attribute("db.namespace", cluster_name)
7081
node_name = headers.get("X-Found-Handling-Instance")
7182
if node_name is not None:
72-
self.otel_span.set_attribute("db.elasticsearch.node.name", node_name)
83+
self.otel_span.set_attribute("elasticsearch.node.name", node_name)
7384

7485
def set_db_statement(self, serialized_body: bytes) -> None:
7586
if self.otel_span is None:
@@ -79,5 +90,11 @@ def set_db_statement(self, serialized_body: bytes) -> None:
7990
return
8091
elif self.body_strategy == "raw" and self.endpoint_id in SEARCH_ENDPOINTS:
8192
self.otel_span.set_attribute(
82-
"db.statement", serialized_body.decode("utf-8")
93+
"db.query.text", serialized_body.decode("utf-8")
8394
)
95+
96+
def set_db_response(self, status_code: int) -> None:
97+
if self.otel_span is None:
98+
return
99+
100+
self.otel_span.set_attribute("db.response.status_code", str(status_code))

elastic_transport/_transport.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@ def perform_request( # type: ignore[return]
338338
node = self.node_pool.get()
339339
start_time = time.time()
340340
try:
341-
otel_span.set_node_metadata(node.host, node.port, node.base_url, target)
341+
otel_span.set_node_metadata(
342+
node.host, node.port, node.base_url, target, method
343+
)
342344
resp = node.perform_request(
343345
method,
344346
target,
@@ -442,6 +444,7 @@ def perform_request( # type: ignore[return]
442444
# We either got a response we're happy with or
443445
# we've exhausted all of our retries so we return it.
444446
if not retry or attempt >= max_retries:
447+
otel_span.set_db_response(resp.meta.status)
445448
return TransportApiResponse(resp.meta, body)
446449
else:
447450
_logger.warning(

tests/async_/test_async_transport.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,6 @@ async def test_sniff_on_start():
393393
calls = []
394394

395395
def sniff_callback(*args):
396-
nonlocal calls
397396
calls.append(args)
398397
return [NodeConfig("http", "localhost", 80)]
399398

@@ -420,7 +419,6 @@ async def test_sniff_before_requests():
420419
calls = []
421420

422421
def sniff_callback(*args):
423-
nonlocal calls
424422
calls.append(args)
425423
return []
426424

@@ -446,7 +444,6 @@ async def test_sniff_on_node_failure():
446444
calls = []
447445

448446
def sniff_callback(*args):
449-
nonlocal calls
450447
calls.append(args)
451448
return []
452449

@@ -551,15 +548,15 @@ async def test_sniffed_nodes_added_to_pool(async_sniff_callback):
551548
if async_sniff_callback:
552549

553550
async def sniff_callback(*_):
554-
nonlocal loop, sniffed_at
551+
nonlocal sniffed_at
555552
await asyncio.sleep(0.1)
556553
sniffed_at = loop.time()
557554
return sniffed_nodes
558555

559556
else:
560557

561558
def sniff_callback(*_):
562-
nonlocal loop, sniffed_at
559+
nonlocal sniffed_at
563560
time.sleep(0.1)
564561
sniffed_at = loop.time()
565562
return sniffed_nodes

tests/test_node_pool.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,6 @@ def __init__(self):
245245
self.nodes_gotten = 0
246246

247247
def run(self) -> None:
248-
nonlocal pool
249-
250248
while time.time() < start + 2:
251249
node = pool.get()
252250
self.nodes_gotten += 1

tests/test_otel.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def test_no_span():
4141
9200,
4242
"http://localhost:9200/",
4343
"_ml/anomaly_detectors/my-job/_open",
44+
"POST",
4445
)
4546
span.set_elastic_cloud_metadata(
4647
{
@@ -65,23 +66,30 @@ def test_detailed_span():
6566
9200,
6667
"http://localhost:9200/",
6768
"_ml/anomaly_detectors/my-job/_open",
69+
"POST",
6870
)
6971
span.set_elastic_cloud_metadata(
7072
{
7173
"X-Found-Handling-Cluster": "e9106fc68e3044f0b1475b04bf4ffd5f",
7274
"X-Found-Handling-Instance": "instance-0000000001",
7375
}
7476
)
77+
span.set_db_response(202)
7578

7679
spans = memory_exporter.get_finished_spans()
7780
assert len(spans) == 1
7881
assert spans[0].name == "ml.open_job"
7982
assert spans[0].attributes == {
83+
"db.system.name": "elasticsearch",
8084
"url.full": "http://localhost:9200/_ml/anomaly_detectors/my-job/_open",
85+
"http.request.method": "POST",
8186
"server.address": "localhost",
8287
"server.port": 9200,
83-
"db.elasticsearch.cluster.name": "e9106fc68e3044f0b1475b04bf4ffd5f",
84-
"db.elasticsearch.node.name": "instance-0000000001",
88+
"db.operation.name": "my-job/_open",
89+
"http.request.method": "POST",
90+
"db.namespace": "e9106fc68e3044f0b1475b04bf4ffd5f",
91+
"elasticsearch.node.name": "instance-0000000001",
92+
"db.response.status_code": "202",
8593
}
8694

8795

@@ -95,5 +103,7 @@ def test_db_statement():
95103
assert len(spans) == 1
96104
assert spans[0].name == "search"
97105
assert spans[0].attributes == {
98-
"db.statement": '{"query":{"match_all":{}}}',
106+
"db.system.name": "elasticsearch",
107+
"db.operation.name": "search",
108+
"db.query.text": '{"query":{"match_all":{}}}',
99109
}

tests/test_transport.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,6 @@ def test_sniff_on_start():
434434
calls = []
435435

436436
def sniff_callback(*args):
437-
nonlocal calls
438437
calls.append(args)
439438
return [NodeConfig("http", "localhost", 80)]
440439

@@ -458,7 +457,6 @@ def test_sniff_before_requests():
458457
calls = []
459458

460459
def sniff_callback(*args):
461-
nonlocal calls
462460
calls.append(args)
463461
return []
464462

@@ -482,7 +480,6 @@ def test_sniff_on_node_failure():
482480
calls = []
483481

484482
def sniff_callback(*args):
485-
nonlocal calls
486483
calls.append(args)
487484
return []
488485

@@ -655,8 +652,6 @@ def __init__(self):
655652
self.successful_requests = 0
656653

657654
def run(self) -> None:
658-
nonlocal t, start
659-
660655
while time.time() < start + 2:
661656
t.perform_request("GET", "/")
662657
self.successful_requests += 1

utils/build-dists.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def set_tmp_dir():
5454

5555

5656
def run(argv, expect_exit_code=0):
57-
global tmp_dir
5857
if tmp_dir is None:
5958
os.chdir(base_dir)
6059
else:

0 commit comments

Comments
 (0)