Simplify bootstrap and generate code (#514)

- We now automatically generate bootstrap_gen.py file from the list of instrumentations present in the source tree.
- Bootstrap command now uses consumes this auto-generated list instead of keeping it's own local copy.
- We no longer uninstall packages before installing them as instrumentation package no longer specify libraries as dependencies so the edge cases are no longer there.
- We no longer try to install an incompatible version or force upgrade/downgrade an installed version. This used to leave systems in broken states which should happen no more.
This commit is contained in:
Owais Lone
2021-06-01 21:49:09 +05:30
committed by GitHub
parent af7ab072cc
commit 5d1f3201af
47 changed files with 1330 additions and 215 deletions

View File

@ -45,7 +45,7 @@ jobs:
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: .tox path: .tox
key: v2-build-tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} key: v2-build-tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'gen-requirements.txt', 'dev-requirements.txt') }}
- name: run tox - name: run tox
run: tox -f ${{ matrix.python-version }}-${{ matrix.package }} -- --benchmark-json=${{ env.RUN_MATRIX_COMBINATION }}-benchmark.json run: tox -f ${{ matrix.python-version }}-${{ matrix.package }} -- --benchmark-json=${{ env.RUN_MATRIX_COMBINATION }}-benchmark.json
- name: Find and merge benchmarks - name: Find and merge benchmarks
@ -76,7 +76,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
tox-environment: [ "docker-tests", "lint", "docs" ] tox-environment: [ "docker-tests", "lint", "docs", "generate" ]
name: ${{ matrix.tox-environment }} name: ${{ matrix.tox-environment }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -99,6 +99,9 @@ jobs:
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: .tox path: .tox
key: v2-misc-tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }} key: v2-misc-tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'gen-requirements.txt', 'docs-requirements.txt') }}
- name: run tox - name: run tox
run: tox -e ${{ matrix.tox-environment }} run: tox -e ${{ matrix.tox-environment }}
- name: Ensure generated code is up to date
if: matrix.tox-environment == 'generate'
run: git diff --exit-code || (echo 'Generated code is out of date, please run "tox -e generate" and commit the changes in this PR.' && exit 1)

1
.gitignore vendored
View File

@ -8,6 +8,7 @@
*.egg *.egg
*.egg-info *.egg-info
dist dist
dist-info
build build
eggs eggs
parts parts

