|
1 | | -""" |
2 | | -Tracing utilities for the psycopg2 potgres client library. |
3 | | -""" |
4 | | -import functools |
5 | | - |
6 | 1 | import wrapt |
7 | 2 |
|
8 | | -from ddtrace import config |
9 | | -from ddtrace.constants import _SPAN_MEASURED_KEY |
10 | | -from ddtrace.constants import SPAN_KIND |
11 | | -from ddtrace.ext import SpanKind |
12 | | -from ddtrace.ext import SpanTypes |
13 | | -from ddtrace.ext import db |
14 | | -from ddtrace.ext import net |
15 | | -from ddtrace.internal.constants import COMPONENT |
16 | | -from ddtrace.internal.schema import schematize_database_operation |
17 | | - |
18 | 3 |
|
19 | 4 | def get_psycopg2_extensions(psycopg_module): |
20 | | - class TracedCursor(psycopg_module.extensions.cursor): |
21 | | - """Wrapper around cursor creating one span per query""" |
22 | | - |
23 | | - def __init__(self, *args, **kwargs): |
24 | | - self._datadog_tracer = kwargs.pop("datadog_tracer", None) |
25 | | - self._datadog_service = kwargs.pop("datadog_service", None) |
26 | | - self._datadog_tags = kwargs.pop("datadog_tags", None) |
27 | | - super(TracedCursor, self).__init__(*args, **kwargs) |
28 | | - |
29 | | - def execute(self, query, vars=None): # noqa: A002 |
30 | | - """just wrap the cursor execution in a span""" |
31 | | - if not self._datadog_tracer: |
32 | | - return psycopg_module.extensions.cursor.execute(self, query, vars) |
33 | | - |
34 | | - with self._datadog_tracer.trace( |
35 | | - schematize_database_operation("postgres.query", database_provider="postgresql"), |
36 | | - service=self._datadog_service, |
37 | | - span_type=SpanTypes.SQL, |
38 | | - ) as s: |
39 | | - s.set_tag_str(COMPONENT, config.psycopg.integration_name) |
40 | | - s.set_tag_str(db.SYSTEM, config.psycopg.dbms_name) |
41 | | - |
42 | | - # set span.kind to the type of operation being performed |
43 | | - s.set_tag_str(SPAN_KIND, SpanKind.CLIENT) |
44 | | - |
45 | | - # PERF: avoid setting via Span.set_tag |
46 | | - s.set_metric(_SPAN_MEASURED_KEY, 1) |
47 | | - if s.context.sampling_priority is None or s.context.sampling_priority <= 0: |
48 | | - return super(TracedCursor, self).execute(query, vars) |
49 | | - |
50 | | - s.resource = query |
51 | | - s.set_tags(self._datadog_tags) |
52 | | - try: |
53 | | - return super(TracedCursor, self).execute(query, vars) |
54 | | - finally: |
55 | | - s.set_metric(db.ROWCOUNT, self.rowcount) |
56 | | - |
57 | | - def callproc(self, procname, vars=None): # noqa: A002 |
58 | | - """just wrap the execution in a span""" |
59 | | - return psycopg_module.extensions.cursor.callproc(self, procname, vars) |
60 | | - |
61 | | - class TracedConnection(psycopg_module.extensions.connection): |
62 | | - """Wrapper around psycopg2 for tracing""" |
63 | | - |
64 | | - def __init__(self, *args, **kwargs): |
65 | | - self._datadog_tracer = kwargs.pop("datadog_tracer", None) |
66 | | - self._datadog_service = kwargs.pop("datadog_service", None) |
67 | | - |
68 | | - super(TracedConnection, self).__init__(*args, **kwargs) |
69 | | - |
70 | | - # add metadata (from the connection, string, etc) |
71 | | - dsn = psycopg_module.extensions.parse_dsn(self.dsn) |
72 | | - self._datadog_tags = { |
73 | | - net.TARGET_HOST: dsn.get("host"), |
74 | | - net.TARGET_PORT: dsn.get("port"), |
75 | | - net.SERVER_ADDRESS: dsn.get("host"), |
76 | | - db.NAME: dsn.get("dbname"), |
77 | | - db.USER: dsn.get("user"), |
78 | | - db.SYSTEM: config.psycopg.dbms_name, |
79 | | - "db.application": dsn.get("application_name"), |
80 | | - } |
81 | | - |
82 | | - self._datadog_cursor_class = functools.partial( |
83 | | - TracedCursor, |
84 | | - datadog_tracer=self._datadog_tracer, |
85 | | - datadog_service=self._datadog_service, |
86 | | - datadog_tags=self._datadog_tags, |
87 | | - ) |
88 | | - |
89 | | - def cursor(self, *args, **kwargs): |
90 | | - """register our custom cursor factory""" |
91 | | - kwargs.setdefault("cursor_factory", self._datadog_cursor_class) |
92 | | - return super(TracedConnection, self).cursor(*args, **kwargs) |
93 | | - |
94 | | - # extension hooks |
95 | 5 | _extensions = [ |
96 | 6 | ( |
97 | 7 | psycopg_module.extensions.register_type, |
|
0 commit comments