Tracing Fission functions with Jaeger
Bhavin Gandhi
Is the service working?
Let's keep checking for that
They are never 100% up
Nines don’t matter if users aren’t happy.
Being able to get view of system
Helps to understand your system
Stop reverse engineering applications and start monitoring from the inside.
Events, errors occurred in applications
The limits of logging
Signal to noise ratio
Serve for problems predicted in advanced
Numerical information about what's happening
Help to predict the behavior
Path taken by an user's request
Connecting individual components
Greetings as Service
Image credits: CNCF Branding & Zipkin Community: Logos
server.py
loads user defined functionsDirectory structure
./python-env ├── Dockerfile ├── lib │ ├── __init__.py │ └── tracing.py ├── README.md ├── requirements.txt └── server.py
/specialize
in server.py
from lib.tracing import initialize_tracing
…
@self.route('/specialize', methods=['POST'])
def load():
# load user function from codepath
userfunc = …
# Wrap userfunc with tracing instrumentation
self.userfunc = initialize_tracing(userfunc)
return ""
initialize_tracing
in lib/tracing.py
def initialize_tracing(func):
def inner():
…
func_resp = func()
return func_resp
return inner
Creating the tracer
object
def inner():
…
tracer = _init_tracer(fission_func_name)
…
return func_resp
Starting the trace event using with
block
def inner():
…
with tracer.start_span(span_name, child_of=span_ctx) as span:
…
func_resp = func()
return func_resp
Spans of greeter function
Spans of image function
extract
operationIncoming request to the function
… trace-ctx: 1234abcd:5678
tracer.extract()
tracer.start_span()
inject
operationtracer.inject()
g
extract
and inject
flow
tracing.py
def inner():
…
span_ctx = tracer.extract(Format.HTTP_HEADERS, request.headers)
with tracer.start_span(span_name, child_of=span_ctx) as span:
…
generated_headers = dict()
tracer.inject(span, Format.HTTP_HEADERS, generated_headers)
# User may want to set tags on span or use the generated_headers
g.span = span
g.generated_headers = generated_headers
…
func_resp = func()
# Add headers from generated_headers to response
…
return resp
More about MQT of Fission
FOLLOWS_FROM
reference instead CHILD_OF
––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time [-Parent Span--------------] [-Child Span A----] [-Child Span B----] [-Parent Span-] [-Child Span-]
Diagram credits: OpenTracing Specification. Apache License 2.0
jaeger-client-python
tracing.py
span_ctx = tracer.extract(Format.HTTP_HEADERS, request.headers)
# passing it as reference instead of child_of relation as we
# have async calls to services
span_reference = follows_from(referenced_context=span_ctx)
with tracer.start_span(span_name, references=span_reference) as span:
…
return response
tracer.close()
from jaeger-client-python
tracer.close()
is not fully synchronousFOLLOWS_FROM
referencebhavin192[at]geeksocket.in
These slides are released publicly under
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)