View File

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.2.0-0.21b0...HEAD) ## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.2.0-0.21b0...HEAD)
### Changed ### Changed
- `opentelemetry-bootstrap` not longer forcibly removes and re-installs libraries and their instrumentations.
This means running bootstrap will not auto-upgrade existing dependencies and as a result not cause dependency
conflicts.
([#514](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/514))
- `opentelemetry-instrumentation-asgi` Set the response status code on the server span - `opentelemetry-instrumentation-asgi` Set the response status code on the server span
([#478](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/478)) ([#478](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/478))
- `opentelemetry-instrumentation-tornado` Fixed cases where description was used with non- - `opentelemetry-instrumentation-tornado` Fixed cases where description was used with non-

View File

@ -170,7 +170,7 @@ Below is a checklist of things to be mindful of when implementing a new instrume
- Extends from [BaseInstrumentor](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py#L26) - Extends from [BaseInstrumentor](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py#L26)
- Supports auto-instrumentation - Supports auto-instrumentation
- Add an entry point (ex. https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/instrumentation/opentelemetry-instrumentation-requests/setup.cfg#L56) - Add an entry point (ex. https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/instrumentation/opentelemetry-instrumentation-requests/setup.cfg#L56)
- Add instrumentation package to `bootstrap.py` (https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py#L37) - Run `python scripts/setup.py` followed by `python scripts/generate_instrumentation_bootstrap.py` after adding a new instrumentation package.
- Functionality that is common amongst other instrumentation and can be abstracted [here](https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation) - Functionality that is common amongst other instrumentation and can be abstracted [here](https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation)
- Request/response [hooks](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/408) for http instrumentations - Request/response [hooks](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/408) for http instrumentations
- `suppress_instrumentation` functionality - `suppress_instrumentation` functionality

6
gen-requirements.txt Normal file
View File

@ -0,0 +1,6 @@
-c dev-requirements.txt
astor==0.8.1
jinja2~=2.7
isort
black

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -66,6 +68,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -17,6 +17,8 @@
# RUN `python scripts/generate_setup.py` TO REGENERATE. # RUN `python scripts/generate_setup.py` TO REGENERATE.
import distutils.cmd
import json
import os import os
from configparser import ConfigParser from configparser import ConfigParser
@ -56,6 +58,32 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places",
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
"name": config["metadata"]["name"],
"version": PACKAGE_INFO["__version__"],
"instruments": PACKAGE_INFO["_instruments"],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
version=PACKAGE_INFO["__version__"], extras_require=extras_require cmdclass={"meta": JSONMetadataCommand},
version=PACKAGE_INFO["__version__"],
extras_require=extras_require,
) )

View File

@ -15,118 +15,19 @@
# limitations under the License. # limitations under the License.
import argparse import argparse
import pkgutil import logging
import subprocess import subprocess
import sys import sys
from logging import getLogger
import pkg_resources
from opentelemetry.instrumentation.bootstrap_gen import (
default_instrumentations,
libraries,
)
from opentelemetry.instrumentation.version import __version__ as version from opentelemetry.instrumentation.version import __version__ as version
logger = getLogger(__file__) logger = logging.getLogger(__file__)
# A mapping of "target library" to "desired instrumentor path/versioned package
# name". Used as part of the `opentelemetry-bootstrap` command which looks at
# libraries used by the application that is to be instrumented, and handles
# automatically installing the appropriate instrumentations for that app.
# This helps for those who prefer to turn on as much instrumentation as
# possible, and don't want to go through the manual process of combing through
# the libraries their application uses to figure which one can be
# instrumented.
# NOTE: system-metrics is not to be included.
def all_instrumentations():
pkg_instrumentation_map = {
"aiohttp-client": "opentelemetry-instrumentation-aiohttp-client",
"aiopg": "opentelemetry-instrumentation-aiopg",
"asyncpg": "opentelemetry-instrumentation-asyncpg",
"boto": "opentelemetry-instrumentation-boto",
"botocore": "opentelemetry-instrumentation-botocore",
"celery": "opentelemetry-instrumentation-celery",
"dbapi": "opentelemetry-instrumentation-dbapi",
"django": "opentelemetry-instrumentation-django",
"elasticsearch": "opentelemetry-instrumentation-elasticsearch",
"falcon": "opentelemetry-instrumentation-falcon",
"fastapi": "opentelemetry-instrumentation-fastapi",
"flask": "opentelemetry-instrumentation-flask",
"grpc": "opentelemetry-instrumentation-grpc",
"jinja2": "opentelemetry-instrumentation-jinja2",
"mysql": "opentelemetry-instrumentation-mysql",
"psycopg2": "opentelemetry-instrumentation-psycopg2",
"pymemcache": "opentelemetry-instrumentation-pymemcache",
"pymongo": "opentelemetry-instrumentation-pymongo",
"pymysql": "opentelemetry-instrumentation-pymysql",
"pyramid": "opentelemetry-instrumentation-pyramid",
"redis": "opentelemetry-instrumentation-redis",
"requests": "opentelemetry-instrumentation-requests",
"sklearn": "opentelemetry-instrumentation-sklearn",
"sqlalchemy": "opentelemetry-instrumentation-sqlalchemy",
"sqlite3": "opentelemetry-instrumentation-sqlite3",
"starlette": "opentelemetry-instrumentation-starlette",
"tornado": "opentelemetry-instrumentation-tornado",
"urllib": "opentelemetry-instrumentation-urllib",
}
for pkg, instrumentation in pkg_instrumentation_map.items():
pkg_instrumentation_map[pkg] = "{0}=={1}".format(
instrumentation, version
)
return pkg_instrumentation_map
instrumentations = all_instrumentations()
# relevant instrumentors and tracers to uninstall and check for conflicts for target libraries
libraries = {
"aiohttp-client": ("opentelemetry-instrumentation-aiohttp-client",),
"aiopg": ("opentelemetry-instrumentation-aiopg",),
"asyncpg": ("opentelemetry-instrumentation-asyncpg",),
"boto": ("opentelemetry-instrumentation-boto",),
"botocore": ("opentelemetry-instrumentation-botocore",),
"celery": ("opentelemetry-instrumentation-celery",),
"dbapi": ("opentelemetry-instrumentation-dbapi",),
"django": ("opentelemetry-instrumentation-django",),
"elasticsearch": ("opentelemetry-instrumentation-elasticsearch",),
"falcon": ("opentelemetry-instrumentation-falcon",),
"fastapi": ("opentelemetry-instrumentation-fastapi",),
"flask": ("opentelemetry-instrumentation-flask",),
"grpc": ("opentelemetry-instrumentation-grpc",),
"jinja2": ("opentelemetry-instrumentation-jinja2",),
"mysql": ("opentelemetry-instrumentation-mysql",),
"psycopg2": ("opentelemetry-instrumentation-psycopg2",),
"pymemcache": ("opentelemetry-instrumentation-pymemcache",),
"pymongo": ("opentelemetry-instrumentation-pymongo",),
"pymysql": ("opentelemetry-instrumentation-pymysql",),
"pyramid": ("opentelemetry-instrumentation-pyramid",),
"redis": ("opentelemetry-instrumentation-redis",),
"requests": ("opentelemetry-instrumentation-requests",),
"sklearn": ("opentelemetry-instrumentation-sklearn",),
"sqlalchemy": ("opentelemetry-instrumentation-sqlalchemy",),
"sqlite3": ("opentelemetry-instrumentation-sqlite3",),
"starlette": ("opentelemetry-instrumentation-starlette",),
"tornado": ("opentelemetry-instrumentation-tornado",),
"urllib": ("opentelemetry-instrumentation-urllib",),
}
def _install_package(library, instrumentation):
"""
Ensures that desired version is installed w/o upgrading its dependencies
by uninstalling where necessary (if `target` is not provided).
OpenTelemetry auto-instrumentation packages often have traced libraries
as instrumentation dependency (e.g. flask for
opentelemetry-instrumentation-flask), so using -I on library could cause
likely undesired Flask upgrade.Using --no-dependencies alone would leave
potential for nonfunctional installations.
"""
pip_list = _sys_pip_freeze()
for package in libraries[library]:
if "{}==".format(package).lower() in pip_list:
logger.info(
"Existing %s installation detected. Uninstalling.", package
)
_sys_pip_uninstall(package)
_sys_pip_install(instrumentation)
def _syscall(func): def _syscall(func):
@ -148,15 +49,6 @@ def _syscall(func):
return wrapper return wrapper
@_syscall
def _sys_pip_freeze():
return (
subprocess.check_output([sys.executable, "-m", "pip", "freeze"])
.decode()
.lower()
)
@_syscall @_syscall
def _sys_pip_install(package): def _sys_pip_install(package):
# explicit upgrade strategy to override potential pip config # explicit upgrade strategy to override potential pip config
@ -174,13 +66,6 @@ def _sys_pip_install(package):
) )
@_syscall
def _sys_pip_uninstall(package):
subprocess.check_call(
[sys.executable, "-m", "pip", "uninstall", "-y", package]
)
def _pip_check(): def _pip_check():
"""Ensures none of the instrumentations have dependency conflicts. """Ensures none of the instrumentations have dependency conflicts.
Clean check reported as: Clean check reported as:
@ -203,22 +88,44 @@ def _pip_check():
) )
def _is_installed(library): def _is_installed(req):
return library in sys.modules or pkgutil.find_loader(library) is not None if req in sys.modules:
return True
try:
pkg_resources.get_distribution(req)
except pkg_resources.DistributionNotFound:
return False
except pkg_resources.VersionConflict as exc:
logger.warning(
"instrumentation for package %s is available but version %s is installed. Skipping.",
exc.req,
exc.dist.as_requirement(), # pylint: disable=no-member
)
return False
return True
def _find_installed_libraries(): def _find_installed_libraries():
return {k: v for k, v in instrumentations.items() if _is_installed(k)} libs = default_instrumentations[:]
libs.extend(
[
v["instrumentation"]
for _, v in libraries.items()
if _is_installed(v["library"])
]
)
return libs
def _run_requirements(packages): def _run_requirements():
print("\n".join(packages.values()), end="") logger.setLevel(logging.ERROR)
print("\n".join(_find_installed_libraries()), end="")
def _run_install(packages): def _run_install():
for pkg, inst in packages.items(): for lib in _find_installed_libraries():
_install_package(pkg, inst) _sys_pip_install(lib)
_pip_check() _pip_check()
@ -250,4 +157,4 @@ def run() -> None:
action_install: _run_install, action_install: _run_install,
action_requirements: _run_requirements, action_requirements: _run_requirements,
}[args.action] }[args.action]
cmd(_find_installed_libraries()) cmd()

