Coder Social home page Coder Social logo

open-telemetry / opentelemetry-python Goto Github PK

View Code? Open in Web Editor NEW
1.7K 42.0 593.0 12.92 MB

OpenTelemetry Python API and SDK

Home Page: https://opentelemetry.io

License: Apache License 2.0

Python 99.34% Shell 0.31% Jinja 0.35%
python opentelemetry tracecontext correlationcontext distributed-tracing logging metrics sdk

opentelemetry-python's Introduction

OpenTelemetry Python

Slack Build Status Minimum Python Version Release Read the Docs

Project Status

See the OpenTelemetry Instrumentation for Python.

Signal Status Project
Traces Stable N/A
Metrics Stable N/A
Logs Experimental N/A

Project versioning information and stability guarantees can be found here.

Getting started

You can find the getting started guide for OpenTelemetry Python here.

If you are looking for examples on how to use the OpenTelemetry API to instrument your code manually, or how to set up the OpenTelemetry Python SDK, see https://opentelemetry.io/docs/instrumentation/python/manual/.

Python Version Support

This project ensures compatibility with the current supported versions of the Python. As new Python versions are released, support for them is added and as old Python versions reach their end of life, support for them is removed.

We add support for new Python versions no later than 3 months after they become stable.

We remove support for old Python versions 6 months after they reach their end of life.

Documentation

The online documentation is available at https://opentelemetry-python.readthedocs.io/. To access the latest version of the documentation, see https://opentelemetry-python.readthedocs.io/en/latest/.

Install

This repository includes multiple installable packages. The opentelemetry-api package includes abstract classes and no-op implementations that comprise the OpenTelemetry API following the OpenTelemetry specification. The opentelemetry-sdk package is the reference implementation of the API.

Libraries that produce telemetry data should only depend on opentelemetry-api, and defer the choice of the SDK to the application developer. Applications may depend on opentelemetry-sdk or another package that implements the API.

The API and SDK packages are available on the Python Package Index (PyPI). You can install them via pip with the following commands:

pip install opentelemetry-api
pip install opentelemetry-sdk

The exporter/ directory includes OpenTelemetry exporter packages. You can install the packages separately with the following command:

pip install opentelemetry-exporter-{exporter}

The propagator/ directory includes OpenTelemetry propagator packages. You can install the packages separately with the following command:

pip install opentelemetry-propagator-{propagator}

To install the development versions of these packages instead, clone or fork this repository and perform an editable install:

pip install -e ./opentelemetry-api -e ./opentelemetry-sdk -e ./opentelemetry-semantic-conventions

For additional exporter and instrumentation packages, see the opentelemetry-python-contrib repository.

Contributing

For information about contributing to OpenTelemetry Python, see CONTRIBUTING.md.

We meet weekly on Thursdays at 9AM PST. The meeting is subject to change depending on contributors' availability. Check the OpenTelemetry community calendar for specific dates and Zoom meeting links.

Meeting notes are available as a public Google doc.

Approvers (@open-telemetry/python-approvers):

Emeritus Approvers

For more information about the approver role, see the community repository.

Maintainers (@open-telemetry/python-maintainers):

Emeritus Maintainers:

For more information about the maintainer role, see the community repository.

Thanks to all the people who already contributed!

opentelemetry-python's People

Contributors

aabmass avatar c24t avatar chalin avatar cnnradams avatar codeboten avatar dependabot[bot] avatar dgzlopes avatar emdneto avatar ffe4 avatar hectorhdzg avatar hivetraum avatar jeremydvoss avatar lmolkova avatar lzchen avatar majorgreys avatar mariojonke avatar mauriciovasquezbernal avatar musicinmybrain avatar nathanielrn avatar oberon00 avatar ocelotl avatar ofek avatar opentelemetrybot avatar owais avatar reyang avatar shalevr avatar soumyadeepm04 avatar srikanthccv avatar toumorokoshi avatar xrmx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opentelemetry-python's Issues

