Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Telemetry setup #182

Merged
merged 7 commits into from
Mar 20, 2024
Merged
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
5 changes: 5 additions & 0 deletions DEVELOPERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ And then update with the latest upstream assets:
just assets/update
```

## Opentelemetry

To log opentelemetry traces to the console in local environments,
set the `OTEL_EXPORTER_CONSOLE` environment variable in your `.env` file.

## Testing

### Test categories
Expand Down
7 changes: 6 additions & 1 deletion airlock/views/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.urls import reverse
from django.views.decorators.http import require_http_methods
from django.views.decorators.vary import vary_on_headers
from opentelemetry import trace

from airlock.business_logic import RequestFileType, UrlPath, bll
from airlock.file_browser_api import get_workspace_tree
Expand All @@ -15,6 +16,9 @@
from .helpers import get_path_item_from_tree_or_404, get_workspace_or_raise, serve_file


tracer = trace.get_tracer_provider().get_tracer("airlock")


def grouped_workspaces(workspaces):
workspaces_by_project = defaultdict(list)
for workspace in workspaces:
Expand Down Expand Up @@ -43,7 +47,8 @@ def workspace_view(request, workspace_name: str, path: str = ""):
template = "file_browser/contents.html"
selected_only = True

tree = get_workspace_tree(workspace, path, selected_only)
with tracer.start_as_current_span("build_workspace_tree") as _span:
tree = get_workspace_tree(workspace, path, selected_only)
rebkwok marked this conversation as resolved.
Show resolved Hide resolved

path_item = get_path_item_from_tree_or_404(tree, path)

Expand Down
13 changes: 12 additions & 1 deletion dotenv-sample
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,22 @@ AIRLOCK_REQUEST_DIR=releases/
# in AIRLOCK_API_TOKEN is set)
AIRLOCK_DEV_USERS_FILE="dev_users.json"


# Note: in development, these settings will be automatically updated by
# `just job-server/{run,stop}
# In production you can find this token for an existing backend in the
# Job Server staff area at https://jobs.opensafely.org/staff/backends/ ,
# and you can use the default value for the endpoint.
AIRLOCK_API_TOKEN=
AIRLOCK_API_ENDPOINT="https://localhost:9000/api/v2"

# Opentelemetry
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io"
# key will be for specific prod/test/dev honeycomb environment
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=VALIDKEY1234"

# Set to True to log opentelemetry traces to the console in local env
export OTEL_EXPORTER_CONSOLE=True

# OTEL requires these, it needs to access settings before other stuff has initialised
DJANGO_SETTINGS_MODULE="airlock.settings"
PYTHONPATH="/usr/local/bin/python"
11 changes: 11 additions & 0 deletions gunicorn.conf.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import services.tracing as tracing


# workers
workers = 4

# listen
port = 8000
bind = "0.0.0.0"


# Because of Gunicorn's pre-fork web server model, we need to initialise opentelemetry
# in gunicorn's post_fork method in order to instrument our application process, see:
# https://opentelemetry-python.readthedocs.io/en/latest/examples/fork-process-model/README.html
def post_fork(server, worker):
server.log.info("Worker spawned (pid: %s)", worker.pid)
tracing.setup_default_tracing()
1 change: 1 addition & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ test *ARGS: devenv
--cov=local_db \
--cov=tests \
--cov=old_api \
--cov=services \
--cov-report=html \
--cov-report=term-missing:skip-covered

Expand Down
4 changes: 4 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
import os
import sys

import services.tracing as tracing


def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "airlock.settings")
tracing.setup_default_tracing()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, this is nice, being able to trace management commands is really nice.


try:
from django.core.management import execute_from_command_line
except ImportError as exc:
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ DJANGO_SETTINGS_MODULE = "airlock.settings"
testpaths = [
"tests"
]
filterwarnings = [
"ignore::DeprecationWarning:opentelemetry.*:",
]