View File

@ -0,0 +1,134 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# DO NOT EDIT. THIS FILE WAS AUTOGENERATED FROM INSTRUMENTATION PACKAGES.
# RUN `python scripts/generate_instrumentation_bootstrap.py` TO REGENERATE.
libraries = {
"aiohttp": {
"library": "aiohttp ~= 3.0",
"instrumentation": "opentelemetry-instrumentation-aiohttp-client==0.22.dev0",
},
"aiopg": {
"library": "aiopg >= 0.13.0",
"instrumentation": "opentelemetry-instrumentation-aiopg==0.22.dev0",
},
"asgiref": {
"library": "asgiref ~= 3.0",
"instrumentation": "opentelemetry-instrumentation-asgi==0.22.dev0",
},
"asyncpg": {
"library": "asyncpg >= 0.12.0",
"instrumentation": "opentelemetry-instrumentation-asyncpg==0.22.dev0",
},
"boto": {
"library": "boto~=2.0",
"instrumentation": "opentelemetry-instrumentation-boto==0.22.dev0",
},
"botocore": {
"library": "botocore ~= 1.0",
"instrumentation": "opentelemetry-instrumentation-botocore==0.22.dev0",
},
"celery": {
"library": "celery >= 4.0, < 6.0",
"instrumentation": "opentelemetry-instrumentation-celery==0.22.dev0",
},
"django": {
"library": "django >= 1.10",
"instrumentation": "opentelemetry-instrumentation-django==0.22.dev0",
},
"elasticsearch": {
"library": "elasticsearch >= 2.0",
"instrumentation": "opentelemetry-instrumentation-elasticsearch==0.22.dev0",
},
"falcon": {
"library": "falcon ~= 2.0",
"instrumentation": "opentelemetry-instrumentation-falcon==0.22.dev0",
},
"fastapi": {
"library": "fastapi ~= 0.58.1",
"instrumentation": "opentelemetry-instrumentation-fastapi==0.22.dev0",
},
"flask": {
"library": "flask ~= 1.0",
"instrumentation": "opentelemetry-instrumentation-flask==0.22.dev0",
},
"grpcio": {
"library": "grpcio ~= 1.27",
"instrumentation": "opentelemetry-instrumentation-grpc==0.22.dev0",
},
"jinja2": {
"library": "jinja2~=2.7",
"instrumentation": "opentelemetry-instrumentation-jinja2==0.22.dev0",
},
"mysql-connector-python": {
"library": "mysql-connector-python ~= 8.0",
"instrumentation": "opentelemetry-instrumentation-mysql==0.22.dev0",
},
"psycopg2-binary": {
"library": "psycopg2-binary >= 2.7.3.1",
"instrumentation": "opentelemetry-instrumentation-psycopg2==0.22.dev0",
},
"pymemcache": {
"library": "pymemcache ~= 1.3",
"instrumentation": "opentelemetry-instrumentation-pymemcache==0.22.dev0",
},
"pymongo": {
"library": "pymongo ~= 3.1",
"instrumentation": "opentelemetry-instrumentation-pymongo==0.22.dev0",
},
"PyMySQL": {
"library": "PyMySQL ~= 0.10.1",
"instrumentation": "opentelemetry-instrumentation-pymysql==0.22.dev0",
},
"pyramid": {
"library": "pyramid >= 1.7",
"instrumentation": "opentelemetry-instrumentation-pyramid==0.22.dev0",
},
"redis": {
"library": "redis >= 2.6",
"instrumentation": "opentelemetry-instrumentation-redis==0.22.dev0",
},
"requests": {
"library": "requests ~= 2.0",
"instrumentation": "opentelemetry-instrumentation-requests==0.22.dev0",
},
"scikit-learn": {
"library": "scikit-learn ~= 0.24.0",
"instrumentation": "opentelemetry-instrumentation-sklearn==0.22.dev0",
},
"sqlalchemy": {
"library": "sqlalchemy",
"instrumentation": "opentelemetry-instrumentation-sqlalchemy==0.22.dev0",
},
"starlette": {
"library": "starlette ~= 0.13.0",
"instrumentation": "opentelemetry-instrumentation-starlette==0.22.dev0",
},
"tornado": {
"library": "tornado >= 6.0",
"instrumentation": "opentelemetry-instrumentation-tornado==0.22.dev0",
},
"urllib3": {
"library": "urllib3 >= 1.0.0, < 2.0.0",
"instrumentation": "opentelemetry-instrumentation-urllib3==0.22.dev0",
},
}
default_instrumentations = [
"opentelemetry-instrumentation-dbapi==0.22.dev0",
"opentelemetry-instrumentation-logging==0.22.dev0",
"opentelemetry-instrumentation-sqlite3==0.22.dev0",
"opentelemetry-instrumentation-urllib==0.22.dev0",
"opentelemetry-instrumentation-wsgi==0.22.dev0",
]

