Skip to content

Commit ee08f84

Browse files
authored
fix: test per runtime (RD-12064) (#252)
fix: version testing per runtime (RD-12064) (#252)
1 parent 766c0d6 commit ee08f84

File tree

58 files changed

+2346
-253
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2346
-253
lines changed

.github/workflows/push-actions.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
matrix:
1212
npm-task: ['prettier:ci', 'lint', 'test:unit']
1313
steps:
14-
- uses: actions/checkout@v3
14+
- uses: actions/checkout@v4
1515
- name: Set up Node
1616
uses: actions/setup-node@v3
1717
with:
@@ -21,7 +21,7 @@ jobs:
2121
- run: npm ci
2222
- run: npm run ${{ matrix.npm-task }}
2323
- name: Upload distro as artifact
24-
uses: actions/upload-artifact@v3
24+
uses: actions/upload-artifact@v4
2525
if: ${{ matrix.npm-task == 'test:unit' }}
2626
with:
2727
name: distro-package
@@ -32,7 +32,7 @@ jobs:
3232
name: List instrumentations to test
3333
runs-on: ubuntu-latest
3434
steps:
35-
- uses: actions/checkout@v3
35+
- uses: actions/checkout@v4
3636
- id: list_instrumentations
3737
run: |
3838
instrumentations_as_json_list=$(ls -1 test/instrumentations | jq --raw-input --slurp 'split("\n") | map(select(. != ""))' | jq -r tostring)
@@ -57,7 +57,7 @@ jobs:
5757
# see https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners for
5858
# runner specs, default swap space is only 2GB
5959
swap-size-gb: 10
60-
- uses: actions/checkout@v3
60+
- uses: actions/checkout@v4
6161
- name: Set up Node
6262
uses: actions/setup-node@v3
6363
with:
@@ -83,7 +83,7 @@ jobs:
8383
node-version: ${{ matrix.node_cimg_tag }}
8484
architecture: x64
8585
- name: Download distro
86-
uses: actions/download-artifact@v3
86+
uses: actions/download-artifact@v4
8787
with:
8888
name: distro-package
8989
- run: npm i ./distro.tgz

.github/workflows/version-testing.yml

+14-9
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ jobs:
1010
matrix:
1111
# NOTE: if these are updated, don't forget to
1212
# update the download-artifacts versions as well
13-
node_cimg_tag: [ 14, 16, 18 ]
13+
node_cimg_tag: [ 14, 16, 18, 20 ]
1414
name: test-untested-versions
1515
steps:
16-
- uses: actions/checkout@v3
16+
- uses: actions/checkout@v4
1717
- name: Set up Node
1818
uses: actions/setup-node@v3
1919
with:
@@ -40,7 +40,7 @@ jobs:
4040
cp "$path" versions_artifact;
4141
fi
4242
done
43-
- uses: actions/upload-artifact@v2
43+
- uses: actions/upload-artifact@v4
4444
with:
4545
name: ${{ matrix.node_cimg_tag }}
4646
path: versions_artifact
@@ -50,27 +50,32 @@ jobs:
5050
name: create-pr-for-new-versions
5151
needs: test-untested-versions
5252
steps:
53-
- uses: actions/checkout@v3
53+
- uses: actions/checkout@v4
5454
- name: Set up Python
5555
uses: actions/setup-python@v4
5656
with:
5757
python-version: 3.7
5858
- run: mkdir versions_artifacts
59-
- uses: actions/download-artifact@v2
59+
- uses: actions/download-artifact@v4
6060
continue-on-error: true # when there aren't changes the artifact won't be uploaded and this step will fail
6161
with:
6262
name: 14
6363
path: versions_artifacts/14
64-
- uses: actions/download-artifact@v2
64+
- uses: actions/download-artifact@v4
6565
continue-on-error: true
6666
with:
6767
name: 16
6868
path: versions_artifacts/16
69-
- uses: actions/download-artifact@v2
69+
- uses: actions/download-artifact@v4
7070
continue-on-error: true
7171
with:
7272
name: 18
7373
path: versions_artifacts/18
74+
- uses: actions/download-artifact@v4
75+
continue-on-error: true
76+
with:
77+
name: 20
78+
path: versions_artifacts/20
7479
- run: python3 -m pip install -r ./requirements-ci.txt
7580
# TODO replace this with a node.js script
7681
- run: PYTHONPATH=${PYTHONPATH}:$(pwd)/scripts python3 -m gather_version_artifacts
@@ -95,13 +100,13 @@ jobs:
95100
body: ${{ env.new_versions }}
96101
base: main
97102
labels: version-testing, automerge
98-
reviewers: GuyMoses,saartochner,shanishiri
103+
reviewers: GuyMoses,nadav3396,shanishiri
99104

100105
delete-old-version-testing-branches:
101106
runs-on: ubuntu-latest
102107
name: delete-old-version-testing-branches
103108
needs: create-pr-for-new-versions
104109
steps:
105-
- uses: actions/checkout@v3
110+
- uses: actions/checkout@v4
106111
- run: | # remove all the version testing branches that aren't from today
107112
./scripts/delete_old_version_testing_branches.sh

README.md

+19-14
Original file line numberDiff line numberDiff line change
@@ -276,22 +276,26 @@ trace.getActiveSpan()?.addEvent('<error-message>', {'lumigo.type': '<error-type>
276276
277277
## Supported packages
278278
279-
| Instrumentation | Package | Supported Versions |
280-
| --- | --- | --- |
281-
| grpc-js | [@grpc](https://www.npmjs.com/package/@grpc) | 1.8.0~1.8.20 |
282-
| amqplib | [amqplib](https://www.npmjs.com/package/amqplib) | 0.9.0~0.10.3 |
283-
| express | [express](https://www.npmjs.com/package/express) | 4.9.0~4.18.2 |
284-
| fastify | [fastify](https://www.npmjs.com/package/fastify) | 3.29.0~4.24.3 |
285-
| ioredis | [ioredis](https://www.npmjs.com/package/ioredis) | 4.0.0~4.28.5 |
286-
| | | 5.0.0~5.3.2 |
287-
| kafkajs | [kafkajs](https://www.npmjs.com/package/kafkajs) | 2.0.0~2.2.4 |
288-
| mongodb | [mongodb](https://www.npmjs.com/package/mongodb) | 3.6.6~3.7.3 |
289-
| | | 4.0.0~4.16.0 |
290-
| prisma | [prisma](https://www.npmjs.com/package/prisma) | 4.2.0~4.13.0 |
291-
| redis | [redis](https://www.npmjs.com/package/redis) | 4.0.0~4.6.8 |
279+
| Instrumentation | Package | Supported Versions | | | |
280+
| --- | --- | :---: | :---: | :---: | :---: |
281+
| | | 14 | 16 | 18 | 20 |
282+
| grpc-js | [grpc-js](https://www.npmjs.com/package/grpc-js) | 1.8.0~1.8.20|1.8.0~1.8.20|1.8.0~1.8.20|1.8.0~1.8.20|
283+
| amqplib | [amqplib](https://www.npmjs.com/package/amqplib) | 0.9.0~0.10.3|0.9.0~0.10.3|0.9.0~0.10.3|0.9.0~0.10.3|
284+
| express | [express](https://www.npmjs.com/package/express) | 4.9.0~4.18.2|4.9.0~4.18.2|4.9.0~4.18.2|4.9.0~4.18.2|
285+
| fastify | [fastify](https://www.npmjs.com/package/fastify) | 3.3.0~3.29.5|3.3.0~3.29.5|3.3.0~3.29.5|3.3.0~3.29.5|
286+
| | | 4.0.0| 4.0.0| 4.0.0| 4.0.0|
287+
| | | 4.0.1~4.26.1| 4.0.1~4.26.1| 4.0.1~4.26.1| 4.0.1~4.26.1|
288+
| ioredis | [ioredis](https://www.npmjs.com/package/ioredis) | 4.0.0~4.28.5|4.0.0~4.28.5|4.0.0~4.28.5|4.0.0~4.28.5|
289+
| | | 5.0.0~5.3.2| 5.0.0~5.3.2| 5.0.0~5.3.2| 5.0.0~5.3.2|
290+
| kafkajs | [kafkajs](https://www.npmjs.com/package/kafkajs) | 2.0.0~2.2.4|2.0.0~2.2.4|2.0.0~2.2.4|2.0.0~2.2.4|
291+
| mongodb | [mongodb](https://www.npmjs.com/package/mongodb) | 4.17.0|3.6.6~3.7.3|3.6.6~3.7.3|3.6.6~3.7.3|
292+
| | | 6.3.0| 4.0.0~4.17.2| 4.0.0~4.17.2| 4.0.0~4.17.2|
293+
| | | | 5.0.0~5.9.2| 5.0.0~5.9.2| 5.0.0~5.9.2|
294+
| prisma | [prisma](https://www.npmjs.com/package/prisma) | 4.2.0~4.13.0|4.2.0~4.13.0|4.2.0~4.13.0|4.2.0~4.13.0|
295+
| redis | [redis](https://www.npmjs.com/package/redis) | 4.0.0~4.6.8|4.0.0~4.6.13|4.0.0~4.6.13|4.0.0~4.6.13|
296+
| | | 4.6.10~4.6.13| | | |
292297
293298
### Activating your Prisma client's instrumentation
294-
295299
If you're using [Prisma](https://www.npmjs.com/package/prisma) and you would like it instrumented, the *only* thing you will need to do (aside from [activating the tracer](#tracer-activation), of course) is ensure that your schema file's `generator client` has the `tracing` preview feature enabled prior to generating the client itself.
296300
297301
```prisma
@@ -303,6 +307,7 @@ generator client {
303307
304308
**NOTE**: There have been reports of a possible bug that interferes with tracing when multiple Prisma clients have been instantiated, see [Prisma issue #20779](https://github.com/prisma/prisma/issues/20779).
305309
310+
306311
## Automated dependency reporting
307312
308313
To provide better support and better data-driven product decisions with respect to which packages to support next, the Lumigo OpenTelemetry Distro for JS will report to Lumigo SaaS on startup the packages and their versions used in this application, together with the OpenTelemetry resource data to enable analytics in terms of which platforms use which dependencies.

jest.instrumentations.setup.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const {
77
loadPackageVersionsFromBackup,
88
} = require('./scripts/tested-versions-file-utils');
99

10+
const runtimeVersion = parseInt(process.version.slice(1).split('.')[0]);
1011
const oldEnv = Object.assign({}, process.env);
1112
beforeEach(() => {
1213
process.env = { ...oldEnv };
@@ -34,7 +35,7 @@ afterAll(() => {
3435
versions_keys.forEach((pkg) => {
3536
// updated supported versions file
3637
const testedVersionFolder = `./src/instrumentations/${pkg}/tested_versions`;
37-
const testVersionsFile = `${testedVersionFolder}/${pkg}`;
38+
const testVersionsFile = `${testedVersionFolder}/${runtimeVersion}/${pkg}`;
3839
fs.mkdirSync(testedVersionFolder, { recursive: true });
3940
const versionStrings = versions[pkg].unsupported
4041
.map((v) => `!${v}`)

scripts/describe_supported_versions_diff.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ git diff --name-only -- "${ROOT_DIR}/src/" | \
1111
sort | \
1212
while read -r modified_version_file; do \
1313
package_name=$(basename "${modified_version_file}")
14+
runtime_path=$(dirname "${modified_version_file}")
15+
runtime=$(basename "${runtime_path}")
1416
new_versions=$(git diff HEAD --no-ext-diff --unified=0 --exit-code -a --no-prefix -- ${modified_version_file} | egrep "^\+" | tail -n +2 | sed 's/\+\(.*\)/\1/' | tr '\n' ' ')
15-
echo "${package_name}: ${new_versions}"
17+
echo "${package_name} (${runtime}): ${new_versions}"
1618
done

scripts/gather_version_artifacts.py

+43-78
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,67 @@
1+
# call this script from the project root with python3 -m scripts.gather_version_artifacts
2+
13
import os
24
from glob import glob
3-
from typing import List, Dict, Tuple
5+
from typing import List
46

57
from tested_versions_utils import TestedVersions
68

7-
ARTIFACT_DIR_NAME = "versions_artifacts"
8-
9+
ARTIFACTS_PATH = "versions_artifacts"
10+
INSTRUMENTATIONS_PATH = "src/instrumentations/"
911

1012
# Before this script runs, the job downloads the artifacts into files with the following example structure:
1113
#
1214
# versions_artifacts/
13-
# 12/
14-
# express: (next lines are the data inside the file)
15-
# 4.17.2
16-
# !4.17.3
17-
# mongoose:
18-
# 6.4.4
19-
# 3.9.7
20-
# 14/
21-
# express:
22-
# 4.17.2
23-
# !4.17.3
24-
# mongoose:
25-
# 3.9.7
26-
# 6.4.4
15+
# 3.7/
16+
# boto3: (next lines are the data inside the file)
17+
# 1.0.0
18+
# !2.0.0
19+
# 3.10/
20+
# fastapi:
21+
# 5.1.0
22+
# 5.2.0
2723
#
2824
# Each file contains the original supported versions and the results from the tests in the previous job.
2925

26+
3027
def main() -> None:
31-
runtime_to_files = {
32-
python_runtime: sorted(
33-
os.listdir(os.path.join(ARTIFACT_DIR_NAME, python_runtime))
34-
)
35-
for python_runtime in os.listdir(ARTIFACT_DIR_NAME)
28+
files_by_runtime = {
29+
python_runtime: sorted(os.listdir(os.path.join(ARTIFACTS_PATH, python_runtime)))
30+
for python_runtime in os.listdir(ARTIFACTS_PATH)
3631
}
37-
print("runtime_to_files:", runtime_to_files)
38-
if not any(runtime_to_files.values()):
32+
print(f"new results detected: {files_by_runtime}")
33+
34+
if not any(files_by_runtime.values()):
3935
print("No files were found so nothing to update, returning")
4036
return
41-
files_names = list(runtime_to_files.values())[0]
42-
if any([files != files_names for files in runtime_to_files.values()]):
43-
raise Exception("Got different files from different runtimes")
44-
origin_tested_files = glob(
45-
"src/instrumentations/*/tested_versions/*"
46-
)
47-
for instrumentation_name in files_names:
48-
handle_dependency(
49-
instrumentation_name, origin_tested_files, tuple(runtime_to_files)
50-
)
5137

38+
for runtime, dependencies in files_by_runtime.items():
39+
update_dependencies(dependencies, runtime)
5240

53-
def handle_dependency(
54-
instrumentation_name: str, origin_tested_files: List[str], runtimes: Tuple[str, ...]
55-
) -> None:
56-
print("working on:", instrumentation_name)
57-
origin_path = next(
58-
path
59-
for path in origin_tested_files
60-
if path.endswith(f"tested_versions/{instrumentation_name}")
61-
)
6241

63-
runtime_to_tested_versions = calculate_runtime_to_tested_versions_dict(
64-
instrumentation_name, runtimes
65-
)
66-
67-
for version in list(runtime_to_tested_versions.values())[0].all_versions:
68-
supported = all(
69-
[
70-
# A version is supported only if it works in all runtimes
71-
(version in runtime_to_tested_versions[runtime].supported_versions)
72-
for runtime in runtimes
73-
]
42+
def update_dependencies(dependencies: List[str], runtime: str) -> None:
43+
for instrumentation_name in dependencies:
44+
print(
45+
f"processing {instrumentation_name} for {runtime}...",
7446
)
75-
76-
TestedVersions.add_version_to_file(origin_path, version, supported)
77-
78-
79-
def calculate_runtime_to_tested_versions_dict(
80-
instrumentation_name: str, runtimes: Tuple[str, ...]
81-
) -> Dict[str, TestedVersions]:
82-
runtime_to_tested_versions = {
83-
runtime: TestedVersions.from_file(
84-
os.path.join(ARTIFACT_DIR_NAME, runtime, instrumentation_name)
47+
# find all the relevant files in the instrumentations path
48+
# NOTE: this handles the case where the instrumentation's tested versions are
49+
# not in its own path, eg. uvicorn
50+
original_tested_versions_files = glob(
51+
f"{INSTRUMENTATIONS_PATH}/*/tested_versions/{runtime}/*"
8552
)
86-
for runtime in runtimes
87-
}
88-
print("runtime_to_tested_versions:", runtime_to_tested_versions)
89-
90-
# Sanity check that we tested the same versions in all runtimes
91-
all_versions = set(list(runtime_to_tested_versions.values())[0].all_versions)
92-
if any(
93-
[
94-
set(tested_versions.all_versions) != all_versions
95-
for tested_versions in runtime_to_tested_versions.values()
96-
]
97-
):
98-
raise Exception("Got different versions from different runtimes")
99-
return runtime_to_tested_versions
53+
for original_tested_versions_file in original_tested_versions_files:
54+
if original_tested_versions_file.endswith(
55+
f"tested_versions/{runtime}/{instrumentation_name}"
56+
):
57+
tested_versions = TestedVersions.from_file(
58+
os.path.join(ARTIFACTS_PATH, runtime, instrumentation_name)
59+
)
60+
for version in tested_versions.all_versions:
61+
supported = version in tested_versions.supported_versions
62+
TestedVersions.add_version_to_file(
63+
original_tested_versions_file, version, supported
64+
)
10065

10166

10267
if __name__ == "__main__":

scripts/init_tested_versions.sh

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
3+
PACKAGE_NAME="$1"
4+
SUPPORTED_VERSIONS=(14 16 18 20)
5+
6+
if [ -z "$PACKAGE_NAME" ]; then
7+
echo "Usage: $0 <PACKAGE_NAME>"
8+
exit 1
9+
fi
10+
11+
base_folder="src/instrumentations/${PACKAGE_NAME}/tested_versions"
12+
test_folder="src/test/integration/${PACKAGE_NAME}"
13+
14+
echo "Creating tested versions folders under ${base_folder}..."
15+
for version in "${SUPPORTED_VERSIONS[@]}"; do
16+
echo "Creating ${version} folder..."
17+
version_folder="${base_folder}/${version}"
18+
mkdir -p "$version_folder"
19+
touch "${version_folder}/${PACKAGE_NAME}"
20+
done
21+
22+
echo ""
23+
echo "Creating tested versions symlink in ${test_folder}..."
24+
mkdir -p "$test_folder"
25+
pushd "$test_folder"
26+
if [ -e tested_versions ]; then
27+
echo "Removing old tested_versions symlink..."
28+
rm tested_versions
29+
fi
30+
echo "linking from ${test_folder} to ${base_folder}..."
31+
ln -s ../../../../${base_folder} tested_versions
32+
popd
33+
34+
echo ""
35+
echo "Done"

0 commit comments

Comments
 (0)