|
4 | 4 |
|
5 | 5 | """Charmed Machine Operator for the PostgreSQL database.""" |
6 | 6 |
|
| 7 | + |
| 8 | +def _remove_stale_otel_sdk_packages(): |
| 9 | + """Hack to remove stale opentelemetry sdk packages from the charm's python venv. |
| 10 | +
|
| 11 | + See https://github.com/canonical/grafana-agent-operator/issues/146 and |
| 12 | + https://bugs.launchpad.net/juju/+bug/2058335 for more context. This patch can be removed after |
| 13 | + this juju issue is resolved and sufficient time has passed to expect most users of this library |
| 14 | + have migrated to the patched version of juju. When this patch is removed, un-ignore rule E402 for this file in the pyproject.toml (see setting |
| 15 | + [tool.ruff.lint.per-file-ignores] in pyproject.toml). |
| 16 | +
|
| 17 | + This only has an effect if executed on an upgrade-charm event. |
| 18 | + """ |
| 19 | + # all imports are local to keep this function standalone, side-effect-free, and easy to revert later |
| 20 | + import os |
| 21 | + |
| 22 | + if os.getenv("JUJU_DISPATCH_PATH") != "hooks/upgrade-charm": |
| 23 | + return |
| 24 | + |
| 25 | + import logging |
| 26 | + import shutil |
| 27 | + from collections import defaultdict |
| 28 | + |
| 29 | + from importlib_metadata import distributions |
| 30 | + |
| 31 | + otel_logger = logging.getLogger("charm_tracing_otel_patcher") |
| 32 | + otel_logger.debug("Applying _remove_stale_otel_sdk_packages patch on charm upgrade") |
| 33 | + # group by name all distributions starting with "opentelemetry_" |
| 34 | + otel_distributions = defaultdict(list) |
| 35 | + for distribution in distributions(): |
| 36 | + name = distribution._normalized_name |
| 37 | + if name.startswith("opentelemetry_"): |
| 38 | + otel_distributions[name].append(distribution) |
| 39 | + |
| 40 | + otel_logger.debug(f"Found {len(otel_distributions)} opentelemetry distributions") |
| 41 | + |
| 42 | + # If we have multiple distributions with the same name, remove any that have 0 associated files |
| 43 | + for name, distributions_ in otel_distributions.items(): |
| 44 | + if len(distributions_) <= 1: |
| 45 | + continue |
| 46 | + |
| 47 | + otel_logger.debug(f"Package {name} has multiple ({len(distributions_)}) distributions.") |
| 48 | + for distribution in distributions_: |
| 49 | + if not distribution.files: # Not None or empty list |
| 50 | + path = distribution._path |
| 51 | + otel_logger.info(f"Removing empty distribution of {name} at {path}.") |
| 52 | + shutil.rmtree(path) |
| 53 | + |
| 54 | + otel_logger.debug("Successfully applied _remove_stale_otel_sdk_packages patch. ") |
| 55 | + |
| 56 | + |
| 57 | +# apply hacky patch to remove stale opentelemetry sdk packages on upgrade-charm. |
| 58 | +# it could be trouble if someone ever decides to implement their own tracer parallel to |
| 59 | +# ours and before the charm has inited. We assume they won't. |
| 60 | +# !!IMPORTANT!! keep all otlp imports UNDER this call. |
| 61 | +_remove_stale_otel_sdk_packages() |
| 62 | + |
| 63 | +# ruff: disable[E402] |
7 | 64 | import json |
8 | 65 | import logging |
9 | 66 | import os |
|
122 | 179 | from upgrade import PostgreSQLUpgrade, get_postgresql_dependencies_model |
123 | 180 | from utils import new_password, snap_refreshed |
124 | 181 |
|
| 182 | +# ruff: enable[E402] |
| 183 | + |
125 | 184 | logger = logging.getLogger(__name__) |
126 | 185 | logging.getLogger("httpx").setLevel(logging.WARNING) |
127 | 186 | logging.getLogger("httpcore").setLevel(logging.WARNING) |
|
0 commit comments