Skip to content

Commit c0da0bd

Browse files
committed
2 parents c1b6fd5 + 53b8714 commit c0da0bd

File tree

7 files changed

+173
-45
lines changed

7 files changed

+173
-45
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash -e
2+
3+
sed -i "/\[stable\]/{n;s/version=.*/version=$1/}" eachdist.ini
4+
sed -i "/\[prerelease\]/{n;s/version=.*/version=$2/}" eachdist.ini
5+
6+
./scripts/eachdist.py update_patch_versions \
7+
--stable_version=$1 \
8+
--unstable_version=$2 \
9+
--stable_version_prev=$3 \
10+
--unstable_version_prev=$4
11+

.github/workflows/prepare-patch-release.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,18 @@ jobs:
4040
exit 1
4141
fi
4242
43+
stable_version_prev="$stable_major_minor.$((stable_patch))"
44+
unstable_version_prev="0.${unstable_minor}b$((unstable_patch))"
4345
stable_version="$stable_major_minor.$((stable_patch + 1))"
4446
unstable_version="0.${unstable_minor}b$((unstable_patch + 1))"
4547
4648
echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV
4749
echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV
50+
echo "STABLE_VERSION_PREV=$stable_version_prev" >> $GITHUB_ENV
51+
echo "UNSTABLE_VERSION_PREV=$unstable_version_prev" >> $GITHUB_ENV
4852
4953
- name: Update version
50-
run: .github/scripts/update-version.sh $STABLE_VERSION $UNSTABLE_VERSION
54+
run: .github/scripts/update-version-patch.sh $STABLE_VERSION $UNSTABLE_VERSION $STABLE_VERSION_PREV $UNSTABLE_VERSION_PREV
5155