View File

@ -13,18 +13,17 @@
# limitations under the License. # limitations under the License.
# type: ignore # type: ignore
from functools import reduce
from io import StringIO from io import StringIO
from random import sample from random import sample
from unittest import TestCase from unittest import TestCase
from unittest.mock import call, patch from unittest.mock import call, patch
from opentelemetry.instrumentation import bootstrap from opentelemetry.instrumentation import bootstrap
from opentelemetry.instrumentation.bootstrap_gen import libraries
def sample_packages(packages, rate): def sample_packages(packages, rate):
sampled = sample(list(packages), int(len(packages) * rate),) return sample(list(packages), int(len(packages) * rate),)
return {k: v for k, v in packages.items() if k in sampled}
class TestBootstrap(TestCase): class TestBootstrap(TestCase):
@ -34,9 +33,8 @@ class TestBootstrap(TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
# select random 60% of instrumentations
cls.installed_libraries = sample_packages( cls.installed_libraries = sample_packages(
bootstrap.instrumentations, 0.6 [lib["instrumentation"] for lib in libraries.values()], 0.6
) )
# treat 50% of sampled packages as pre-installed # treat 50% of sampled packages as pre-installed
@ -49,39 +47,21 @@ class TestBootstrap(TestCase):
return_value=cls.installed_libraries, return_value=cls.installed_libraries,
) )
pip_freeze_output = []
for inst in cls.installed_instrumentations.values():
inst = inst.replace(">=", "==")
if "==" not in inst:
inst = "{}==x.y".format(inst)
pip_freeze_output.append(inst)
cls.pip_freeze_patcher = patch(
"opentelemetry.instrumentation.bootstrap._sys_pip_freeze",
return_value="\n".join(pip_freeze_output),
)
cls.pip_install_patcher = patch( cls.pip_install_patcher = patch(
"opentelemetry.instrumentation.bootstrap._sys_pip_install", "opentelemetry.instrumentation.bootstrap._sys_pip_install",
) )
cls.pip_uninstall_patcher = patch(
"opentelemetry.instrumentation.bootstrap._sys_pip_uninstall",
)
cls.pip_check_patcher = patch( cls.pip_check_patcher = patch(
"opentelemetry.instrumentation.bootstrap._pip_check", "opentelemetry.instrumentation.bootstrap._pip_check",
) )
cls.pkg_patcher.start() cls.pkg_patcher.start()
cls.mock_pip_freeze = cls.pip_freeze_patcher.start()
cls.mock_pip_install = cls.pip_install_patcher.start() cls.mock_pip_install = cls.pip_install_patcher.start()
cls.mock_pip_uninstall = cls.pip_uninstall_patcher.start()
cls.mock_pip_check = cls.pip_check_patcher.start() cls.mock_pip_check = cls.pip_check_patcher.start()
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
cls.pip_check_patcher.start() cls.pip_check_patcher.start()
cls.pip_uninstall_patcher.start()
cls.pip_install_patcher.start() cls.pip_install_patcher.start()
cls.pip_freeze_patcher.start()
cls.pkg_patcher.stop() cls.pkg_patcher.stop()
@patch("sys.argv", ["bootstrap", "-a", "pipenv"]) @patch("sys.argv", ["bootstrap", "-a", "pipenv"])
@ -94,32 +74,13 @@ class TestBootstrap(TestCase):
with patch("sys.stdout", new=StringIO()) as fake_out: with patch("sys.stdout", new=StringIO()) as fake_out:
bootstrap.run() bootstrap.run()
self.assertEqual( self.assertEqual(
fake_out.getvalue(), fake_out.getvalue(), "\n".join(self.installed_libraries),
"\n".join(self.installed_libraries.values()),
) )
@patch("sys.argv", ["bootstrap", "-a", "install"]) @patch("sys.argv", ["bootstrap", "-a", "install"])
def test_run_cmd_install(self): def test_run_cmd_install(self):
bootstrap.run() bootstrap.run()
self.assertEqual(
self.mock_pip_freeze.call_count, len(self.installed_libraries)
)
to_uninstall = reduce(
lambda x, y: x + y,
[
pkgs
for lib, pkgs in bootstrap.libraries.items()
if lib in self.installed_instrumentations
],
)
self.mock_pip_uninstall.assert_has_calls(
[call(i) for i in to_uninstall], any_order=True
)
self.mock_pip_install.assert_has_calls( self.mock_pip_install.assert_has_calls(
[call(i) for i in self.installed_libraries.values()], [call(i) for i in self.installed_libraries], any_order=True,
any_order=True,
) )
self.assertEqual(self.mock_pip_check.call_count, 1) self.assertEqual(self.mock_pip_check.call_count, 1)

