Skip to content

Commit 20d6600

Browse files
committed
Introduce edot-bootstrap
Same opentelemetry-bootstrap but with our choices of instrumentations.
1 parent 423016a commit 20d6600

File tree

10 files changed

+160
-5
lines changed

10 files changed

+160
-5
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
@@ -33,12 +33,12 @@ pip install elastic-opentelemetry
3333
## Usage
3434

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

4040
```bash
41-
opentelemetry-bootstrap --action=install
41+
edot-bootstrap --action=install
4242
```
4343

4444
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]

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.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 sys
18+
19+
from opentelemetry.instrumentation import (
20+
bootstrap as otel_bootstrap,
21+
)
22+
23+
from elasticotel.instrumentation import bootstrap
24+
25+
26+
def test_overriden_instrumentations(monkeypatch, capfd):
27+
monkeypatch.setattr(sys, "argv", ["edot-bootstrap", "-a", "requirements"])
28+
29+
monkeypatch.setattr(otel_bootstrap, "_is_installed", lambda lib: True)
30+
31+
bootstrap.run()
32+
captured = capfd.readouterr()
33+
assert "opentelemetry-instrumentation-openai-v2" not in captured.out
34+
assert "elastic-opentelemetry-instrumentation-openai" in captured.out

0 commit comments

Comments
 (0)