|
| 1 | +""" |
| 2 | +Copyright (c) 2024 Scale3 Labs |
| 3 | +
|
| 4 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +you may not use this file except in compliance with the License. |
| 6 | +You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +See the License for the specific language governing permissions and |
| 14 | +limitations under the License. |
| 15 | +""" |
| 16 | + |
| 17 | +import re |
| 18 | +from importlib_metadata import version as v |
| 19 | +from langtrace.trace_attributes import DatabaseSpanAttributes |
| 20 | +from opentelemetry import baggage, trace |
| 21 | +from opentelemetry.trace import SpanKind,Tracer |
| 22 | +from opentelemetry.trace.propagation import set_span_in_context |
| 23 | +from opentelemetry.trace.status import Status, StatusCode |
| 24 | + |
| 25 | +from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME |
| 26 | +from langtrace_python_sdk.constants.instrumentation.common import ( |
| 27 | + LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, |
| 28 | + SERVICE_PROVIDERS, |
| 29 | +) |
| 30 | +from langtrace_python_sdk.constants.instrumentation.pgvector import APIS |
| 31 | +from langtrace_python_sdk.utils.llm import get_span_name |
| 32 | +from langtrace_python_sdk.utils.misc import extract_input_params, to_iso_format |
| 33 | + |
| 34 | + |
| 35 | +# Utility function to extract table name |
| 36 | +def extract_table_name(query): |
| 37 | + # This regex assumes basic SQL queries like SELECT, INSERT INTO, UPDATE, DELETE FROM |
| 38 | + match = re.search(r'(from|into|update|delete\s+from)\s+(\w+)', query, re.IGNORECASE) |
| 39 | + if match: |
| 40 | + return match.group(2) |
| 41 | + return None |
| 42 | + |
| 43 | + |
| 44 | +def generic_patch(method_name, version, tracer: Tracer): |
| 45 | + |
| 46 | + def traced_method(wrapped, instance, args, kwargs): |
| 47 | + query = args[0] |
| 48 | + params = args[1] if len(args) > 1 else None |
| 49 | + api = APIS[method_name] |
| 50 | + service_provider = SERVICE_PROVIDERS["PGVECTOR"] |
| 51 | + extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY) |
| 52 | + |
| 53 | + span_attributes = { |
| 54 | + "langtrace.sdk.name": "langtrace-python-sdk", |
| 55 | + "langtrace.service.name": service_provider, |
| 56 | + "langtrace.service.type": "vectordb", |
| 57 | + "langtrace.service.version": version, |
| 58 | + "langtrace.version": v(LANGTRACE_SDK_NAME), |
| 59 | + "db.system": "pgvector", |
| 60 | + "db.operation": api["OPERATION"], |
| 61 | + "db.collection.name": extract_table_name(query), |
| 62 | + "db.namespace": instance.connection.info.dbname, |
| 63 | + "db.query": str(query), |
| 64 | + **(extra_attributes if extra_attributes is not None else {}), |
| 65 | + } |
| 66 | + |
| 67 | + attributes = DatabaseSpanAttributes(**span_attributes) |
| 68 | + |
| 69 | + with tracer.start_as_current_span( |
| 70 | + name=get_span_name(method_name), |
| 71 | + kind=SpanKind.CLIENT, |
| 72 | + context=set_span_in_context(trace.get_current_span()), |
| 73 | + ) as span: |
| 74 | + for field, value in attributes.model_dump(by_alias=True).items(): |
| 75 | + if value is not None: |
| 76 | + span.set_attribute(field, value) |
| 77 | + try: |
| 78 | + # Attempt to call the original method |
| 79 | + result = wrapped(*args, **kwargs) |
| 80 | + span.set_status(StatusCode.OK) |
| 81 | + return result |
| 82 | + except Exception as err: |
| 83 | + # Record the exception in the span |
| 84 | + span.record_exception(err) |
| 85 | + # Set the span status to indicate an error |
| 86 | + span.set_status(Status(StatusCode.ERROR, str(err))) |
| 87 | + # Reraise the exception to ensure it's not swallowed |
| 88 | + raise |
| 89 | + |
| 90 | + return traced_method |
0 commit comments