View File

@ -0,0 +1,98 @@
#!/usr/bin/env python3
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import ast
import logging
import os
import subprocess
import astor
import pkg_resources
from otel_packaging import (
get_instrumentation_packages,
root_path,
scripts_path,
)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("instrumentation_list_generator")
_auto_generation_msg = """
# DO NOT EDIT. THIS FILE WAS AUTOGENERATED FROM templates/{source}.
# RUN `python scripts/generate_setup.py` TO REGENERATE.
"""
_template = """
{header}
# DO NOT EDIT. THIS FILE WAS AUTOGENERATED FROM INSTRUMENTATION PACKAGES.
# RUN `python scripts/generate_instrumentation_bootstrap.py` TO REGENERATE.
{source}
"""
_source_tmpl = """
libraries = {}
default_instrumentations = []
"""
gen_path = os.path.join(
root_path,
"opentelemetry-instrumentation",
"src",
"opentelemetry",
"instrumentation",
"bootstrap_gen.py",
)
def main():
# pylint: disable=no-member
default_instrumentations = ast.List(elts=[])
libraries = ast.Dict(keys=[], values=[])
for pkg in get_instrumentation_packages():
if not pkg["instruments"]:
default_instrumentations.elts.append(ast.Str(pkg["requirement"]))
for target_pkg in pkg["instruments"]:
parsed = pkg_resources.Requirement.parse(target_pkg)
libraries.keys.append(ast.Str(parsed.name))
libraries.values.append(
ast.Dict(
keys=[ast.Str("library"), ast.Str("instrumentation")],
values=[ast.Str(target_pkg), ast.Str(pkg["requirement"])],
)
)
tree = ast.parse(_source_tmpl)
tree.body[0].value = libraries
tree.body[1].value = default_instrumentations
source = astor.to_source(tree)
with open(
os.path.join(scripts_path, "license_header.txt"), "r"
) as header_file:
header = header_file.read()
source = _template.format(header=header, source=source)
with open(gen_path, "w") as gen_file:
gen_file.write(source)
subprocess.run(["black", "-q", gen_path], check=True)
if __name__ == "__main__":
main()