Create packages, automate releases

Create new opentelemetry- packages for the API and SDK, and consider doing the same for all OC contrib packages.

Configure CI to build and release these packages when we tag a new release.

See #6 for CI bootstrapping.

Tracing API

Add abstract classes for tracing following the java client and the (WIP) spec.

The API should also include no-op implementations for some classes, see the java client for details.

Decide supported Python 3.x versions (current code is 3.4+)

In #14 we decided not to support Python 2. But with the current code base, we do not even support 3.6, even though setup.py claims we support 3.4. While it would be nice to be on 3.7 only, I think we should at the very least support 3.6. Demo:

user@pc:~/opentelemetry-python/opentelemetry-api$ cat /etc/issue.net
Ubuntu 18.04.2 LTS
user@pc:~/opentelemetry-python/opentelemetry-api$ python3 --version # Note that this is the latest Python version in this Ubuntu version
Python 3.6.8
user@pc:~/opentelemetry-python/opentelemetry-api$ python3 -c 'import opentelemetry.trace'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/mnt/c/workspaces/misc/opentelemetry-python/opentelemetry-api/opentelemetry/trace/__init__.py", line 65
    from __future__ import annotations
    ^
SyntaxError: future feature annotations is not defined

This is PEP 563 which requires 3.7.

Type hints in general seem to be supported since 3.5 / PEP 484. But note that instance/class variable type hints would only be available since 3.6 (PEP 526).

Add Travis CI

Configure travis to run (the as-yet unwritten) tests, lint, and coverage checks on each PR.

cc @lzchen, who did some related work in opencensus-python.

TODO:

  • run unit tests in API and SDK
  • lint and type checks
  • coverage check

Add context API and implementation

We target Python 3, which has different ways of handing asynchronous context:

  1. Python 3.0 - 3.5, only Thread Local Storage is supported.
  2. Python 3.6, contextvars supported as a backport https://pypi.org/project/contextvars/.
  3. Python 3.7+, contextvars provided by the default library.

The current decision:

  1. In order to support v3.x, we need to take the similar approach like what we did in OpenCensus.
  2. We need to provide the ability for user to switch from contextvars back to Thread Local Storage, in order to make it work for existing systems like gevent and tornado. This can be exposed through a non-public API first, considering this is not a common scenario and we can remove it once all systems onboarded to contextvars.
  3. The context library should be released as an individual package.

[loader] Too easy to configure no-op implementation by mistake

From #29 (comment)

The current lazy-loading behavior makes it easy to accidentally create a no-op tracer that sticks around. E.g. if the configured API implementation is decided after making an HTTP request and the used HTTP library is instrumented, the no-op tracer would be installed by the loader (and it's not exchangeable).

Several possible solutions come to my mind:

  • Just provide setters that directly set the global objects. That would also resolve #44. Disadvantage: We allow changing an existing implementation and any loader logic is effectively circumvented if the app uses the setter.
  • Don't load implicitly, explicitly require a call to loader.load (this would require moving the storage of the global objects and factory callbacks back to the loader to be implementable). Before that, all getters will return no-op.
  • Provide loader.finish_configuration(). Similar to load but does not load immediately, only signals to getters that next time they are called they should load their component.

Decide unit test framework

I noticed OpenCensus Python used the Python standard library's unit test framework, while OpenTracing uses pytest. Personally I'd prefer pytest, as it lets you write all your assertions with the assert keyword and you don't have to think about importing & using assertEquals vs assertTrue, etc. On the other hand, the stdlib has the (slight?) advantage of not requiring an additional development dependency.

We should decide for a unit test framework.

Implement samplers

Following #53, implement samplers and use the sampling decision in span construction in the SDK package.

Generate SDK documentation

Currently only documentation for the API package is generated. It'd be nice to have documentation generated for the SDK package as well.

Integration: requests library

Write integration that (semi-?)automatically traces outgoing HTTP requests made using the requests library. Probably much code from OpenCensus can be reused.

Package and directory structure

Decide on the directory structure and packages for the new repo. Borrowing from OpenCensus, this might look like:

context/
contrib/
opentelemetry/
  api/
    logs/
    metrics/
    tags/
    trace/
  sdk/
    common/
    logs/
    metrics/
    tags/
    trace/

Changes as compared to OC:

  • api and sdk are separate packages
  • stats has been merged into metrics

Open questions:

  • What do we want to name the new packages: opentelemetry-api and opentelemetry-sdk, or just opentelemetry for the implementation package?
  • Should we continue to package context separately?
  • Should we distinguish between exporters and integrations (or "adapters") in contrib?

This assumes that we're still using namespace packages to create multiple distributions from the same codebase.

Rename start_span/create_span

Currently start_span() in different languages has different activation semantics: in Java and Ruby, it does not set the newly created Span as the active instance, while Python does (Go seems to offer to do it if you pass a Context).

In OpenTracing, for this purpose, we had start_span() and start_active_span().

Hence I'd suggest renaming the related methods:

  • create_span() -> start_span()
  • start_span() -> start_current_span() or similar

This will most likely impact the Specification itself at some degree, but wanted to ask here first about your opinion ;)

