Code import
This commit is contained in:
186
venv/lib/python2.7/site-packages/eventlet/zipkin/api.py
Normal file
186
venv/lib/python2.7/site-packages/eventlet/zipkin/api.py
Normal file
@@ -0,0 +1,186 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
import socket
|
||||
import random
|
||||
|
||||
from eventlet.green import threading
|
||||
from eventlet.zipkin._thrift.zipkinCore import ttypes
|
||||
from eventlet.zipkin._thrift.zipkinCore.constants import SERVER_SEND
|
||||
|
||||
|
||||
client = None
|
||||
_tls = threading.local() # thread local storage
|
||||
|
||||
|
||||
def put_annotation(msg, endpoint=None):
|
||||
""" This is annotation API.
|
||||
You can add your own annotation from in your code.
|
||||
Annotation is recorded with timestamp automatically.
|
||||
e.g.) put_annotation('cache hit for %s' % request)
|
||||
|
||||
:param msg: String message
|
||||
:param endpoint: host info
|
||||
"""
|
||||
if is_sample():
|
||||
a = ZipkinDataBuilder.build_annotation(msg, endpoint)
|
||||
trace_data = get_trace_data()
|
||||
trace_data.add_annotation(a)
|
||||
|
||||
|
||||
def put_key_value(key, value, endpoint=None):
|
||||
""" This is binary annotation API.
|
||||
You can add your own key-value extra information from in your code.
|
||||
Key-value doesn't have a time component.
|
||||
e.g.) put_key_value('http.uri', '/hoge/index.html')
|
||||
|
||||
:param key: String
|
||||
:param value: String
|
||||
:param endpoint: host info
|
||||
"""
|
||||
if is_sample():
|
||||
b = ZipkinDataBuilder.build_binary_annotation(key, value, endpoint)
|
||||
trace_data = get_trace_data()
|
||||
trace_data.add_binary_annotation(b)
|
||||
|
||||
|
||||
def is_tracing():
|
||||
""" Return whether the current thread is tracking or not """
|
||||
return hasattr(_tls, 'trace_data')
|
||||
|
||||
|
||||
def is_sample():
|
||||
""" Return whether it should record trace information
|
||||
for the request or not
|
||||
"""
|
||||
return is_tracing() and _tls.trace_data.sampled
|
||||
|
||||
|
||||
def get_trace_data():
|
||||
if is_tracing():
|
||||
return _tls.trace_data
|
||||
|
||||
|
||||
def set_trace_data(trace_data):
|
||||
_tls.trace_data = trace_data
|
||||
|
||||
|
||||
def init_trace_data():
|
||||
if is_tracing():
|
||||
del _tls.trace_data
|
||||
|
||||
|
||||
def _uniq_id():
|
||||
"""
|
||||
Create a random 64-bit signed integer appropriate
|
||||
for use as trace and span IDs.
|
||||
XXX: By experimentation zipkin has trouble recording traces with ids
|
||||
larger than (2 ** 56) - 1
|
||||
"""
|
||||
return random.randint(0, (2 ** 56) - 1)
|
||||
|
||||
|
||||
def generate_trace_id():
|
||||
return _uniq_id()
|
||||
|
||||
|
||||
def generate_span_id():
|
||||
return _uniq_id()
|
||||
|
||||
|
||||
class TraceData(object):
|
||||
|
||||
END_ANNOTATION = SERVER_SEND
|
||||
|
||||
def __init__(self, name, trace_id, span_id, parent_id, sampled, endpoint):
|
||||
"""
|
||||
:param name: RPC name (String)
|
||||
:param trace_id: int
|
||||
:param span_id: int
|
||||
:param parent_id: int or None
|
||||
:param sampled: lets the downstream servers know
|
||||
if I should record trace data for the request (bool)
|
||||
:param endpoint: zipkin._thrift.zipkinCore.ttypes.EndPoint
|
||||
"""
|
||||
self.name = name
|
||||
self.trace_id = trace_id
|
||||
self.span_id = span_id
|
||||
self.parent_id = parent_id
|
||||
self.sampled = sampled
|
||||
self.endpoint = endpoint
|
||||
self.annotations = []
|
||||
self.bannotations = []
|
||||
self._done = False
|
||||
|
||||
def add_annotation(self, annotation):
|
||||
if annotation.host is None:
|
||||
annotation.host = self.endpoint
|
||||
if not self._done:
|
||||
self.annotations.append(annotation)
|
||||
if annotation.value == self.END_ANNOTATION:
|
||||
self.flush()
|
||||
|
||||
def add_binary_annotation(self, bannotation):
|
||||
if bannotation.host is None:
|
||||
bannotation.host = self.endpoint
|
||||
if not self._done:
|
||||
self.bannotations.append(bannotation)
|
||||
|
||||
def flush(self):
|
||||
span = ZipkinDataBuilder.build_span(name=self.name,
|
||||
trace_id=self.trace_id,
|
||||
span_id=self.span_id,
|
||||
parent_id=self.parent_id,
|
||||
annotations=self.annotations,
|
||||
bannotations=self.bannotations)
|
||||
client.send_to_collector(span)
|
||||
self.annotations = []
|
||||
self.bannotations = []
|
||||
self._done = True
|
||||
|
||||
|
||||
class ZipkinDataBuilder:
|
||||
@staticmethod
|
||||
def build_span(name, trace_id, span_id, parent_id,
|
||||
annotations, bannotations):
|
||||
return ttypes.Span(
|
||||
name=name,
|
||||
trace_id=trace_id,
|
||||
id=span_id,
|
||||
parent_id=parent_id,
|
||||
annotations=annotations,
|
||||
binary_annotations=bannotations
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def build_annotation(value, endpoint=None):
|
||||
if isinstance(value, unicode):
|
||||
value = value.encode('utf-8')
|
||||
return ttypes.Annotation(time.time() * 1000 * 1000,
|
||||
str(value), endpoint)
|
||||
|
||||
@staticmethod
|
||||
def build_binary_annotation(key, value, endpoint=None):
|
||||
annotation_type = ttypes.AnnotationType.STRING
|
||||
return ttypes.BinaryAnnotation(key, value, annotation_type, endpoint)
|
||||
|
||||
@staticmethod
|
||||
def build_endpoint(ipv4=None, port=None, service_name=None):
|
||||
if ipv4 is not None:
|
||||
ipv4 = ZipkinDataBuilder._ipv4_to_int(ipv4)
|
||||
if service_name is None:
|
||||
service_name = ZipkinDataBuilder._get_script_name()
|
||||
return ttypes.Endpoint(
|
||||
ipv4=ipv4,
|
||||
port=port,
|
||||
service_name=service_name
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _ipv4_to_int(ipv4):
|
||||
return struct.unpack('!i', socket.inet_aton(ipv4))[0]
|
||||
|
||||
@staticmethod
|
||||
def _get_script_name():
|
||||
return os.path.basename(sys.argv[0])
|
||||
Reference in New Issue
Block a user