From 8d5646c2e7923605d77cbc95277faec8e2fe1159 Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Sun, 16 Jun 2024 23:12:27 -0700 Subject: [PATCH 1/6] add tracer, readme, tests --- .gitignore | 1 + README.md | 96 +++++++++-------------- requirements.txt | 3 + src/api_tracer/__init__.py | 3 + src/api_tracer/path_finder.py | 69 ++++++++++++++++ src/api_tracer/span.py | 43 ++++++++++ src/api_tracer/span_exporter/collector.py | 27 +++++++ tests/collector/collector-config.yaml | 21 +++++ tests/test_scipy.py | 14 ++++ tests/test_span.py | 27 +++++++ 10 files changed, 243 insertions(+), 61 deletions(-) create mode 100644 src/api_tracer/__init__.py create mode 100644 src/api_tracer/path_finder.py create mode 100644 src/api_tracer/span.py create mode 100644 src/api_tracer/span_exporter/collector.py create mode 100644 tests/collector/collector-config.yaml create mode 100644 tests/test_scipy.py create mode 100644 tests/test_span.py diff --git a/.gitignore b/.gitignore index baf47da..db362aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .venv __pycache__ .coverage +*/*.egg-info diff --git a/README.md b/README.md index c4cea62..f17e98a 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,52 @@ -# Python project template +# API Tracer -This is a template repository for any Python project that comes with the following dev tools: +This library adds basic telemetry to Python projects that traces the usage and run time of Python functions within a given scope. -* `ruff`: identifies many errors and style issues (`flake8`, `isort`, `pyupgrade`) -* `black`: auto-formats code +## Usage -Those checks are run as pre-commit hooks using the `pre-commit` library. +To track usage of one or more existing Python projects, run: -It includes `pytest` for testing plus the `pytest-cov` plugin to measure coverage. - -The checks and tests are all run using Github actions on every pull request and merge to main. - -This repository is setup for Python 3.11. To change the version: -1. Change the `image` argument in `.devcontainer/devcontainer.json` (see [https://github.com/devcontainers/images/tree/main/src/python](https://github.com/devcontainers/images/tree/main/src/python#configuration) for a list of pre-built Docker images) -1. Change the config options in `.precommit-config.yaml` -1. Change the version number in `.github/workflows/python.yaml` - -## Development instructions - -## With devcontainer - -This repository comes with a devcontainer (a Dockerized Python environment). If you open it in Codespaces, it should automatically initialize the devcontainer. - -Locally, you can open it in VS Code with the Dev Containers extension installed. - -## Without devcontainer - -If you can't or don't want to use the devcontainer, then you should first create a virtual environment: +```python +from api_tracer import install, start_span_processor +install( + [ + my_project.my_module + ] +) +start_span_processor('my-project-service') ``` -python3 -m venv .venv -source .venv/bin/activate -``` - -Then install the dev tools and pre-commit hooks: -``` -python3 -m pip install --user -r requirements-dev.txt -pre-commit install -``` +To explicitly add instrumentation to functions you want to trace, use the `span` decorator: -## Adding code and tests +```python +from api_tracer import span, start_span_processor -This repository starts with a very simple `main.py` and a test for it at `tests/main_test.py`. -You'll want to replace that with your own code, and you'll probably want to add additional files -as your code grows in complexity. -When you're ready to run tests, run: +@span +def foo(bar): + print(bar) +if __name__ == "__main__": + start_span_processor("test-service") + foo(bar="baz") ``` -python3 -m pytest -``` - -# File breakdown -Here's a short explanation of each file/folder in this template: +## Start collector -* `.devcontainer`: Folder containing files used for setting up a devcontainer - * `devcontainer.json`: File configuring the devcontainer, includes VS Code settings -* `.github`: Folder for Github-specific files and folders - * `workflows`: Folder containing Github actions config files - * `python.yaml`: File configuring Github action that runs tools and tests -* `tests`: Folder containing Python tests - * `main_test.py`: File with pytest-style tests of main.py -* `.gitignore`: File describing what file patterns Git should never track -* `.pre-commit-config.yaml`: File listing all the pre-commit hooks and args -* `main.py`: The main (and currently only) Python file for the program -* `pyproject.toml`: File configuring most of the Python dev tools -* `README.md`: You're reading it! -* `requirements-dev.txt`: File listing all PyPi packages required for development -* `requirements.txt`: File listing all PyPi packages required for production +To start a collector that prints each log message to stdout, run `cd tests/collector` and run -For a longer explanation, read [this blog post](http://blog.pamelafox.org/2022/09/how-i-setup-python-project.html). +```bash +docker run -p 4317:4317 -p 4318:4318 --rm -v $(pwd)/collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector +``` -# 🔎 Found an issue or have an idea for improvement? +To start a Jaeger collector that starts a basic dashboard, run: -Help me make this template repository better by letting us know and opening an issue! +```bash +docker run --name jaeger \ + -e COLLECTOR_OTLP_ENABLED=true \ + -p 16686:16686 \ + -p 4317:4317 \ + -p 4318:4318 \ + jaegertracing/all-in-one:1.35 +``` diff --git a/requirements.txt b/requirements.txt index e69de29..0bd5b90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1,3 @@ +opentelemetry-api==1.25.0 +opentelemetry-sdk==1.25.0 +opentelemetry-exporter-otlp-proto-grpc==1.25.0 diff --git a/src/api_tracer/__init__.py b/src/api_tracer/__init__.py new file mode 100644 index 0000000..76f084d --- /dev/null +++ b/src/api_tracer/__init__.py @@ -0,0 +1,3 @@ +from api_tracer.path_finder import install +from api_tracer.span import span +from api_tracer.span_exporter.jaeger import start_span_processor diff --git a/src/api_tracer/path_finder.py b/src/api_tracer/path_finder.py new file mode 100644 index 0000000..932fcb8 --- /dev/null +++ b/src/api_tracer/path_finder.py @@ -0,0 +1,69 @@ +import inspect +import sys +from importlib.abc import MetaPathFinder +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader + +from api_tracer.span import span + +__all__ = ["install"] + + +class TelemetryMetaFinder(MetaPathFinder): + def __init__(self, module_names, *args, **kwargs): + """MetaPathFinder implementation that overrides a spec loader + of type SourceFileLoader with a TelemetrySpanLoader. + + Args: + module_names (List[str]): Module names to include. + """ + self._module_names = module_names + super().__init__(*args, **kwargs) + + def find_spec(self, fullname, path, target=None): + if any([name in fullname for name in self._module_names]): + for finder in sys.meta_path: + if finder != self: + spec = finder.find_spec(fullname, path, target) + if spec is not None: + if isinstance(spec.loader, SourceFileLoader): + return spec_from_loader( + name=spec.name, + loader=TelemetrySpanSourceFileLoader( + spec.name, + spec.origin + ), + origin=spec.origin + ) + else: + return spec + + return None + + +class TelemetrySpanSourceFileLoader(SourceFileLoader): + def exec_module(self, module): + super().exec_module(module) + functions = inspect.getmembers(module, predicate=inspect.isfunction) + classes = inspect.getmembers(module, predicate=inspect.isclass) + + # Add telemetry to functions + for name, _function in functions: + _module = inspect.getmodule(_function) + if module == _module: + setattr(_module, name, span(_function)) + + # Add telemetry to methods + for _, _class in classes: + for name, method in inspect.getmembers( + _class, + predicate=inspect.isfunction + ): + if inspect.getmodule(_class) == module: + if not name.startswith("_"): + setattr(_class, name, span(method)) + + +def install(module_names: list[str]): + """Inserts the finder into the import machinery""" + sys.meta_path.insert(0, TelemetryMetaFinder(module_names)) diff --git a/src/api_tracer/span.py b/src/api_tracer/span.py new file mode 100644 index 0000000..23f4b84 --- /dev/null +++ b/src/api_tracer/span.py @@ -0,0 +1,43 @@ +from collections.abc import Sequence +from contextlib import wraps + +from opentelemetry import trace + +ALLOWED_TYPES = [bool, str, bytes, int, float] + +__all__ = ["span"] + + +def _get_func_name(func): + return f"{func.__module__}.{func.__qualname__}" + + +def _serialize(arg): + for _type in ALLOWED_TYPES: + if isinstance(arg, _type): + return arg + if isinstance(arg, Sequence) and len(arg) > 0: + if isinstance(arg[0], _type): + return arg + return str(arg) + + +def span(func): + # Creates a tracer from the global tracer provider + tracer = trace.get_tracer(__name__) + func_name = _get_func_name(func) + + @wraps(func) + def span_wrapper(*args, **kwargs): + with tracer.start_as_current_span(func_name) as span: + span.set_attribute("num_args", len(args)) + span.set_attribute("num_kwargs", len(kwargs)) + print(args) + print(kwargs) + for n, arg in enumerate(args): + span.set_attribute(f"args.{n}", _serialize(arg)) + for k, v in kwargs.items(): + span.set_attribute(f"kwargs.{k}", v) + return func(*args, **kwargs) + + return span_wrapper diff --git a/src/api_tracer/span_exporter/collector.py b/src/api_tracer/span_exporter/collector.py new file mode 100644 index 0000000..66c140b --- /dev/null +++ b/src/api_tracer/span_exporter/collector.py @@ -0,0 +1,27 @@ +import os +import os.path + +from opentelemetry import trace +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter +from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor + +__all__ = ["start_span_processor"] + + +def start_span_processor(service_name: str): + resource = Resource(attributes={ + "service.name": service_name + }) + trace.set_tracer_provider(TracerProvider(resource=resource)) + + agent_host_name = os.environ.get("OTEL_COLLECTOR_HOST", "localhost") + agent_port = os.environ.get("OTEL_COLLECTOR_PORT", 4317) + endpoint = f"http://{agent_host_name}:{agent_port}" + + otlp_exporter = OTLPSpanExporter(endpoint=endpoint, insecure=True) + + trace.get_tracer_provider().add_span_processor( + BatchSpanProcessor(otlp_exporter) + ) diff --git a/tests/collector/collector-config.yaml b/tests/collector/collector-config.yaml new file mode 100644 index 0000000..29b4a93 --- /dev/null +++ b/tests/collector/collector-config.yaml @@ -0,0 +1,21 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +exporters: + debug: + verbosity: detailed +service: + pipelines: + traces: + receivers: [otlp] + exporters: [debug] + metrics: + receivers: [otlp] + exporters: [debug] + logs: + receivers: [otlp] + exporters: [debug] diff --git a/tests/test_scipy.py b/tests/test_scipy.py new file mode 100644 index 0000000..4a8ce29 --- /dev/null +++ b/tests/test_scipy.py @@ -0,0 +1,14 @@ +from api_tracer import install, start_span_processor + +if __name__ == "__main__": + install( + [ + "scipy.stats._distn_infrastructure" + ] + ) + start_span_processor("scipy-service") + + from scipy import stats + + stats.norm.pdf(x=1, loc=1, scale=0.01) + stats.norm(loc=1, scale=0.01).pdf(1) diff --git a/tests/test_span.py b/tests/test_span.py new file mode 100644 index 0000000..e693c49 --- /dev/null +++ b/tests/test_span.py @@ -0,0 +1,27 @@ +from time import sleep + +from api_tracer import span, start_span_processor + + +@span +def foo(hello="world", delay=1): + print(hello) + sleep(delay) + +@span +def bar(spam="eggs", delay=1): + print(spam) + sleep(delay) + +@span +def baz(apple="orange", delay=1): + print(apple) + sleep(delay) + + +if __name__ == "__main__": + start_span_processor("test-service") + + foo(hello="foo", delay=1) + bar(spam="bar", delay=2) + baz(apple="baz", delay=3) From a23fcaac488b8ad9c04f2efcc6823ea521857d9a Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Sun, 16 Jun 2024 23:16:19 -0700 Subject: [PATCH 2/6] import from collector --- src/api_tracer/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api_tracer/__init__.py b/src/api_tracer/__init__.py index 76f084d..6c2f97a 100644 --- a/src/api_tracer/__init__.py +++ b/src/api_tracer/__init__.py @@ -1,3 +1,3 @@ from api_tracer.path_finder import install from api_tracer.span import span -from api_tracer.span_exporter.jaeger import start_span_processor +from api_tracer.span_exporter.collector import start_span_processor From 43c9a1cac7b6a07e6edee57ba9e385b6c1f241ba Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Mon, 17 Jun 2024 13:53:52 +0200 Subject: [PATCH 3/6] refactor --- collector/collector-config.yaml | 22 +++++++++++++++++++ src/api_tracer/__init__.py | 2 +- src/api_tracer/span_processor/__init__.py | 1 + .../collector.py | 18 ++++++++++++--- tests/test_scipy.py | 4 ++-- tests/test_span.py | 5 ++--- 6 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 collector/collector-config.yaml create mode 100644 src/api_tracer/span_processor/__init__.py rename src/api_tracer/{span_exporter => span_processor}/collector.py (60%) diff --git a/collector/collector-config.yaml b/collector/collector-config.yaml new file mode 100644 index 0000000..b24459c --- /dev/null +++ b/collector/collector-config.yaml @@ -0,0 +1,22 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +exporters: + debug: + verbosity: detailed +service: + pipelines: + traces: + receivers: [otlp] + exporters: [debug] + metrics: + receivers: [otlp] + exporters: [debug] + logs: + receivers: [otlp] + exporters: [debug] + diff --git a/src/api_tracer/__init__.py b/src/api_tracer/__init__.py index 6c2f97a..7f82508 100644 --- a/src/api_tracer/__init__.py +++ b/src/api_tracer/__init__.py @@ -1,3 +1,3 @@ from api_tracer.path_finder import install from api_tracer.span import span -from api_tracer.span_exporter.collector import start_span_processor +from api_tracer.span_processor import setup_collector, setup_console diff --git a/src/api_tracer/span_processor/__init__.py b/src/api_tracer/span_processor/__init__.py new file mode 100644 index 0000000..645b031 --- /dev/null +++ b/src/api_tracer/span_processor/__init__.py @@ -0,0 +1 @@ +from api_tracer.span_processor.collector import setup_collector, setup_console diff --git a/src/api_tracer/span_exporter/collector.py b/src/api_tracer/span_processor/collector.py similarity index 60% rename from src/api_tracer/span_exporter/collector.py rename to src/api_tracer/span_processor/collector.py index 66c140b..50a40b9 100644 --- a/src/api_tracer/span_exporter/collector.py +++ b/src/api_tracer/span_processor/collector.py @@ -5,12 +5,12 @@ from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import BatchSpanProcessor +from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter -__all__ = ["start_span_processor"] +__all__ = ["setup_collector"] -def start_span_processor(service_name: str): +def setup_collector(service_name: str): resource = Resource(attributes={ "service.name": service_name }) @@ -25,3 +25,15 @@ def start_span_processor(service_name: str): trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(otlp_exporter) ) + + +def setup_console(service_name: str): + resource = Resource(attributes={ + "service.name": service_name + }) + trace.set_tracer_provider(TracerProvider(resource=resource)) + console_exporter = ConsoleSpanExporter() + + trace.get_tracer_provider().add_span_processor( + BatchSpanProcessor(console_exporter) + ) diff --git a/tests/test_scipy.py b/tests/test_scipy.py index 4a8ce29..c30e6f8 100644 --- a/tests/test_scipy.py +++ b/tests/test_scipy.py @@ -1,4 +1,4 @@ -from api_tracer import install, start_span_processor +from api_tracer import install, setup_collector if __name__ == "__main__": install( @@ -6,7 +6,7 @@ "scipy.stats._distn_infrastructure" ] ) - start_span_processor("scipy-service") + setup_collector("scipy-service") from scipy import stats diff --git a/tests/test_span.py b/tests/test_span.py index e693c49..2d53c59 100644 --- a/tests/test_span.py +++ b/tests/test_span.py @@ -1,6 +1,6 @@ from time import sleep -from api_tracer import span, start_span_processor +from api_tracer import setup_console, span @span @@ -20,8 +20,7 @@ def baz(apple="orange", delay=1): if __name__ == "__main__": - start_span_processor("test-service") - + setup_console("test-service") foo(hello="foo", delay=1) bar(spam="bar", delay=2) baz(apple="baz", delay=3) From c7374692e446768b9f808c9c249142ad00a3f51c Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Mon, 12 May 2025 14:42:47 -0700 Subject: [PATCH 4/6] use auto_instrumentation --- .gitignore | 3 ++ pyproject.toml | 28 ++++++++++++++++ src/api_tracer/__init__.py | 1 - src/api_tracer/console.py | 24 +++++++++++++ src/api_tracer/span.py | 3 +- src/api_tracer/span_processor/__init__.py | 1 - src/api_tracer/span_processor/collector.py | 39 ---------------------- tests/test_scipy.py | 30 +++++++++++------ tests/test_span.py | 5 +-- 9 files changed, 78 insertions(+), 56 deletions(-) create mode 100644 src/api_tracer/console.py delete mode 100644 src/api_tracer/span_processor/__init__.py delete mode 100644 src/api_tracer/span_processor/collector.py diff --git a/.gitignore b/.gitignore index db362aa..9916cd8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ +.env .venv __pycache__ .coverage */*.egg-info +uv.lock +.vscode diff --git a/pyproject.toml b/pyproject.toml index fadfc3b..e128d11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,31 @@ +[project] +name = "api_tracer" +authors = [ + { name = "guenp", email = "guenp@hey.com" }, +] +description = "A great package." +readme = "README.md" +license = "MIT" +requires-python = ">=3.9" +classifiers = [ + "Development Status :: 1 - Planning", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering", + "Typing :: Typed", +] +dynamic = ["version"] +dependencies = [] + [tool.ruff] line-length = 120 target-version = "py311" diff --git a/src/api_tracer/__init__.py b/src/api_tracer/__init__.py index 7f82508..d1c5156 100644 --- a/src/api_tracer/__init__.py +++ b/src/api_tracer/__init__.py @@ -1,3 +1,2 @@ from api_tracer.path_finder import install from api_tracer.span import span -from api_tracer.span_processor import setup_collector, setup_console diff --git a/src/api_tracer/console.py b/src/api_tracer/console.py new file mode 100644 index 0000000..6ec0f93 --- /dev/null +++ b/src/api_tracer/console.py @@ -0,0 +1,24 @@ +import os + +from opentelemetry import trace +from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter + +__all__ = ["setup_console"] + + +def setup_console(service_name: str | None = None): + if service_name is None: + attributes = os.environ.get("OTEL_RESOURCE_ATTRIBUTES") + attributes = dict(k.split("=") for k in attributes.split(",")) + else: + attributes = {"service.name": service_name} + + resource = Resource(attributes=attributes) + trace.set_tracer_provider(TracerProvider(resource=resource)) + console_exporter = ConsoleSpanExporter() + + trace.get_tracer_provider().add_span_processor( + BatchSpanProcessor(console_exporter) + ) diff --git a/src/api_tracer/span.py b/src/api_tracer/span.py index 23f4b84..1931365 100644 --- a/src/api_tracer/span.py +++ b/src/api_tracer/span.py @@ -32,12 +32,11 @@ def span_wrapper(*args, **kwargs): with tracer.start_as_current_span(func_name) as span: span.set_attribute("num_args", len(args)) span.set_attribute("num_kwargs", len(kwargs)) - print(args) - print(kwargs) for n, arg in enumerate(args): span.set_attribute(f"args.{n}", _serialize(arg)) for k, v in kwargs.items(): span.set_attribute(f"kwargs.{k}", v) + span.set_status(trace.StatusCode.OK) return func(*args, **kwargs) return span_wrapper diff --git a/src/api_tracer/span_processor/__init__.py b/src/api_tracer/span_processor/__init__.py deleted file mode 100644 index 645b031..0000000 --- a/src/api_tracer/span_processor/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from api_tracer.span_processor.collector import setup_collector, setup_console diff --git a/src/api_tracer/span_processor/collector.py b/src/api_tracer/span_processor/collector.py deleted file mode 100644 index 50a40b9..0000000 --- a/src/api_tracer/span_processor/collector.py +++ /dev/null @@ -1,39 +0,0 @@ -import os -import os.path - -from opentelemetry import trace -from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter -from opentelemetry.sdk.resources import Resource -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter - -__all__ = ["setup_collector"] - - -def setup_collector(service_name: str): - resource = Resource(attributes={ - "service.name": service_name - }) - trace.set_tracer_provider(TracerProvider(resource=resource)) - - agent_host_name = os.environ.get("OTEL_COLLECTOR_HOST", "localhost") - agent_port = os.environ.get("OTEL_COLLECTOR_PORT", 4317) - endpoint = f"http://{agent_host_name}:{agent_port}" - - otlp_exporter = OTLPSpanExporter(endpoint=endpoint, insecure=True) - - trace.get_tracer_provider().add_span_processor( - BatchSpanProcessor(otlp_exporter) - ) - - -def setup_console(service_name: str): - resource = Resource(attributes={ - "service.name": service_name - }) - trace.set_tracer_provider(TracerProvider(resource=resource)) - console_exporter = ConsoleSpanExporter() - - trace.get_tracer_provider().add_span_processor( - BatchSpanProcessor(console_exporter) - ) diff --git a/tests/test_scipy.py b/tests/test_scipy.py index c30e6f8..9f97849 100644 --- a/tests/test_scipy.py +++ b/tests/test_scipy.py @@ -1,14 +1,22 @@ -from api_tracer import install, setup_collector +from opentelemetry.instrumentation.auto_instrumentation import initialize -if __name__ == "__main__": - install( - [ - "scipy.stats._distn_infrastructure" - ] - ) - setup_collector("scipy-service") +from api_tracer import install +from api_tracer.console import setup_console - from scipy import stats +install([ + "scipy.stats._correlation", + "scipy.stats._distn_infrastructure" +]) +initialize() +setup_console() - stats.norm.pdf(x=1, loc=1, scale=0.01) - stats.norm(loc=1, scale=0.01).pdf(1) +from scipy import stats + +stats.norm.pdf(x=1, loc=1, scale=0.01) +stats.norm(loc=1, scale=0.02).pdf(1) +stats.chatterjeexi([1, 2, 3, 4],[1.1, 2.2, 3.3, 4.4]) + +# X = stats.Normal() +# Y = stats.exp((X + 1)*0.01) +# from scipy import test +# test() diff --git a/tests/test_span.py b/tests/test_span.py index 2d53c59..7094604 100644 --- a/tests/test_span.py +++ b/tests/test_span.py @@ -1,6 +1,7 @@ from time import sleep -from api_tracer import setup_console, span +from api_tracer.console import setup_console +from api_tracer.span import span @span @@ -20,7 +21,7 @@ def baz(apple="orange", delay=1): if __name__ == "__main__": - setup_console("test-service") + setup_console("test") foo(hello="foo", delay=1) bar(spam="bar", delay=2) baz(apple="baz", delay=3) From 26c862df5b87f2f1d55a2eb4505e295451f3a4e2 Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Mon, 12 May 2025 14:44:55 -0700 Subject: [PATCH 5/6] add prereqs --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f17e98a..e38d8e1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,16 @@ This library adds basic telemetry to Python projects that traces the usage and run time of Python functions within a given scope. +## Installation + +Prerequisites: + +``` +pip install opentelemetry-distro +pip install opentelemetry-exporter-otlp +opentelemetry-bootstrap --action=install +``` + ## Usage To track usage of one or more existing Python projects, run: From 9af725daad822d58c017d763779e6e7b6fb9096a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 19:22:43 +0000 Subject: [PATCH 6/6] Bump opentelemetry-exporter-otlp-proto-grpc from 1.25.0 to 1.33.0 Bumps [opentelemetry-exporter-otlp-proto-grpc](https://github.com/open-telemetry/opentelemetry-python) from 1.25.0 to 1.33.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-python/compare/v1.25.0...v1.33.0) --- updated-dependencies: - dependency-name: opentelemetry-exporter-otlp-proto-grpc dependency-version: 1.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0bd5b90..df8d4bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ opentelemetry-api==1.25.0 opentelemetry-sdk==1.25.0 -opentelemetry-exporter-otlp-proto-grpc==1.25.0 +opentelemetry-exporter-otlp-proto-grpc==1.33.0