Git Product home page Git Product logo

honeycomb-opentelemetry-python's Introduction

Honeycomb OpenTelemetry Distro for Python

OSS Lifecycle CircleCI PyPi

STATUS: this library is BETA. You're welcome to try it, and let us know your feedback in the issues!

This is Honeycomb's Distribution of OpenTelemetry for Python. It makes getting started with OpenTelemetry and Honeycomb easier!

Latest release built with:

Requirements

  • Python 3.7 or higher

Getting Started

Honeycomb's Distribution of OpenTelemetry for Python allows you to streamline configuration and to instrument as quickly and easily as possible.

Why would I want to use this?

  • Streamlined configuration for sending data to Honeycomb!
  • Easy interop with existing instrumentation with OpenTelemetry!
  • Deterministic sampling!
  • Multi-span attributes!
  • Local visualizations!

License

Apache 2.0 License.

honeycomb-opentelemetry-python's People

Contributors

brookesargent avatar dependabot[bot] avatar emilyashley avatar gaganpreet avatar guillemtrebol avatar jamiedanielson avatar mikegoldsmith avatar pkanal avatar robbkidd avatar to-json avatar vreynolds avatar

Stargazers

 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

honeycomb-opentelemetry-python's Issues

types: a typechecker

It might be nice to have type annotations and run a type checker setup for once we get into custom ad-ons to the base distro. This might take some discovery, I haven't gotten a chance to use python types before but I'd love to if we can!

If we decide to use mypy here's a cheatsheet and don't forget to include a py.typed file for packaging. (poetry may do this by default?)

consider adding docs for troubleshooting cache issues

I'm not sure if this is something off with how I'm holding it, but after #56 , I cannot get the distro to work properly. It says it cannot find module honeycomb. If I revert and move honeycomb/opentelemetry out of the src folder, and update the pyproject package reference, it works as expected.

To reproduce, it may be necessary to remove the __pycache__ and reinstall. If so as a follow-up I'd like to add that to the Makefile as well, a clean target that removes pycache and dist.

research error in logs of tests

When running tests, this error shows up in the console:

Failed to export metrics, error code: StatusCode.UNAUTHENTICATED
Failed to export metrics, error code: StatusCode.UNAUTHENTICATED
Failed to export traces, error code: StatusCode.UNAUTHENTICATED
Failed to export traces, error code: StatusCode.UNAUTHENTICATED

Version conflict running honeycomb's opentelemetry-instrument

Versions
v0.1.2b0

Steps to reproduce

I am trying to run a Honeycomb + OpenTelemetry instrumented Flask app following the documentation on the docs here, as of April 4th 2023.
https://docs.honeycomb.io/getting-data-in/opentelemetry/python-distro/#automatic-instrumentation

I have built a Docker image as described here:

Dockerfile:

FROM python:3.9

COPY ./requirements.txt /app/requirements.txt

WORKDIR /app

RUN pip install -r requirements.txt
RUN pip install honeycomb-opentelemetry --pre
RUN opentelemetry-bootstrap --action=install

COPY . /app

ENTRYPOINT ["opentelemetry-instrument", "python","/app/app.py"]
EXPOSE 5000

requirements.txt:

Flask==2.0.2

app.py:

from flask import Flask, jsonify, request
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider

# Set up tracer
resource = Resource.create({"service.name": "my-service"})
trace.set_tracer_provider(TracerProvider(resource=resource))

# Define routes for the Flask app
app = Flask(__name__)


@app.route("/")
def index():
    return "Welcome to my Flask app!"


@app.route("/hello")
def hello():
    return jsonify({"message": "Hello, world!"})


@app.route("/user/<username>")
def user_profile(username):
    user_agent = request.headers.get("User-Agent")
    with trace.get_tracer(__name__).start_as_current_span("user_profile"):
        # Do some work here...
        return jsonify({"username": username, "user_agent": user_agent})


if __name__ == "__main__":
    app.run(host='0.0.0.0')

When running the application with this command, with Honeycomb debugging active:
docker container run -p 5000:5000 -e DEBUG=true flask_test

