Skip to content

Commit 598a58e

Browse files
authored
Introduce edot-bootstrap (#196)
Same opentelemetry-bootstrap but with our choices of instrumentations.
1 parent e56ee62 commit 598a58e

File tree

11 files changed

+161
-6
lines changed

11 files changed

+161
-6
lines changed

CONTRIBUTING.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ Once approved, the author of the pull request,
102102
or reviewer if the author does not have commit access,
103103
should "Squash and merge".
104104

105+
### Bumping version of EDOT instrumentations
106+
107+
When new EDOT instrumentations are released we need to update:
108+
109+
- `operator/requirements.txt`, in order to have them available in the Docker image used for the Kubernetes Operator auto-instrumentation
110+
- `elasticotel/instrumentation/bootstrap.py`, in order to make them available to `edot-bootstrap`
111+
105112
### Releasing
106113

107114
Releases tags are signed so you need to have a PGP key set up, you can follow Github documentation on [creating a key](https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key) and

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ pip install elastic-opentelemetry
3434
## Usage
3535

3636
Our distribution does not install any instrumentation package by default, instead it relies on the
37-
`opentelemetry-bootstrap` command to scan the installed packages and install the available instrumentation.
37+
`edot-bootstrap` command to scan the installed packages and install the available instrumentation, preferring EDOT variants when available.
3838
The following command will install all the instrumentations available for libraries found installed
3939
in your environment:
4040

4141
```bash
42-
opentelemetry-bootstrap --action=install
42+
edot-bootstrap --action=install
4343
```
4444

4545
It will be useful to add this command every time you need to deploy an updated version of your application,

docs/get-started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ pip install elastic-opentelemetry
4242
### Install the available instrumentation
4343

4444
EDOT Python does not install any instrumentation package by default, instead it relies on the
45-
`opentelemetry-bootstrap` command to scan the installed packages and install the available instrumentation.
45+
`edot-bootstrap` command to scan the installed packages and install the available instrumentation.
4646
The following command will install all the instrumentations available for libraries found installed
4747
in your environment:
4848

4949
```bash
50-
opentelemetry-bootstrap --action=install
50+
edot-bootstrap --action=install
5151
```
5252

5353
> [!NOTE]

docs/manual-instrumentation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ We need to make sure to have Flask and the Flask OpenTelemetry instrumentation i
5959

6060
```bash
6161
pip install flask
62-
opentelemetry-bootstrap --action=install
62+
edot-bootstrap --action=install
6363
```
6464

6565
And then we can run this application with the following command:

examples/flask/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ COPY . /app
77
RUN pip install flask elastic-opentelemetry
88

99
# Install all the instrumentations available for the installed packages
10-
RUN opentelemetry-bootstrap -a install
10+
RUN edot-bootstrap -a install
1111

1212
# default flask run port
1313
EXPOSE 5000

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ dependencies = [
3333
"opentelemetry-instrumentation-system-metrics == 0.49b2",
3434
"opentelemetry-semantic-conventions == 0.49b2",
3535
"opentelemetry-sdk == 1.28.2",
36+
"packaging",
3637
]
3738

3839
[project.optional-dependencies]
@@ -48,6 +49,9 @@ distro = "elasticotel.distro:ElasticOpenTelemetryDistro"
4849
process_runtime = "elasticotel.sdk.resources:ProcessRuntimeResourceDetector"
4950
telemetry_distro = "elasticotel.sdk.resources:TelemetryDistroResourceDetector"
5051

52+
[project.scripts]
53+
edot-bootstrap = "elasticotel.instrumentation.bootstrap:run"
54+
5155
[project.readme]
5256
file = "README.md"
5357
content-type = "text/markdown"
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
# or more contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import ast
18+
19+
# this requires python 3.11
20+
import tomllib
21+
from pathlib import Path
22+
23+
root_dir = Path(__file__).parent.parent
24+
instrumentations_repo_dir = root_dir.parent / "elastic-otel-python-instrumentations"
25+
instrumentations_dir = instrumentations_repo_dir / "instrumentation"
26+
27+
pyprojects = instrumentations_dir.glob("*/pyproject.toml")
28+
29+
instrumentations = []
30+
31+
for pyproject in pyprojects:
32+
with pyproject.open("rb") as f:
33+
data = tomllib.load(f)
34+
35+
instrumentation_name = data["project"]["name"]
36+
instruments = data["project"]["optional-dependencies"]["instruments"]
37+
38+
version = None
39+
for version_module in pyproject.parent.glob("src/opentelemetry/instrumentation/*/version.py"):
40+
with version_module.open("rb") as vf:
41+
for line in vf:
42+
if line.startswith(b"__version__"):
43+
tree = ast.parse(line)
44+
assignment_value = tree.body[0].value
45+
version = assignment_value.value
46+
break
47+
break
48+
49+
# not a fan of creating multiple entries is we require more than one library but that's the status
50+
# see https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2409
51+
for instrument in instruments:
52+
instrumentations.append(
53+
{
54+
"library": instrument,
55+
"instrumentation": f"{instrumentation_name}=={version}",
56+
}
57+
)
58+
59+
print(instrumentations)

src/elasticotel/instrumentation/__init__.py

Whitespace-only changes.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
# or more contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from opentelemetry.instrumentation.bootstrap import run as orig_run
18+
from opentelemetry.instrumentation.bootstrap_gen import (
19+
default_instrumentations as gen_default_instrumentations,
20+
)
21+
from opentelemetry.instrumentation.bootstrap_gen import (
22+
libraries as gen_libraries,
23+
)
24+
from packaging.requirements import Requirement
25+
26+
27+
# the instrumentations available in opentelemetry-bootstrap we want to skip
28+
_EXCLUDED_INSTRUMENTATIONS = {"opentelemetry-instrumentation-openai-v2"}
29+
30+
# update with:
31+
# $ python3.12 scripts/build_edot_bootstrap_instrumentations.py | ruff format -
32+
_EDOT_INSTRUMENTATIONS = [
33+
{
34+
"library": "openai >= 1.2.0",
35+
"instrumentation": "elastic-opentelemetry-instrumentation-openai==0.4.0",
36+
}
37+
]
38+
39+
40+
def _get_instrumentation_name(library_entry):
41+
instrumentation = library_entry["instrumentation"]
42+
instrumentation_name = Requirement(instrumentation)
43+
return instrumentation_name.name
44+
45+
46+
def run() -> None:
47+
"""This is a tiny wrapper around the upstream opentelemetry-boostrap implementation that let us decide which instrumentation to use"""
48+
libraries = [
49+
lib for lib in gen_libraries if _get_instrumentation_name(lib) not in _EXCLUDED_INSTRUMENTATIONS
50+
] + _EDOT_INSTRUMENTATIONS
51+
return orig_run(default_instrumentations=gen_default_instrumentations, libraries=libraries)

tests/instrumentation/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)