Add central implementation "registry"/global tracer

As the discussion about this on #11 is getting quite long (#11 (comment)), I opened this issue.

Basically, opentelemetry-python should provide some API that decouples code that just wants to use instrumentation/tracing APIs from any particular tracer implementation. Without such an API, one is forced (or at least tempted) to write code like:

from opentelemetry.sdk.trace import tracer # *** Hard-coded dependency on implemenation

# Create a new root span, set it as the current span in context
with tracer.start_span("parent"):
    pass # Do work

I think it is clear that we want to avoid that, as it would force a whole dependency tree of an application and its libraries to coordinate on a particular implementation of the API, which kinda defeats the purpose of having a separate API layer.

OpenTracing handles this by providing a global tracer object: https://github.com/opentracing/opentracing-python/blob/master/opentracing/__init__.py
OpenTelemetry-java also has a global OpenTelemetry instance that, among other things, holds a reference to a global tracer: https://github.com/open-telemetry/opentelemetry-java/blob/fb0f5339cd1d665a98996806f45c60c65f47d7b6/api/src/main/java/io/opentelemetry/OpenTelemetry.java#L49-L58
There are other options, like having libraries themselves manage their "library-global" tracers. This was also discussed in a different thread #11 (comment).

Public access to meeting notes

I think we should add a link to a publicly viewable document with the meeting notes to https://github.com/open-telemetry/community/#python-sdk. We already share the hangouts link (via calendar), so why not the meeting notes too?

I do not like the other SIGs' way of sharing a publicly editable single document with all historic meeting notes though -- anyone could just edit past meeting notes after the fact.

At least a read-only link to past meeting notes (in a single document or ) should be published. For the live meeting notes I can think of two options:

  • Just share a publicly editable link in the community README or the google calendar.
  • Publish contact points, e.g. "contact @c24t or @reyang at gitter to get write-access to live meeting notes". Alongside that, share a read-only link publicly (without at least a public read-only link, the public hangouts link makes little sense IMHO).

asyncio context propagation in Python 3.5/3.6

The contextvars approach to context propagation requires copying current context on asyncio task creation. This is done internally in asyncio for Python 3.7; however, on Python <3.7 context is not propagated automatically.

Example:

import asyncio
import contextvars

current_task = contextvars.ContextVar("current_task")


async def foo(foo_started, bar_done):
    current_task.set("foo")
    foo_started.set()
    await bar_done.wait()
    print("foo task:", current_task.get())


async def bar(foo_started, bar_done):
    await foo_started.wait()
    current_task.set("bar")
    bar_done.set()


async def main():
    foo_started = asyncio.Event()
    bar_done = asyncio.Event()

    await asyncio.gather(
        foo(foo_started, bar_done),
        bar(foo_started, bar_done),
    )


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