View File

@ -17,6 +17,7 @@
import logging import logging
import os import os
import subprocess import subprocess
import sys
from jinja2 import Template from jinja2 import Template
@ -72,7 +73,17 @@ def main():
with open(generated_file, "w") as fh: with open(generated_file, "w") as fh:
fh.write(generated) fh.write(generated)
fh.flush() fh.flush()
subprocess.run(["black", "-q", generated_file], check=True)
subprocess.run(
[
sys.executable,
"scripts/eachdist.py",
"format",
"--path",
"instrumentation",
],
check=True,
)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,13 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

43
scripts/otel_packaging.py Normal file
View File

@ -0,0 +1,43 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import subprocess
scripts_path = os.path.dirname(os.path.abspath(__file__))
root_path = os.path.dirname(scripts_path)
instrumentations_path = os.path.join(root_path, "instrumentation")
def get_instrumentation_packages():
for pkg in sorted(os.listdir(instrumentations_path)):
pkg_path = os.path.join(instrumentations_path, pkg)
if not os.path.isdir(pkg_path):
continue
out = str(
subprocess.check_output(
"python setup.py meta", shell=True, cwd=pkg_path
)
)
instrumentation = json.loads(out.split("\\n")[1])
instrumentation["requirement"] = "==".join(
(instrumentation["name"], instrumentation["version"],)
)
yield instrumentation
if __name__ == "__main__":
print(list(get_instrumentation_packages()))