[tool.coverage.run]
branch = true
Expand Down
5 changes: 5 additions & 0 deletions requirements.prod.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ gunicorn
requests
pydantic<2.0
ulid
opentelemetry-exporter-otlp-proto-http
opentelemetry-instrumentation-django
opentelemetry-instrumentation-requests
opentelemetry-instrumentation-sqlite3
opentelemetry-sdk
198 changes: 196 additions & 2 deletions requirements.prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ charset-normalizer==3.3.2 \
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
# via requests
deprecated==1.2.14 \
--hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \
--hash=sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3
# via
# opentelemetry-api
# opentelemetry-exporter-otlp-proto-http
django==5.0.3 \
--hash=sha256:5c7d748ad113a81b2d44750ccc41edc14e933f56581683db548c9257e078cc83 \
--hash=sha256:5fb37580dcf4a262f9258c1f4373819aacca906431f505e4688e37f3a99195df
Expand All @@ -127,6 +133,10 @@ django-vite==3.0.3 \
--hash=sha256:0738e6fe49ed097ab8e9e22ac78776584735948e118d3875817f78a87acaac82 \
--hash=sha256:3efe96d93cd77dfca4d8274c49db9dd43c545c95daab3c6b1e3dabf2236df943
# via -r requirements.prod.in
googleapis-common-protos==1.63.0 \
--hash=sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e \
--hash=sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632
# via opentelemetry-exporter-otlp-proto-http
gunicorn==21.2.0 \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
Expand All @@ -135,10 +145,106 @@ idna==3.6 \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
--hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
# via requests
importlib-metadata==6.11.0 \
--hash=sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443 \
--hash=sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b
# via opentelemetry-api
opentelemetry-api==1.23.0 \
--hash=sha256:14a766548c8dd2eb4dfc349739eb4c3893712a0daa996e5dbf945f9da665da9d \
--hash=sha256:cc03ea4025353048aadb9c64919099663664672ea1c6be6ddd8fee8e4cd5e774
# via
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-dbapi
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-sqlite3
# opentelemetry-instrumentation-wsgi
# opentelemetry-sdk
opentelemetry-exporter-otlp-proto-common==1.23.0 \
--hash=sha256:2a9e7e9d5a8b026b572684b6b24dcdefcaa58613d5ce3d644130b0c373c056c1 \
--hash=sha256:35e4ea909e7a0b24235bd0aaf17fba49676527feb1823b46565ff246d5a1ab18
# via opentelemetry-exporter-otlp-proto-http
opentelemetry-exporter-otlp-proto-http==1.23.0 \
--hash=sha256:088eac2320f4a604e2d9ff71aced71fdae601ac6457005fb0303d6bbbf44e6ca \
--hash=sha256:ad853b58681df8efcb2cfc93be2b5fd86351c99ff4ab47dc917da384b8650d91
# via -r requirements.prod.in
opentelemetry-instrumentation==0.44b0 \
--hash=sha256:79560f386425176bcc60c59190064597096114c4a8e5154f1cb281bb4e47d2fc \
--hash=sha256:8213d02d8c0987b9b26386ae3e091e0477d6331673123df736479322e1a50b48
# via
# opentelemetry-instrumentation-dbapi
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-sqlite3
# opentelemetry-instrumentation-wsgi
opentelemetry-instrumentation-dbapi==0.44b0 \
--hash=sha256:36333c7b2bbc6df660f5de965e0c0e8b02885c5b36016ec6386e6bba41c71280 \
--hash=sha256:8cbec84d01e7a7eabf2518186e74e6b95a25ec190ad834df409048dc8e0dbf86
# via opentelemetry-instrumentation-sqlite3
opentelemetry-instrumentation-django==0.44b0 \
--hash=sha256:44574d41e5a8d8a7b06e4d58758d6d2edfac9b61b12f788ff2163ebe27a8bbc2 \
--hash=sha256:b9ad75e2125416285e3d1f7b8b41684234d8fa731e71021898aa38fcc1e32b2b
# via -r requirements.prod.in
opentelemetry-instrumentation-requests==0.44b0 \
--hash=sha256:2ce4a647507afe55acf243b4bd669cc64b31a6444424e89d72d37a7fa0caf215 \
--hash=sha256:69fe6b72d4e6e229ae0d5eef356f0ade87488fcbd0f2f4782a7c616224d97266
# via -r requirements.prod.in
opentelemetry-instrumentation-sqlite3==0.44b0 \
--hash=sha256:235fd29bad1f9e08bf1e08363fc321ab2d137781e4618f4d7d49a5c4c6025fe4 \
--hash=sha256:7e4af8be7221648438c8b70a6fdc8f660c6d51a7f50562b76181c60d73a1298e
# via -r requirements.prod.in
opentelemetry-instrumentation-wsgi==0.44b0 \
--hash=sha256:8d2adc1183ccd17f1329db39b15c1cb759095da10ac1de70c64a653c0acdc9af \
--hash=sha256:b0fe5568de3847f1eb851a4cd2e226ac0a2f6c4d93c7a94766754c4673e8b758
# via opentelemetry-instrumentation-django
opentelemetry-proto==1.23.0 \
--hash=sha256:4c017deca052cb287a6003b7c989ed8b47af65baeb5d57ebf93dde0793f78509 \
--hash=sha256:e6aaf8b7ace8d021942d546161401b83eed90f9f2cc6f13275008cea730e4651
# via
# opentelemetry-exporter-otlp-proto-common
# opentelemetry-exporter-otlp-proto-http
opentelemetry-sdk==1.23.0 \
--hash=sha256:9ddf60195837b59e72fd2033d6a47e2b59a0f74f0ec37d89387d89e3da8cab7f \
--hash=sha256:a93c96990ac0f07c6d679e2f1015864ff7a4f5587122dd5af968034436efb1fd
# via
# -r requirements.prod.in
# opentelemetry-exporter-otlp-proto-http
opentelemetry-semantic-conventions==0.44b0 \
--hash=sha256:2e997cb28cd4ca81a25a9a43365f593d0c2b76be0685015349a89abdf1aa4ffa \
--hash=sha256:7c434546c9cbd797ab980cc88bf9ff3f4a5a28f941117cad21694e43d5d92019
# via
# opentelemetry-instrumentation-dbapi
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-wsgi
# opentelemetry-sdk
opentelemetry-util-http==0.44b0 \
--hash=sha256:75896dffcbbeb5df5429ad4526e22307fc041a27114e0c5bfd90bb219381e68f \
--hash=sha256:ff018ab6a2fa349537ff21adcef99a294248b599be53843c44f367aef6bccea5
# via
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-wsgi
# via gunicorn
packaging==24.0 \
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
# via gunicorn
protobuf==4.25.3 \
--hash=sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4 \
--hash=sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 \
--hash=sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c \
--hash=sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d \
--hash=sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4 \
--hash=sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa \
--hash=sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c \
--hash=sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 \
--hash=sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9 \
--hash=sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c \
--hash=sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2
# via
# googleapis-common-protos
# opentelemetry-proto
pydantic==1.10.14 \
--hash=sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8 \
--hash=sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f \
Expand Down Expand Up @@ -233,7 +339,9 @@ pyyaml==6.0.1 \
requests==2.31.0 \
--hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
--hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
# via -r requirements.prod.in
# via
# -r requirements.prod.in
# opentelemetry-exporter-otlp-proto-http
slippers==0.6.2 \
--hash=sha256:4cb555b8822ba0d404e5405723f5d723994022c29046008ee917081031bc0cf1 \
--hash=sha256:739e05f85354becbf0a65daab831eea62557d89e7512042209ab629af4378bca
Expand All @@ -250,6 +358,7 @@ typing-extensions==4.10.0 \
--hash=sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475 \
--hash=sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb
# via
# opentelemetry-sdk
# pydantic
# slippers
ulid==1.1 \
Expand All @@ -263,3 +372,88 @@ whitenoise==6.6.0 \
--hash=sha256:8998f7370973447fac1e8ef6e8ded2c5209a7b1f67c1012866dbcd09681c3251 \
--hash=sha256:b1f9db9bf67dc183484d760b99f4080185633136a273a03f6436034a41064146
# via -r requirements.prod.in
wrapt==1.16.0 \
--hash=sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc \
--hash=sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81 \
--hash=sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 \
--hash=sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e \
--hash=sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca \
--hash=sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0 \
--hash=sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb \
--hash=sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487 \
--hash=sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40 \
--hash=sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c \
--hash=sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060 \
--hash=sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202 \
--hash=sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41 \
--hash=sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9 \
--hash=sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b \
--hash=sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664 \
--hash=sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d \
--hash=sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362 \
--hash=sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00 \
--hash=sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc \
--hash=sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1 \
--hash=sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267 \
--hash=sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956 \
--hash=sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966 \
--hash=sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 \
--hash=sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228 \
--hash=sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72 \
--hash=sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d \
--hash=sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292 \
--hash=sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0 \
--hash=sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0 \
--hash=sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36 \
--hash=sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c \
--hash=sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5 \
--hash=sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f \
--hash=sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73 \
--hash=sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b \
--hash=sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2 \
--hash=sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593 \
--hash=sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39 \
--hash=sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 \
--hash=sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf \
--hash=sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf \
--hash=sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 \
--hash=sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c \
--hash=sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c \
--hash=sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f \
--hash=sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440 \
--hash=sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465 \
--hash=sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136 \
--hash=sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b \
--hash=sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8 \
--hash=sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3 \
--hash=sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8 \
--hash=sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6 \
--hash=sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e \
--hash=sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f \
--hash=sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c \
--hash=sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e \
--hash=sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8 \
--hash=sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2 \
--hash=sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020 \
--hash=sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35 \
--hash=sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d \
--hash=sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3 \
--hash=sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537 \
--hash=sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809 \
--hash=sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d \
--hash=sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a \
--hash=sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4
# via
# deprecated
# opentelemetry-instrumentation
# opentelemetry-instrumentation-dbapi
zipp==3.18.1 \
--hash=sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b \
--hash=sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715
# via importlib-metadata

# The following packages are considered to be unsafe in a requirements file:
setuptools==69.2.0 \
--hash=sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e \
--hash=sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c
# via opentelemetry-instrumentation
Empty file added services/__init__.py
Empty file.
Loading
Loading