In Python 3.7, the code above will print foo task: foo
In Python 3.5 and 3.6, the code above will print foo task: bar

document pitfalls, e.g. confusion between tracer.Tracer() and tracer.tracer()

Is your feature request related to a problem?

Yes, I initially tried the example from the README.md:

trace.set_preferred_tracer_implementation(lambda T: Tracer())
tracer = trace.tracer()
with tracer.start_span('foo'):
    print(Context)
    with tracer.start_span('bar'):
        print(Context)
        with tracer.start_span('baz'):
            print(Context)
        print(Context)
    print(Context)

But I made a typo with the casing: I typed trace.Tracer() (the constructor for the abstract class Tracer) instead of trace.tracer() (returning the preferred implementation, configurable with set_preferred_tracer_implementation()). The output ended up as the following:

AsyncRuntimeContext({'current_span': None})
AsyncRuntimeContext({'current_span': None})
AsyncRuntimeContext({'current_span': None})
AsyncRuntimeContext({'current_span': None})
AsyncRuntimeContext({'current_span': None})

After fixing the typo, the correct output is displayed:

AsyncRuntimeContext({'current_span': Span(name="foo")})
AsyncRuntimeContext({'current_span': Span(name="bar")})
AsyncRuntimeContext({'current_span': Span(name="baz")})
AsyncRuntimeContext({'current_span': Span(name="bar")})
AsyncRuntimeContext({'current_span': Span(name="foo")})

It confused me at first that there was no error message from the typo.

Describe the solution you'd like

Maybe some documentation docs/pitfalls.md with a checklist of symptoms and common mistakes.

use black as the default python formatter

Proposing publicly to standardize on black as the Python formatter.

Black is fairly popular in the Python community, and is the default formatter for editors such as vscode. Autoformatting eliminates a class of discussion in PRs that does not provide material value to functionality.

Add README

I added a stub readme file in #16 to put contribution info front and center on the github project page, but the real readme file should include at least:

  • a description of the OpenTelemetry project
  • a description of the package structure
  • installation and usage instructions
  • links to examples and documentation

See also:

Offer a specific/static no-op `Span` instance.

In Java, we have a DefaultSpan which does nothing by default (it can propagate SpanContext too, but that's more of additional stuff), and can be used as both a no-op object.

Specifically, DefaultSpan.getInvalid() offers a static instance that can also be used when setting parent (through SpanBuilder.serParent()) and also for Tracer.getCurrentSpan() (so the user doesn't have to do a null check).

As Span at this moment already has this no-op functionality, maybe it makes sense to add a class field? This way we could do:

def start_span(..., parent = Span.invalid(), ...):
   if parent is Span.invalid():
     # fetch the actual current Span as parent.

def get_current_span(self):
   ...
   # Return a no-op in case there's no current Span.
   return Span.invalid()

Support async/await syntax

Python started to support async/await syntax in version 3.7.
We want to explore how to support this in OpenTelemetry Python.
Things to be explored are:

  1. Do we provide this in the API package or API+SDK?
  2. How do we test? If test cases are written using the async/await syntax, they won't work in Python <= v3.6, we might need to collect test cases based on runtime version.

Python 2.7 support

The current effort discards Python 2.7 support, and stick to the 3.x series. However, I know a few other vendors might need to stay compatible with 2.7, so I'm creating this ticket in order to track this.

Host docs, build on release

Decide where to host generated docs, configure CI to generate (and possibly upload) new docs on each release.

See #6 for CI bootstrapping.

Enabling shared state across processes

There are a couple use cases for being able to share objects across processes:

  1. sharing counters / gauges to ensure that the value accurately reflects the correct value for all processes (helpful when using a multi-process web server such as gunicorn)

  2. enable handing of trace information (may not be needed as oftentimes this is done via fork(), which will just create a copy-on-write copy).

We have some prior art with how prometheus does it: https://github.com/prometheus/client_python

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.