Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ jobs:
discovery.type: single-node
xpack.security.enabled: "false"
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
- image: mcr.microsoft.com/mssql/server:2022-latest
environment:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: YourStrong@Passw0rd
MSSQL_USER: sa
MSSQL_DATABASE: master
working_directory: ~/repo
steps:
- checkout
Expand Down
10 changes: 10 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,13 @@ services:
interval: 10s
timeout: 5s
retries: 5

mssql:
image: mcr.microsoft.com/azure-sql-edge
ports:
- 1433:1433
environment:
ACCEPT_EULA: Y
MSSQL_DATABASE: master
MSSQL_USER: sa
MSSQL_SA_PASSWORD: YourStrong@Passw0rd
1 change: 1 addition & 0 deletions src/instana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def boot_agent() -> None:
pika, # noqa: F401
psycopg2, # noqa: F401
pymongo, # noqa: F401
pymssql, # noqa: F401
pymysql, # noqa: F401
pyramid, # noqa: F401
redis, # noqa: F401
Expand Down
36 changes: 21 additions & 15 deletions src/instana/instrumentation/pep0249.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# (c) Copyright IBM Corp. 2021
# (c) Copyright Instana Inc. 2018

from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
from typing import TYPE_CHECKING, Any, Callable, Optional, Union

# This is a wrapper for PEP-0249: Python Database API Specification v2.0
import wrapt
Expand All @@ -24,8 +24,8 @@ def __init__(
self,
cursor: Any,
module_name: str,
connect_params: Optional[List[Union[str, Dict[str, Any]]]] = None,
cursor_params: Optional[Dict[str, Any]] = None,
connect_params: Optional[list[Union[str, dict[str, Any]]]] = None,
cursor_params: Optional[dict[str, Any]] = None,
) -> None:
super(CursorWrapper, self).__init__(wrapped=cursor)
self._module_name = module_name
Expand All @@ -52,9 +52,15 @@ def _collect_kvs(
self._connect_params[1][db_parameter_name],
)

Comment thread
pvital marked this conversation as resolved.
host = next(
(p for p in ("host", "server") if p in self._connect_params[1]),
None,
)
if host:
span.set_attribute("host", self._connect_params[1][host])

span.set_attribute(SpanAttributes.DB_STATEMENT, sql_sanitizer(sql))
span.set_attribute(SpanAttributes.DB_USER, self._connect_params[1]["user"])
span.set_attribute("host", self._connect_params[1]["host"])
span.set_attribute("port", self._connect_params[1]["port"])
except Exception as e:
logger.debug(e)
Expand All @@ -65,8 +71,8 @@ def __enter__(self) -> Self:
def execute(
self,
sql: str,
params: Optional[Dict[str, Any]] = None,
) -> Callable[[str, Dict[str, Any]], None]:
params: Optional[dict[str, Any]] = None,
) -> Callable[[str, dict[str, Any]], None]:
tracer, _, operation_name = get_tracer_tuple()

# If not tracing or we're being called from sqlalchemy, just pass through
Expand All @@ -90,8 +96,8 @@ def execute(
def executemany(
self,
sql: str,
seq_of_parameters: List[Dict[str, Any]],
) -> Callable[[str, List[Dict[str, Any]]], None]:
seq_of_parameters: list[dict[str, Any]],
) -> Callable[[str, list[dict[str, Any]]], None]:
tracer, _, operation_name = get_tracer_tuple()

# If not tracing or we're being called from sqlalchemy, just pass through
Expand All @@ -115,8 +121,8 @@ def executemany(
def callproc(
self,
proc_name: str,
params: Dict[str, Any],
) -> Callable[[str, Dict[str, Any]], None]:
params: dict[str, Any],
) -> Callable[[str, dict[str, Any]], None]:
tracer, _, operation_name = get_tracer_tuple()

# If not tracing or we're being called from sqlalchemy, just pass through
Expand Down Expand Up @@ -150,7 +156,7 @@ def __init__(
self,
connection: "ConnectionWrapper",
module_name: str,
connect_params: List[Union[str, Dict[str, Any]]],
connect_params: list[Union[str, dict[str, Any]]],
) -> None:
super(ConnectionWrapper, self).__init__(wrapped=connection)
self._module_name = module_name
Expand All @@ -161,8 +167,8 @@ def __enter__(self) -> Self:

def cursor(
self,
*args: Tuple[int, str, Dict[str, Any]],
**kwargs: Dict[str, Any],
*args: tuple[int, str, dict[str, Any]],
**kwargs: dict[str, Any],
) -> CursorWrapper:
return CursorWrapper(
cursor=self.__wrapped__.cursor(*args, **kwargs),
Expand Down Expand Up @@ -193,8 +199,8 @@ def __init__(

def __call__(
self,
*args: Tuple[int, str, Dict[str, Any]],
**kwargs: Dict[str, Any],
*args: tuple[int, str, dict[str, Any]],
**kwargs: dict[str, Any],
) -> ConnectionWrapper:
connect_params = (args, kwargs) if args or kwargs else None
return self._wrapper_ctor(
Expand Down
17 changes: 17 additions & 0 deletions src/instana/instrumentation/pymssql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# (c) Copyright IBM Corp. 2026

from instana.log import logger
from instana.instrumentation.pep0249 import ConnectionFactory

try:
import pymssql

cf = ConnectionFactory(connect_func=pymssql.connect, module_name="mssql")

setattr(pymssql, "connect", cf)
if hasattr(pymssql, "Connect"):
setattr(pymssql, "Connect", cf)

logger.debug("Instrumenting pymssql")
except ImportError:
pass
1 change: 1 addition & 0 deletions src/instana/span/kind.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"httpx",
"log",
"memcache",
"mssql",
"mongo",
"mysql",
"postgres",
Expand Down
13 changes: 13 additions & 0 deletions src/instana/span/registered_span.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ def _populate_exit_span_data(self, span: "InstanaSpan") -> None:
elif span.name == "mysql":
self._collect_mysql_attributes(span)

elif span.name == "mssql":
self._collect_mssql_attributes(span)

elif span.name == "postgres":
self._collect_postgres_attributes(span)

Expand Down Expand Up @@ -366,6 +369,16 @@ def _collect_mysql_attributes(self, span: "InstanaSpan") -> None:
)
self.data["mysql"]["error"] = span.attributes.pop("mysql.error", None)

def _collect_mssql_attributes(self, span: "InstanaSpan") -> None:
self.data["mssql"]["host"] = span.attributes.pop("host", None)
self.data["mssql"]["port"] = span.attributes.pop("port", None)
self.data["mssql"]["db"] = span.attributes.pop(SpanAttributes.DB_NAME, None)
self.data["mssql"]["user"] = span.attributes.pop(SpanAttributes.DB_USER, None)
self.data["mssql"]["stmt"] = span.attributes.pop(
SpanAttributes.DB_STATEMENT, None
)
self.data["mssql"]["error"] = span.attributes.pop("mssql.error", None)

def _collect_postgres_attributes(self, span: "InstanaSpan") -> None:
self.data["pg"]["host"] = span.attributes.pop("host", None)
self.data["pg"]["port"] = span.attributes.pop("port", None)
Expand Down
2 changes: 2 additions & 0 deletions src/instana/span/span.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ def record_exception(
self.set_attribute("lambda.error", message)
elif self.name.startswith("kafka"):
self.set_attribute("kafka.error", message)
elif self.name == "mssql":
self.set_attribute("mssql.error", message)
else:
_attributes = {"message": message}
if attributes:
Expand Down
Loading
Loading