5256
- name: Set up Python 3.9
5357
uses: actions/setup-python@v5

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4444
([#2635](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2635))
4545
- `opentelemetry-instrumentation` Add support for string based dotted module paths in unwrap
4646
([#2919](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2919))
47+
- `opentelemetry-instrumentation-dbapi` Add sqlcomment to `db.statement` attribute
48+
([#2935](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2935))
4749

4850
### Fixed
4951

instrumentation/opentelemetry-instrumentation-confluent-kafka/README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ Installation
1919
References
2020
----------
2121

22-
* `OpenTelemetry confluent-kafka/ Tracing <https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/confluent-kafka/confluent-kafka.html>`_
22+
* `OpenTelemetry confluent-kafka/ Tracing <https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/confluent_kafka/confluent_kafka.html>`_
2323
* `OpenTelemetry Project <https://opentelemetry.io/>`_

instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -492,49 +492,54 @@ def traced_execution(
492492
with self._db_api_integration._tracer.start_as_current_span(
493493
name, kind=SpanKind.CLIENT
494494
) as span:
495-
self._populate_span(span, cursor, *args)
496-
if args and self._commenter_enabled:
497-
try:
498-
args_list = list(args)
499-
500-
# lazy capture of mysql-connector client version using cursor
501-
if (
502-
self._db_api_integration.database_system == "mysql"
503-
and self._db_api_integration.connect_module.__name__
504-
== "mysql.connector"
505-
and not self._db_api_integration.commenter_data[
506-
"mysql_client_version"
507-
]
508-
):
509-
self._db_api_integration.commenter_data[
510-
"mysql_client_version"
511-
] = cursor._cnx._cmysql.get_client_info()
512-
513-
commenter_data = dict(
514-
self._db_api_integration.commenter_data
515-
)
516-
if self._commenter_options.get(
517-
"opentelemetry_values", True
518-
):
519-
commenter_data.update(**_get_opentelemetry_values())
520-
521-
# Filter down to just the requested attributes.
522-
commenter_data = {
523-
k: v
524-
for k, v in commenter_data.items()
525-
if self._commenter_options.get(k, True)
526-
}
527-
statement = _add_sql_comment(
528-
args_list[0], **commenter_data
529-
)
530-
531-
args_list[0] = statement
532-
args = tuple(args_list)
533-
534-
except Exception as exc: # pylint: disable=broad-except
535-
_logger.exception(
536-
"Exception while generating sql comment: %s", exc
537-
)
495+
if span.is_recording():
496+
if args and self._commenter_enabled:
497+
try:
498+
args_list = list(args)
499+
500+
# lazy capture of mysql-connector client version using cursor
501+
if (
502+
self._db_api_integration.database_system == "mysql"
503+
and self._db_api_integration.connect_module.__name__
504+
== "mysql.connector"
505+
and not self._db_api_integration.commenter_data[
506+
"mysql_client_version"
507+
]
508+
):
509+
self._db_api_integration.commenter_data[
510+
"mysql_client_version"
511+
] = cursor._cnx._cmysql.get_client_info()
512+
513+
commenter_data = dict(
514+
self._db_api_integration.commenter_data
515+
)
516+
if self._commenter_options.get(
517+
"opentelemetry_values", True
518+
):
519+
commenter_data.update(
520+
**_get_opentelemetry_values()
521+
)
522+
523+
# Filter down to just the requested attributes.
524+
commenter_data = {
525+
k: v
526+
for k, v in commenter_data.items()
527+
if self._commenter_options.get(k, True)
528+
}
529+
statement = _add_sql_comment(
530+
args_list[0], **commenter_data
531+
)
532+
533+
args_list[0] = statement
534+
args = tuple(args_list)
535+
536+
except Exception as exc: # pylint: disable=broad-except
537+
_logger.exception(
538+
"Exception while generating sql comment: %s", exc
539+
)
540+
541+
self._populate_span(span, cursor, *args)
542+
538543
return query_method(*args, **kwargs)
539544

540545

instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515

1616
import logging
17+
import re
1718
from unittest import mock
1819

1920
from opentelemetry import context
@@ -306,6 +307,44 @@ def __getattr__(self, name):
306307
r"Select 1 /\*dbapi_level='1.0',dbapi_threadsafety='unknown',driver_paramstyle='unknown',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
307308
)
308309

310+
def test_executemany_comment_matches_db_statement_attribute(self):
311+
connect_module = mock.MagicMock()
312+
connect_module.__version__ = mock.MagicMock()
313+
connect_module.__libpq_version__ = 123
314+
connect_module.apilevel = 123
315+
connect_module.threadsafety = 123
316+
connect_module.paramstyle = "test"
317+
318+
db_integration = dbapi.DatabaseApiIntegration(
319+
"testname",
320+
"postgresql",
321+
enable_commenter=True,
322+
commenter_options={"db_driver": False, "dbapi_level": False},
323+
connect_module=connect_module,
324+
)
325+
mock_connection = db_integration.wrapped_connection(
326+
mock_connect, {}, {}
327+
)
328+
cursor = mock_connection.cursor()
329+
cursor.executemany("Select 1;")
330+
self.assertRegex(
331+
cursor.query,
332+
r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
333+
)
334+
spans_list = self.memory_exporter.get_finished_spans()
335+
self.assertEqual(len(spans_list), 1)
336+
span = spans_list[0]
337+
self.assertRegex(
338+
span.attributes[SpanAttributes.DB_STATEMENT],
339+
r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/",
340+
)
341+
342+
cursor_span_id = re.search(r"[a-zA-Z0-9_]{16}", cursor.query).group()
343+
db_statement_span_id = re.search(
344+
r"[a-zA-Z0-9_]{16}", span.attributes[SpanAttributes.DB_STATEMENT]
345+
).group()
346+
self.assertEqual(cursor_span_id, db_statement_span_id)
347+
309348
def test_compatible_build_version_psycopg_psycopg2_libpq(self):
310349
connect_module = mock.MagicMock()
311350
connect_module.__name__ = "test"

scripts/eachdist.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,16 @@ def setup_instparser(instparser):
237237
"releaseargs", nargs=argparse.REMAINDER, help=extraargs_help("pytest")
238238
)
239239

240+
patchreleaseparser = subparsers.add_parser(
241+
"update_patch_versions",
242+
help="Updates version numbers during patch release, used by maintainers and CI",
243+
)
244+
patchreleaseparser.set_defaults(func=patch_release_args)
245+
patchreleaseparser.add_argument("--stable_version", required=True)
246+
patchreleaseparser.add_argument("--unstable_version", required=True)
247+
patchreleaseparser.add_argument("--stable_version_prev", required=True)
248+
patchreleaseparser.add_argument("--unstable_version_prev", required=True)
249+
240250
fmtparser = subparsers.add_parser(
241251
"format",
242252
help="Formats all source code with black and isort.",
@@ -655,6 +665,27 @@ def update_dependencies(targets, version, packages):
655665
)
656666

657667

668+
def update_patch_dependencies(targets, version, prev_version, packages):
669+
print("updating patch dependencies")
670+
if "all" in packages:
671+
packages.extend(targets)
672+
673+
# PEP 508 allowed specifier operators
674+
operators = ["==", "!=", "<=", ">=", "<", ">", "===", "~=", "="]
675+
operators_pattern = "|".join(re.escape(op) for op in operators)
676+
677+
for pkg in packages:
678+
search = rf"({basename(pkg)}[^,]*?)(\s?({operators_pattern})\s?)(.*{prev_version})"
679+
replace = r"\g<1>\g<2>" + version
680+
print(f"{search=}\t{replace=}\t{pkg=}")
681+
update_files(
682+
targets,
683+
"pyproject.toml",
684+
search,
685+
replace,
686+
)
687+
688+
658689
def update_files(targets, filename, search, replace):
659690
errors = False
660691
for target in targets:
@@ -687,10 +718,12 @@ def release_args(args):
687718
versions = args.versions
688719
updated_versions = []
689720

721+
# remove excluded packages
690722
excluded = cfg["exclude_release"]["packages"].split()
691723
targets = [
692724
target for target in targets if basename(target) not in excluded
693725
]
726+
694727
for group in versions.split(","):
695728
mcfg = cfg[group]
696729
version = mcfg["version"]
@@ -707,6 +740,40 @@ def release_args(args):
707740
update_changelogs("-".join(updated_versions))
708741

709742

743+
def patch_release_args(args):
744+
print("preparing patch release")
745+
746+
rootpath = find_projectroot()
747+
targets = list(find_targets_unordered(rootpath))
748+
cfg = ConfigParser()
749+
cfg.read(str(find_projectroot() / "eachdist.ini"))
750+
751+
# remove excluded packages
752+
excluded = cfg["exclude_release"]["packages"].split()
753+
targets = [
754+
target for target in targets if basename(target) not in excluded
755+
]
756+
757+
# stable
758+
mcfg = cfg["stable"]
759+
packages = mcfg["packages"].split()
760+
print(f"update stable packages to {args.stable_version}")
761+
762+
update_patch_dependencies(
763+
targets, args.stable_version, args.stable_version_prev, packages
764+
)
765+
update_version_files(targets, args.stable_version, packages)
766+
767+
# prerelease
768+
mcfg = cfg["prerelease"]
769+
packages = mcfg["packages"].split()
770+
print(f"update prerelease packages to {args.unstable_version}")
771+
update_patch_dependencies(
772+
targets, args.unstable_version, args.unstable_version_prev, packages
773+
)
774+
update_version_files(targets, args.unstable_version, packages)
775+
776+
710777
def test_args(args):
711778
clean_remainder_args(args.pytestargs)
712779
execute_args(

0 commit comments

Comments
 (0)