the following inconsistency with versions appears even before Flask starts:

Distribution distro configuration failed
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py", line 37, in _load_distros
    distro = entry_point.load()()
  File "/usr/local/lib/python3.9/site-packages/pkg_resources/__init__.py", line 2449, in load
    self.require(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/pkg_resources/__init__.py", line 2472, in require
    items = working_set.resolve(reqs, env, installer, extras=self.extras)
  File "/usr/local/lib/python3.9/site-packages/pkg_resources/__init__.py", line 777, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (opentelemetry-sdk 1.16.0 (/usr/local/lib/python3.9/site-packages), Requirement.parse('opentelemetry-sdk~=1.17.0'), {'opentelemetry-exporter-otlp-proto-grpc', 'opentelemetry-exporter-otlp-proto-
http'})
Failed to auto initialize opentelemetry
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py", line 119, in initialize
    distro = _load_distros()
  File "/usr/local/lib/python3.9/site-packages/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py", line 52, in _load_distros
    raise exc
  File "/usr/local/lib/python3.9/site-packages/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py", line 37, in _load_distros
    distro = entry_point.load()()
  File "/usr/local/lib/python3.9/site-packages/pkg_resources/__init__.py", line 2449, in load
    self.require(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/pkg_resources/__init__.py", line 2472, in require
    items = working_set.resolve(reqs, env, installer, extras=self.extras)
  File "/usr/local/lib/python3.9/site-packages/pkg_resources/__init__.py", line 777, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (opentelemetry-sdk 1.16.0 (/usr/local/lib/python3.9/site-packages), Requirement.parse('opentelemetry-sdk~=1.17.0'), {'opentelemetry-exporter-otlp-proto-grpc', 'opentelemetry-exporter-otlp-proto-
http'})

Django docs

Django's a thing. I think in our docs we should at least acknowledge it and mention or link to the appropriate instrumentation to install for Django apps. Probably not worth a whole-hog sample and docs section though.

dockerize the example flask app

We have a dockerized version of the plain python app, but this ticket is to dockerize the flask app to test more instrumentation and baggage with smoke tests

Automatic Instrumentation doesn't seem to work

Versions

current

Steps to reproduce

  1. run the flask app, see no automatic instrumentation for flask.

Additional context

The flask app should be automatically instrumented with the opentelemetry-instrument command line argument, but only manual instrumentation is being picked up. Smoke tests for the flask app should also be updated to include tests for auto-instr spans.

Add Honeycomb deterministic sampler

Create a new trace sampler that is based on the parent based sampler & ratio based sampler and returns appends the honeycomb sample rate as an additional attribute. This sampler should be added by to the tracer provider and use the configured sample rate from the HoneycombOptions class.

  • Create new sampler
  • Add sampler as part of tracer provider creation

πŸ“ Planning Issue β¬… πŸ‘€

βœ” Project Setup

  • #4
    • pyproject setup; poetry
    • linting: pylint, pycodestyle
    • testing suite setup hello world; coverage, pytest
    • readme dev instructions
  • #20
  • #2
  • #5

βœ” Instrumentation Setup - Tracing

βœ” Project Maintenance / Hygiene

βœ” Honeycomb Add-ons

βœ” Packaging

  • #6
    • explore packaging a py package locally
    • try it out in EGS
  • #7
    • setup packaging and release with circleCI + PyPI
    • bump2version like libhoney-py?
    • releasing.md

βœ” Smoke Tests

Documentation

[dev] audit of developing.md, releasing.md, and readme.md

TODO:

README:

  • include minimum supported Python (like upstream) and a link to DEVELOPING if the reader wants to tinker
  • describe (very high level diffs) of examples and link to their READMEs

DEVELOPING:

  • replace poetry commands with make commands for a dev experience consistent with our other projects and CI

EXAMPLES READMES:

  • use poetry commands in the examples READMEs to speak to a Pythony audience that don't care about our dev workflow

Setup logging

Our logging is currently done using print(). We should instead use the defacto Logging packages.

Fix linting errors

Is your feature request related to a problem? Please describe.
There are a lot of linting errors when running make lint. These should be resolved before enabling the lint to run in CI in #31.

Project setup for local development

We'd like the project to be set up for local development, this includes:

  • pyproject setup and poetry
  • a system for linting. see: pylint, pycodestyle
  • a testing suite setup with a hello world example; code coverage
  • and a readme / dev instructions for each of these aspects!

See also #2 required for local setup for development and troubleshooting.

DeterministicSampler: Parent-based or not?

We initially built this with a Parent-based approach to sampling, however in discussion there have been several shortcomings of this approach.

  • Parent based would potentially make a decision that differs from the sample rate we're setting as an attribute
  • We intentionally removed the parent-based from java... "parent-based sampler would not work because we need to know what SampleRate to set"
  • If we are to follow the behavior in our other distros, we should not be considering a parent span's sampling decision when sampling.

This is a ticket to discuss :) See if these shortcomings still exist. Once we decide and document all concerns, PR #96 is available to toggle it off if needed!

add way to clear env vars before running tests

Is your feature request related to a problem? Please describe.

Unexpected behavior and failing tests when running tests with some environment variables set locally.

Describe the solution you'd like

Find a way to clear environment variables before test runs, similar to how we used the setup-jest file for the node distro.

Describe alternatives you've considered

currently just manually unsetting environment variables

Additional context

Something like monkeypatching environment variables seems to work but it involves a lot of extra copy/paste:

import pytest

@pytest.fixture
def mock_env_missing(monkeypatch):
    monkeypatch.delenv("OTEL_SERVICE_NAME", raising=False)

def test_defaults(mock_env_missing):

...
def test_can_set_service_name_with_envvar(monkeypatch):

Enable linting step in CI for our project preferences, modify the pylint.rc as needed

In #5 we set up the steps to run linting, but found it to be too cumbersome at this stage of development.

We should modify pylint to do what we'd like for linting, and ignore any rules we don't really care about.

Once we get to the "Honey add ons" section of the work, we can re-enable and require linting. I imagine this goes hand-in-hand with also setting up types #19 and docstrings.

warning about invalid protocol when debug is true

When DEBUG=true, a warning shows in the console that an invalid a protocol is detected provided:

WARNING:honeycomb.opentelemetry.options:Invalid OTLP exporter protocol detected. Must be one of ['grpc', 'http/protbuf']. Defaulting to grpc

This warning should not be displaying if I have not set any specific protocol. Is the warning valid? If so, is our protocol not being set properly?

Steps to reproduce

  1. export HONEYCOMB_API_KEY=mykey
  2. export DEBUG=true
  3. make run_example

[user] docs.honeycomb

  • Requirements
  • Examples
  • Initialize
  • Automatic Instrumentation
    • Install Packages
      • double-check there are no dependency conflicts with installing latest release
    • Configure and Run
    • GRPC vs HTTP
    • Advanced Configuration
  • Manual Instrumentation
    • Creating Spans
    • Adding Attributes to Spans
    • Propagating Baggage
  • Sampling
    • Deterministic Sampler, Sample Rate Attribute.
  • Distributed Trace Propagation
  • Troubleshooting
    • (ensure existing sections are still relevant)
    • Exporting to the console

https://github.com/honeycombio/docs/pull/1684

Add all Honeycomb options

Update HoneycombOptions to add the following options and include trace & metrics alternatives as appropriate.

  • API key
  • Traces API key
  • Metrics API key
  • Endpoint
  • Traces Endpoint
  • Metrics Endpoint
  • Dataset
  • Traces Dataset
  • Metrics Dataset
  • SampleRate
  • ServiceName
  • ServiceVersion
  • LocalVisualizations
  • Debug

validate: manual instrumentation when using the operator

Collection team recently added the ability to auto-instrument Python using the OTel Operator. We should validate that they can use the Pythin Distro to add manual instrumentation in that use case. (@TylerHelmuth has context on using the operator)

Outcome: we can use the distro with operator! --> file a follow-up issue to add docs (post python distro beta)
Outcome: we can't use the distro with operator :( --> file a follow-up issue to make it work as part of the python distro beta release

Allow HTTP trace & metric exporters

Add option to enable HTTP/protobuf based exporters instead of the default gRPC exporters. The protocol can be updated uing the following environment variables.

Supported values are grpc & http/protobuf with grpc being default.

See OpenTelemetry Protocol Exporter for more details.

  • Configure tracer provider exporter using OTEL_EXPORTER_OTLP_PROTOCOL and OTEL_EXPORTER_OTLP_TRACES_PROTOCOL
  • Configure metrics provider exporter using OTEL_EXPORTER_OTLP_PROTOCOL and OTEL_EXPORTER_OTLP_METRICS_PROTOCOL

Create example app with traces using python distro as local dependency

We'd like to have an example flask app in this repo that does the following:

  • uses latest code version of the Honey SDK (local dependency)
  • exercises at least one auto-instrumentation
  • creates at least one manual span
  • has a curl-able endpoint that generates telemetry
  • can be configured to send traces to HNY or to a local console

should opentelemetry-instrument read code config?

I run with opentelemetry-instrument, it doesn’t pick up my code configuration in this app.

poetry run opentelemetry-instrument python3 app.py results in unknown_service:python and debug is not true.

poetry run python3 app.py correctly picks up those env vars πŸ€”

I guess the question is… should it? Or does using opentelemetry-instrument mean you can only use env vars and not config in code with configure_opentelemetry?

Example app improvements

While reviewing some Python PRs, @JamieDanielson and I came across a couple of things with the example app that could be improved or maybe we were missing something! Wanted to log this issue before the holidays so that everything isn't washed away in January

  1. Get the example app to use our distro.
  2. The command poetry run opentelemetry-instrument flask run runs the app but results in some errors from OTel when traces are being sent
Transient error StatusCode.UNAVAILABLE encountered while exporting traces, retrying in 1s.

CircleCI setup

Setup a config.yml for circleCI that runs

  • the tests
  • and lint
  • and codestyle.

We also would like:

  • the tests to have a test summary
  • and the lint and codestyle to be relevant to our project

[dev/user] audit of example app as an illustrative example of use

  • explain the differences in examples (in the main readme? and also in example readmes)

  • flask --- uses environment variable options and opentelemetry-instrument

    • has the baggage examples for context vs token
  • hello-world --- uses configure_opentelemetry and options parameters

  • Add an example of local exporter.

  • Use MOAR options

  • Metrics?

Please move the example info from developing.md to readme.md

Improve docs around auto and manual SDK configuration options

Ensure docs describe both auto and manual SDK configuration using the distro.

For example:

  • Auto instrumentation with opentelemetry-instrument
  • Manual configuration with configure_opentelemetry

Note: our hello-world-flask example only show auto instrumentation.

Add baggage span processor

Create a new span processor that sets all currently set attrbutes from trace context baggage on newly started spans. This span procesor should also be added to the tracer provider.

  • Create new baggage span processor
  • Add processor to tracer provider

docs: update egs to use distro

Is your feature request related to a problem? Please describe.

We want to exercise the new distro in EGS!

Describe the solution you'd like

Switch a python service in EGS to use the Python Distro.

Packaging setup - Locally

We'd like to follow good, modern python packaging guidelines so let's explore what those are.
Before setting packaging and releasing up on PyPI (#7) we're going to want to test it out locally.

This ticket might be done when:

  • We can check out how the packaging works locally and test against it
  • You feel good about the experience of including this module in external code (i.e. EGS)

This might be a good place to start? https://packaging.python.org/en/latest/tutorials/packaging-projects/.
It's worth noting that we're using poetry so best practices might differ from pip recommendations.

Add debug & console warnings

In some following scenarios, we should print warnings for the user to inform them of bad / invalid configuration:

  • No Honeycomb API key set
  • Legacy API key and no dataset us set
  • New API key and dataset is set

Note: Depoends on the following PR to merge

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.