Hi Folks!
I am trying to create a small example migrating a “non-istio” app that is already using jaeger to istio.
from flask import Flask
from jaeger_client import Config
import logging
from flask_opentracing import FlaskTracer
from opentracing_instrumentation.client_hooks import install_all_patches
from opentracing_instrumentation.request_context import RequestContextManager
import requests
def init_tracer(service):
logging.getLogger('').handlers = []
logging.basicConfig(format='%(message)s', level=logging.DEBUG)
config = Config(
config={ # usually read from some yaml config
'sampler': {'type': 'const', 'param': 1, },
'logging': True,
'reporter_batch_size': 1,
},
service_name=service,
)
return config.initialize_tracer()
app = Flask(__name__)
tracer = init_tracer('frontend')
flask_tracer = FlaskTracer(tracer, True, app, ['url','url_rule','method','path','environ.HTTP_X_REAL_IP'])
@app.route("/")
def frontend():
with RequestContextManager(span=flask_tracer.get_span()):
requests.get('http://backend:8083/backend')
requests.get('http://meaning:8084/meaning')
return 'frontend'
install_all_patches()
if __name__ == "__main__":
app.run(port=8082, debug=True)
The example above works using Jaeger, but if I do use Istio it doesn’t get my span tags and it is not grouping these calls.
I understand that the “productpage” example uses only the B3 headers to generate the grouping… If I try to update my example following the “productpage” recommendation it does group my requests, but it is not linking to istio-ingressgateway creatinga “trace-without-root-span”:
The code updated:
from flask import Flask, request
import requests
#Tracing Istio
from flask import _request_ctx_stack as stack
from jaeger_client import Tracer, ConstSampler
from opentracing.propagation import Format
from jaeger_client.reporter import NullReporter
from jaeger_client.codecs import B3Codec
from opentracing.ext import tags
from opentracing_instrumentation.request_context import get_current_span, span_in_context
try:
import http.client as http_client
except ImportError:
# Python 2
import httplib as http_client
http_client.HTTPConnection.debuglevel = 1
app = Flask(__name__)
tracer = Tracer(
one_span_per_rpc=True,
service_name='frontend',
reporter=NullReporter(),
sampler=ConstSampler(decision=True),
extra_codecs={Format.HTTP_HEADERS: B3Codec()}
)
def trace():
'''
Function decorator that creates opentracing span from incoming b3 headers
'''
def decorator(f):
def wrapper(*args, **kwargs):
request = stack.top.request
try:
# Create a new span context, reading in values (traceid,
# spanid, etc) from the incoming x-b3-*** headers.
span_ctx = tracer.extract(
Format.HTTP_HEADERS,
dict(request.headers)
)
# Note: this tag means that the span will *not* be
# a child span. It will use the incoming traceid and
# spanid. We do this to propagate the headers verbatim.
rpc_tag = {tags.SPAN_KIND: tags.SPAN_KIND_RPC_SERVER}
span = tracer.start_span(
operation_name='op', child_of=span_ctx, tags=rpc_tag
)
except Exception as e:
# We failed to create a context, possibly due to no
# incoming x-b3-*** headers. Start a fresh span.
# Note: This is a fallback only, and will create fresh headers,
# not propagate headers.
span = tracer.start_span('op')
with span_in_context(span):
r = f(*args, **kwargs)
return r
wrapper.__name__ = f.__name__
return wrapper
return decorator
def getForwardHeaders(request):
headers = {}
# x-b3-*** headers can be populated using the opentracing span
span = get_current_span()
carrier = {}
tracer.inject(
span_context=span.context,
format=Format.HTTP_HEADERS,
carrier=carrier)
headers.update(carrier)
incoming_headers = ['x-request-id']
for ihdr in incoming_headers:
val = request.headers.get(ihdr)
if val is not None:
headers[ihdr] = val
#print "incoming: "+ihdr+":"+val
return headers
@app.route("/")
@trace()
def frontend():
headers = getForwardHeaders(request)
requests.get('http://backend:8083/backend', headers=headers)
requests.get('http://meaning:8084/meaning', headers=headers)
return 'frontend v2 basic'
#install_all_patches()
if __name__ == "__main__":
print('frontend v2')
app.run(port=8082, debug=True)
Anybody could help me to convert my jaeger code to istio compatible?
Thanks in advance!
Tito