View File

@ -20,6 +20,8 @@ git checkout -b release/${VERSION}
git push origin release/${VERSION} git push origin release/${VERSION}
./scripts/eachdist.py update_versions --versions stable,prerelease ./scripts/eachdist.py update_versions --versions stable,prerelease
./scripts/generate_setup.py
./scripts/generate_instrumentation_bootstrap.py
rc=$? rc=$?
if [ $rc != 0 ]; then if [ $rc != 0 ]; then
echo "::set-output name=version_updated::0" echo "::set-output name=version_updated::0"

View File

@ -17,6 +17,8 @@
{{ auto_generation_msg }} {{ auto_generation_msg }}
import os import os
import distutils.cmd
import json
from configparser import ConfigParser from configparser import ConfigParser
import setuptools import setuptools
@ -55,7 +57,31 @@ for dep in extras_require["instruments"]:
extras_require["test"] = test_deps extras_require["test"] = test_deps
class JSONMetadataCommand(distutils.cmd.Command):
description = (
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
"auto-generate code in other places"
)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
metadata = {
'name': config['metadata']['name'],
'version': PACKAGE_INFO['__version__'],
'instruments': PACKAGE_INFO['_instruments'],
}
print(json.dumps(metadata))
setuptools.setup( setuptools.setup(
cmdclass={'meta': JSONMetadataCommand},
version=PACKAGE_INFO["__version__"], version=PACKAGE_INFO["__version__"],
extras_require=extras_require extras_require=extras_require
) )

12
tox.ini
View File

@ -156,6 +156,8 @@ envlist =
docker-tests docker-tests
docs docs
generate
[testenv] [testenv]
deps = deps =
-c dev-requirements.txt -c dev-requirements.txt
@ -212,7 +214,6 @@ changedir =
test-util-http: util/opentelemetry-util-http/tests test-util-http: util/opentelemetry-util-http/tests
test-sdkextension-aws: sdk-extension/opentelemetry-sdk-extension-aws/tests test-sdkextension-aws: sdk-extension/opentelemetry-sdk-extension-aws/tests
test-propagator-ot-trace: propagator/opentelemetry-propagator-ot-trace/tests test-propagator-ot-trace: propagator/opentelemetry-propagator-ot-trace/tests
test-exporter-datadog: exporter/opentelemetry-exporter-datadog/tests test-exporter-datadog: exporter/opentelemetry-exporter-datadog/tests
commands_pre = commands_pre =
@ -430,3 +431,12 @@ commands =
commands_post = commands_post =
docker-compose down -v docker-compose down -v
[testenv:generate]
deps =
-r {toxinidir}/gen-requirements.txt
commands =
{toxinidir}/scripts/generate_setup.py
{toxinidir}/scripts/generate_instrumentation_bootstrap.py