Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port of jaeger remote sampling #3865

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

sconover
Copy link

Description

I'm attempting to port the jaeger remote sampling support from the jaeger-client-python project.
For background about why the PR is structured the way it is, please see this thread.

I'm opening this in draft mode to seek initial feedback+guidance. There's a series of TODO's that raise questions about approach.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Unit tests, in test_sampling.py and test_rate_limiter.py

Does This PR Require a Contrib Repo Change?

It doesn't require one, but there will be a companion PR that depends on this change.

  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

Includes certain modifications to core samplers,
to provide capabilities assumed by the jaeger remote samplers
@sconover
Copy link
Author

@aabmass @srikanthccv Updated as requested, PTAL

@sconover
Copy link
Author

In case it's helpful, here are some general instructions for flexing this e2e:

# A jaeger agent may be started using a command like:
#
# docker run \
# -v /dev/scratch/config:/config \
# -e SAMPLING_CONFIG_TYPE=file \
# -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
# -p 5775:5775/udp \
# -p 6831:6831/udp \ 
# -p 6832:6832/udp \ 
# -p 5778:5778 \
# -p 16686:16686 \   
# -p 14268:14268 \ 
# -p 14250:14250 \ 
# -p 9411:9411 \
# jaegertracing/all-in-one:1.22 \
# --sampling.strategies-file=/config/strategies.json \
# --sampling.strategies-reload-interval=5s
#
# Where the sampling strategies config file is available locally at
# 
# /dev/scratch/config/strategies.json 
#
#
# Run this python script and make a request using:
#   curl localhost:5000/
# If the sampling decision is 'sample' then the ConsoleSpanExporter
# will print the emitted span to the console.
#
# If the agent's strategies.json files is changed to something like
#
# 
# {
#   "service_strategies": [
#     {
#       "service": "foo",
#       "type": "probabilistic",
#       "param": 0.333
#     }
#   ],
#   "default_strategy": {
#     "type": "probabilistic",
#     "param": 1
#   }
# }
#
# ...once these settings sync over via RemoteControlledSampler,
# it will take several curl invocations to see an emitted span,
# reflecting the 1-in-3 chance that a trace is created.

from opentelemetry.sdk.resources import SERVICE_NAME, Resource

from opentelemetry import trace
from opentelemetry.sdk.trace.export import ConsoleSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor

from opentelemetry.jaeger_remote_sampling import RemoteControlledSampler
from opentelemetry.jaeger_remote_sampling import LocalAgentSender

import threading
import tornado

main_loop = tornado.ioloop.IOLoop().current()

import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)

sampler = RemoteControlledSampler(
    channel=LocalAgentSender('localhost', 5778, 5778, io_loop=main_loop),
    service_name='foo',
    sampling_refresh_interval = 5,
    logger = logger,
)

resource = Resource(attributes={
    SERVICE_NAME: "foo"
})
traceProvider = TracerProvider(resource=resource, sampler=sampler)
traceProvider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter("foo")))
trace.set_tracer_provider(traceProvider)

from flask import (
    Flask, 
    jsonify
)

tracer = trace.get_tracer("foo")

def create_app():
    app = Flask(__name__)

    @app.route('/')
    def hello_world(): 
        with tracer.start_as_current_span("foo") as span:
                span.set_attribute("hello.value", "world")
                return jsonify({
                    "status": "success",
                    "message": "Hello World!"
                })
     
    return app

app = create_app()

if __name__ == '__main__':
    threading.Thread(target=lambda: app.run(debug=True, use_reloader=False)).start()
    print("start main loop")
    main_loop.start()
    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant