├── babeltrace-plugins ├── .gitignore ├── zipkin │ ├── src │ │ ├── zipkin_logic │ │ │ ├── __init__.py │ │ │ ├── zipkin_client.py │ │ │ ├── formatters.py │ │ │ ├── trace.py │ │ │ └── ttypes.py │ │ └── babeltrace_zipkin.py │ ├── README.md │ └── zipkin_trace.h ├── scribe_client │ ├── __init__.py │ └── scribe_client.py └── json │ ├── README.md │ └── src │ └── babeltrace_json.py ├── CMakeLists.txt ├── blkin-lib ├── CMakeLists.txt ├── Makefile ├── zipkin_trace.h ├── ztracer.hpp ├── zipkin_c.cc └── zipkin_c.h ├── COPYRIGHT ├── cmake └── modules │ └── FindLTTng.cmake └── README.md /babeltrace-plugins/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /babeltrace-plugins/scribe_client/__init__.py: -------------------------------------------------------------------------------- 1 | from scribe_client import * 2 | -------------------------------------------------------------------------------- /babeltrace-plugins/json/README.md: -------------------------------------------------------------------------------- 1 | babeltrace-json plugin 2 | ======================== 3 | 4 | This plugin enables us to send LTTng trace data to a Scribe server in a valid 5 | json format 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.11) 2 | 3 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") 4 | find_package(LTTng REQUIRED) 5 | 6 | # make && make test 7 | enable_testing() 8 | 9 | add_subdirectory(blkin-lib) 10 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/README.md: -------------------------------------------------------------------------------- 1 | babeltrace-zipkin plugin 2 | ======================== 3 | 4 | In order to use this plugin, the traces created by LTTng should follow a 5 | specific format. This format is provided in zipkin_trace.h file. If this 6 | format is not followed the traces will be dropped. 7 | -------------------------------------------------------------------------------- /blkin-lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(.) 2 | 3 | #blkin 4 | set(blkin_srcs 5 | zipkin_c.cc 6 | ) 7 | add_library(blkin ${blkin_srcs}) 8 | set_target_properties(blkin PROPERTIES POSITION_INDEPENDENT_CODE ON) 9 | target_link_libraries(blkin dl) 10 | add_dependencies(blkin zipkin-tp) 11 | set(blkin_headers 12 | zipkin_c.h 13 | zipkin_trace.h 14 | ztracer.hpp 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /babeltrace-plugins/scribe_client/scribe_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # scribe_client.py 3 | 4 | from scribe import scribe 5 | from thrift.transport import TTransport, TSocket 6 | from thrift.protocol import TBinaryProtocol 7 | 8 | class ScribeClient(object): 9 | 10 | def __init__(self, port, host): 11 | print host 12 | self.port = port 13 | self.host = host 14 | self.openConnection() 15 | 16 | def openConnection(self): 17 | socket = TSocket.TSocket(host=self.host, port=self.port) 18 | self.transport = TTransport.TFramedTransport(socket) 19 | protocol = TBinaryProtocol.TBinaryProtocol(trans=self.transport, 20 | strictRead=False, 21 | strictWrite=False) 22 | self.client = scribe.Client(protocol) 23 | self.transport.open() 24 | 25 | def log(self, category, message): 26 | log_entry = scribe.LogEntry(category, message) 27 | result = self.client.Log(messages=[log_entry]) 28 | return result # 0 for success 29 | 30 | def close(self): 31 | self.transport.close() 32 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 2014 Marios Kogias 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or 5 | without modification, are permitted provided that the following 6 | conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above 9 | copyright notice, this list of conditions and the following 10 | disclaimer. 11 | 2. Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials 14 | provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS 17 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/babeltrace_zipkin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # babeltrace_zipkin.py 3 | 4 | import sys 5 | sys.path.append("../../babeltrace-plugins") 6 | import sys 7 | import getopt 8 | from babeltrace import * 9 | from zipkin_logic.zipkin_client import ZipkinClient 10 | HELP = "Usage: python babeltrace_zipkin.py path/to/trace -s -p " 11 | 12 | 13 | def main(argv): 14 | try: 15 | path = argv[0] 16 | except: 17 | raise TypeError(HELP) 18 | 19 | try: 20 | opts, args = getopt.getopt(argv[1:], "hs:p:") 21 | except getopt.GetoptError: 22 | raise TypeError(HELP) 23 | 24 | server = None 25 | port = None 26 | for opt, arg in opts: 27 | if opt == '-h': 28 | raise TypeError(HELP) 29 | elif opt == '-s': 30 | server = arg 31 | elif opt == '-p': 32 | port = arg 33 | 34 | if not server: 35 | server = "83.212.113.88" 36 | if not port: 37 | port = 1463 38 | 39 | # Open connection with scribe 40 | zipkin = ZipkinClient(port, server) 41 | 42 | # Create TraceCollection and add trace: 43 | traces = TraceCollection() 44 | trace_handle = traces.add_trace(path, "ctf") 45 | if trace_handle is None: 46 | raise IOError("Error adding trace") 47 | 48 | for event in traces.events: 49 | name = event.name 50 | provider, kind = name.split(":") 51 | if provider != "zipkin": 52 | continue 53 | 54 | #create a zipkin trace from event info 55 | trace = zipkin.create_trace(event) 56 | 57 | #create a zipkin annotation from event info 58 | annotation = zipkin.create_annotation(event, kind) 59 | 60 | #record the trace 61 | zipkin.record(trace, annotation) 62 | 63 | zipkin.close() 64 | 65 | if __name__ == "__main__": 66 | main(sys.argv[1:]) 67 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/zipkin_trace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Zipkin lttng-ust tracepoint provider. 3 | */ 4 | 5 | #undef TRACEPOINT_PROVIDER 6 | #define TRACEPOINT_PROVIDER zipkin 7 | 8 | #undef TRACEPOINT_INCLUDE 9 | #define TRACEPOINT_INCLUDE "./zipkin_trace.h" 10 | 11 | #if !defined(_ZIPKIN_H) || defined(TRACEPOINT_HEADER_MULTI_READ) 12 | #define _ZIPKIN_H 13 | 14 | #include 15 | 16 | TRACEPOINT_EVENT( 17 | zipkin, 18 | keyval, 19 | TP_ARGS(char *, service, char *, trace_name, 20 | int, port, char *, ip, long, trace, 21 | long, span, long, parent_span, 22 | char *, key, char *, val ), 23 | 24 | TP_FIELDS( 25 | ctf_string(trace_name, trace_name) 26 | ctf_string(service_name, service) 27 | ctf_integer(int, port_no, port) 28 | ctf_string(ip, ip) 29 | ctf_integer(long, trace_id, trace) 30 | ctf_integer(long, span_id, span) 31 | ctf_integer(long, parent_span_id, parent_span) 32 | ctf_string(key, key) 33 | ctf_string(val, val) 34 | ) 35 | ) 36 | TRACEPOINT_LOGLEVEL( 37 | zipkin, 38 | keyval, 39 | TRACE_WARNING) 40 | 41 | 42 | TRACEPOINT_EVENT( 43 | zipkin, 44 | timestamp, 45 | TP_ARGS(char *, service, char *, trace_name, 46 | int, port, char *, ip, long, trace, 47 | long, span, long, parent_span, 48 | char *, event), 49 | 50 | TP_FIELDS( 51 | ctf_string(trace_name, trace_name) 52 | ctf_string(service_name, service) 53 | ctf_integer(int, port_no, port) 54 | ctf_string(ip, ip) 55 | ctf_integer(long, trace_id, trace) 56 | ctf_integer(long, span_id, span) 57 | ctf_integer(long, parent_span_id, parent_span) 58 | ctf_string(event, event) 59 | ) 60 | ) 61 | TRACEPOINT_LOGLEVEL( 62 | zipkin, 63 | timestamp, 64 | TRACE_WARNING) 65 | #endif /* _ZIPKIN_H */ 66 | 67 | #include 68 | -------------------------------------------------------------------------------- /cmake/modules/FindLTTng.cmake: -------------------------------------------------------------------------------- 1 | # - Find LTTng 2 | # Find the Linux Trace Toolkit - next generation with associated includes path. 3 | # See http://lttng.org/ 4 | # 5 | # This module accepts the following optional variables: 6 | # LTTNG_PATH_HINT = A hint on LTTNG install path. 7 | # 8 | # This module defines the following variables: 9 | # LTTNG_FOUND = Was LTTng found or not? 10 | # LTTNG_EXECUTABLE = The path to lttng command 11 | # LTTNG_LIBRARIES = The list of libraries to link to when using LTTng 12 | # LTTNG_INCLUDE_DIR = The path to LTTng include directory 13 | # 14 | # On can set LTTNG_PATH_HINT before using find_package(LTTng) and the 15 | # module with use the PATH as a hint to find LTTng. 16 | # 17 | # The hint can be given on the command line too: 18 | # cmake -DLTTNG_PATH_HINT=/DATA/ERIC/LTTng /path/to/source 19 | 20 | find_package(PkgConfig) 21 | pkg_check_modules(PC_LTTNG QUIET lttng-ust) 22 | 23 | find_path(LTTNG_INCLUDE_DIR 24 | NAMES lttng/tracepoint.h 25 | HINTS ${PC_LTTNG_INCLUDEDIR} ${PC_LTTNG_INCLUDE_DIRS} 26 | PATH_SUFFIXES include 27 | DOC "The LTTng include headers") 28 | 29 | find_path(LTTNG_LIBRARY_DIR 30 | NAMES liblttng-ust.so 31 | HINTS ${PC_LTTNG_LIBDIR} ${PC_LTTNG_LIBRARY_DIRS} 32 | DOC "The LTTng libraries") 33 | 34 | find_library(LTTNG_UST_LIBRARY lttng-ust PATHS ${LTTNG_LIBRARY_DIR}) 35 | find_library(URCU_LIBRARY urcu-bp PATHS ${LTTNG_LIBRARY_DIR}) 36 | find_library(UUID_LIBRARY uuid) 37 | 38 | set(LTTNG_LIBRARIES ${LTTNG_UST_LIBRARY} ${URCU_LIBRARY} ${UUID_LIBRARY}) 39 | 40 | message(STATUS "Looking for lttng executable...") 41 | set(LTTNG_NAMES "lttng;lttng-ctl") 42 | # FIND_PROGRAM twice using NO_DEFAULT_PATH on first shot 43 | find_program(LTTNG_EXECUTABLE 44 | NAMES ${LTTNG_NAMES} 45 | PATHS ${LTTNG_PATH_HINT}/bin 46 | NO_DEFAULT_PATH 47 | DOC "The LTTNG command line tool") 48 | find_program(LTTNG_PROGRAM 49 | NAMES ${LTTNG_NAMES} 50 | PATHS ${LTTNG_PATH_HINT}/bin 51 | DOC "The LTTNG command line tool") 52 | 53 | # handle the QUIETLY and REQUIRED arguments and set LTTNG_FOUND to TRUE if 54 | # all listed variables are TRUE 55 | include(FindPackageHandleStandardArgs) 56 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LTTNG DEFAULT_MSG LTTNG_INCLUDE_DIR LTTNG_LIBRARY_DIR) 57 | if (NOT LTTNG_FOUND) 58 | if (LTTng_FIND_REQUIRED) 59 | message(FATAL_ERROR "LTTng not found") 60 | endif () 61 | endif () 62 | 63 | mark_as_advanced(LTTNG_INCLUDE_DIR) 64 | mark_as_advanced(LTTNG_LIBRARY_DIR) 65 | -------------------------------------------------------------------------------- /blkin-lib/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Marios Kogias 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or 5 | # without modification, are permitted provided that the following 6 | # conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above 9 | # copyright notice, this list of conditions and the following 10 | # disclaimer. 11 | # 2. Redistributions in binary form must reproduce the above 12 | # copyright notice, this list of conditions and the following 13 | # disclaimer in the documentation and/or other materials 14 | # provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS 17 | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | # POSSIBILITY OF SUCH DAMAGE. 28 | 29 | .PHONY: default clean distclean 30 | 31 | MAJOR=0 32 | MINOR=1 33 | LIBS= -ldl -llttng-ust 34 | DLIB=libblkin 35 | 36 | LIB_DIR=$(shell pwd) 37 | prefix= /usr/local 38 | libdir= $(prefix)/lib 39 | incdir= $(prefix)/include 40 | 41 | H_FILES= zipkin_c.h zipkin_trace.h ztracer.hpp 42 | 43 | default: $(DLIB).so 44 | 45 | $(DLIB).so: $(DLIB).$(MAJOR).so 46 | ln -sf $< $@ 47 | 48 | $(DLIB).$(MAJOR).so: $(DLIB).$(MAJOR).$(MINOR).so 49 | ln -sf $< $@ 50 | 51 | $(DLIB).$(MAJOR).$(MINOR).so: zipkin_c.o tp.o 52 | g++ -shared -o $@ $^ $(LIBS) 53 | 54 | zipkin_c.o: zipkin_c.c zipkin_c.h zipkin_trace.h 55 | gcc -I. -Wall -fpic -g -c -o $@ $< 56 | 57 | tp.o: tp.c zipkin_trace.h 58 | gcc -I. -fpic -g -c -o $@ $< 59 | 60 | install: 61 | install -m 644 $(DLIB).$(MAJOR).$(MINOR).so $(DESTDIR)/$(libdir) 62 | cp -P $(DLIB).$(MAJOR).so $(DESTDIR)/$(libdir) 63 | cp -P $(DLIB).so $(DESTDIR)/$(libdir) 64 | install -m 644 $(H_FILES) $(DESTDIR)/$(incdir) 65 | 66 | clean: 67 | rm -f *.o *.so 68 | make -C clean 69 | 70 | distclean: clean 71 | rm -f socket 72 | -------------------------------------------------------------------------------- /babeltrace-plugins/json/src/babeltrace_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # babeltrace_zipkin.py 3 | 4 | import sys 5 | sys.path.append("../../babeltrace-plugins") 6 | import json 7 | import getopt 8 | from babeltrace import * 9 | from scribe_client import ScribeClient 10 | 11 | HELP = "Usage: python babeltrace_zipkin.py path/to/trace -s -p " 12 | CATEGORY = "LTTng" 13 | 14 | 15 | def main(argv): 16 | try: 17 | path = argv[0] 18 | except: 19 | raise TypeError(HELP) 20 | 21 | try: 22 | opts, args = getopt.getopt(argv[1:], "hs:p:") 23 | except getopt.GetoptError: 24 | raise TypeError(HELP) 25 | 26 | server = None 27 | port = None 28 | for opt, arg in opts: 29 | if opt == '-h': 30 | raise TypeError(HELP) 31 | elif opt == '-s': 32 | server = arg 33 | elif opt == '-p': 34 | port = arg 35 | 36 | if not server: 37 | server = "localhost" 38 | if not port: 39 | port = 1463 40 | 41 | # Open connection with scribe 42 | scribe_client = ScribeClient(port, server) 43 | 44 | # Create TraceCollection and add trace: 45 | traces = TraceCollection() 46 | trace_handle = traces.add_trace(path, "ctf") 47 | if trace_handle is None: 48 | raise IOError("Error adding trace") 49 | 50 | #iterate over events 51 | for event in traces.events: 52 | data = dict() 53 | 54 | data["parent_span_id"]= event["parent_span_id"] 55 | data['name'] = event["trace_name"] 56 | data ["trace_id"] = event["trace_id"] 57 | data["span_id"] = event["span_id"] 58 | data['port'] = event['port_no'] 59 | data['service_name'] = event['service_name'] 60 | data['ip'] = event['ip'] 61 | data['event'] = event['event'] 62 | data['timestamp'] = event.timestamp 63 | ''' 64 | for k, v in event.items(): 65 | field_type = event._field(k).type 66 | data[k] = format_value(field_type, v) 67 | ''' 68 | json_data = json.dumps(data) 69 | 70 | #send data to scribe 71 | scribe_client.log(CATEGORY, json_data) 72 | 73 | scribe_client.close() 74 | 75 | 76 | def format_value(field_type, value): 77 | 78 | if field_type == 1: 79 | return int(value) 80 | elif field_type == 2: 81 | return float(value) 82 | elif field_type == 8: 83 | return [x for x in value] 84 | else: 85 | return str(value) 86 | 87 | if __name__ == "__main__": 88 | main(sys.argv[1:]) 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blkin 2 | 3 | Blkin is a project that allows you to trace applications with LTTng following 4 | the tracing semantics described in Google's [Dapper 5 | Paper](http://static.googleusercontent.com/media/research.google.com/el//pubs/archive/36356.pdf). 6 | 7 | According to this paper, the logged information is called `Annotation`, and 8 | belongs to a specific span and trace. Each trace is comprised of multiple spans 9 | which are related with each other with causal relationships. The Blkin 10 | library gives the user the API to easily instrument C/C++ applications according 11 | to the Dapper specification. In order to instrument applications, you should take 12 | a look at ``blkin-lib/tests`` for some testcases and at the ``blkin-lib/zipkin_c.h`` 13 | file. 14 | 15 | Blkin uses LTTng as a tracing backend, so you must have LTTng installed. 16 | 17 | In order to build and install the Blkin library, go to ``blkin-lib`` folder and run: 18 | 19 | ``` 20 | cmake . 21 | make 22 | make install 23 | ``` 24 | 25 | You should take a look at the examples to find out how to link the blkin lib 26 | with your instrumented application. 27 | 28 | In order to visualize the aggregated information you can use Twitter's 29 | [Zipkin](http://twitter.github.io/zipkin/) and send the data that you created 30 | by running the equivalent babeltrace plugin. In order to do so, you can run: 31 | 32 | ``` 33 | $> ./zipkin/src/babeltrace_zipkin.py -s -p 34 | ``` 35 | 36 | within the babeltrace-plugins directory. Note that you'll need `facebook-scribe` 37 | and `python-thrift` installed. 38 | 39 | In case you have not used the blkin-lib to instrument your application, you can 40 | still send your data to a Scribe server. To do so, you can use another 41 | Babeltrace plugin. This plugin tranforms LTTng trace data to a JSON format and 42 | sends them to a Scribe sever. In order to do so, you can run: 43 | 44 | ``` 45 | $> ./json/src/babeltrace_json.py -s -p 46 | ``` 47 | within the babeltrace-plugins directory. 48 | 49 | You might need to [enable Scribe support](https://github.com/openzipkin/docker-zipkin/blob/master/docker-compose.yml) in Zipkin. 50 | 51 | Both of these plugins require that you have installed Babeltrace with its 52 | Python bindings enabled, which is not the case with the packages provided by many 53 | Linux distributions (see [here](http://diamon.org/babeltrace/docs/python/) for more details). The path to the lttng traces should not be the root 54 | directory but the directory where the channel directories are included. 55 | 56 | ## Dependencies 57 | 58 | * libboost-all-dev 59 | * lttng-tools 60 | 61 | Note that Blkin is tested only with LTTng2.4 62 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/zipkin_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | sys.path.append('.') 5 | from scribe_client import ScribeClient 6 | from trace import Annotation, Trace, Endpoint 7 | from collections import defaultdict 8 | from formatters import base64_thrift_formatter 9 | 10 | 11 | class ZipkinClient(ScribeClient): 12 | 13 | DEFAULT_END_ANNOTATIONS = ("ss", "cr", "end") 14 | 15 | def __init__(self, port, host): 16 | super(ZipkinClient, self).__init__(port, host) 17 | self._annotations_for_trace = defaultdict(list) 18 | 19 | def create_trace(self, event): 20 | service = event["trace_name"] 21 | trace_id = event["trace_id"] 22 | span_id = event["span_id"] 23 | parent_span = event["parent_span_id"] 24 | if parent_span == 0: 25 | parent_span = None 26 | trace = Trace(service, trace_id, span_id, parent_span) 27 | return trace 28 | 29 | def create_annotation(self, event, kind): 30 | if kind == "keyval_string": 31 | key = event["key"] 32 | val = event["val"] 33 | annotation = Annotation.string(key, val) 34 | elif kind == "keyval_integer": 35 | key = event["key"] 36 | val = str(event["val"]) 37 | annotation = Annotation.string(key, val) 38 | elif kind == "timestamp": 39 | timestamp = event.timestamp 40 | #timestamp has different digit length 41 | timestamp = str(timestamp) 42 | timestamp = timestamp[:-3] 43 | event_name = event["event"] 44 | annotation = Annotation.timestamp(event_name, int(timestamp)) 45 | 46 | # create and set endpoint 47 | port = event["port_no"] 48 | service = event["service_name"] 49 | ip = event["ip"] 50 | endpoint = Endpoint(ip, int(port), service) 51 | annotation.endpoint = endpoint 52 | 53 | print annotation 54 | return annotation 55 | 56 | def record(self, trace, annotation): 57 | self.scribe_log(trace, [annotation]) 58 | ''' 59 | trace_key = (trace.trace_id, trace.span_id) 60 | self._annotations_for_trace[trace_key].append(annotation) 61 | if (annotation.name in self.DEFAULT_END_ANNOTATIONS): 62 | saved_annotations = self._annotations_for_trace[trace_key] 63 | del self._annotations_for_trace[trace_key] 64 | self.scribe_log(trace, saved_annotations) 65 | print "Record event" 66 | ''' 67 | 68 | def scribe_log(self, trace, annotations): 69 | trace._endpoint = None 70 | message = base64_thrift_formatter(trace, annotations) 71 | category = 'zipkin' 72 | return self.log(category, message) 73 | -------------------------------------------------------------------------------- /blkin-lib/zipkin_trace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Zipkin lttng-ust tracepoint provider. 3 | */ 4 | 5 | #undef TRACEPOINT_PROVIDER 6 | #define TRACEPOINT_PROVIDER zipkin 7 | 8 | #undef TRACEPOINT_INCLUDE 9 | #define TRACEPOINT_INCLUDE "./zipkin_trace.h" 10 | 11 | #if !defined(_ZIPKIN_H) || defined(TRACEPOINT_HEADER_MULTI_READ) 12 | #define _ZIPKIN_H 13 | 14 | #include 15 | 16 | TRACEPOINT_EVENT( 17 | zipkin, 18 | keyval_string, 19 | TP_ARGS(const char *, trace_name, const char *, service, 20 | int, port, const char *, ip, long, trace, 21 | long, span, long, parent_span, 22 | const char *, key, const char *, val ), 23 | 24 | TP_FIELDS( 25 | /* 26 | * Each span has a name mentioned on it in the UI 27 | * This is the trace name 28 | */ 29 | ctf_string(trace_name, trace_name) 30 | /* 31 | * Each trace takes place in a specific machine-endpoint 32 | * This is identified by a name, a port number and an ip 33 | */ 34 | ctf_string(service_name, service) 35 | ctf_integer(int, port_no, port) 36 | ctf_string(ip, ip) 37 | /* 38 | * According to the tracing semantics each trace should have 39 | * a trace id, a span id and a parent span id 40 | */ 41 | ctf_integer(long, trace_id, trace) 42 | ctf_integer(long, span_id, span) 43 | ctf_integer(long, parent_span_id, parent_span) 44 | /* 45 | * The following is the real annotated information 46 | */ 47 | ctf_string(key, key) 48 | ctf_string(val, val) 49 | ) 50 | ) 51 | TRACEPOINT_LOGLEVEL( 52 | zipkin, 53 | keyval_string, 54 | TRACE_WARNING) 55 | 56 | /* 57 | * This tracepoint allows for integers to come out keyval 58 | */ 59 | 60 | TRACEPOINT_EVENT( 61 | zipkin, 62 | keyval_integer, 63 | TP_ARGS(const char *, trace_name, const char *, service, 64 | int, port, const char *, ip, long, trace, 65 | long, span, long, parent_span, 66 | const char *, key, int64_t, val ), 67 | 68 | TP_FIELDS( 69 | /* 70 | * Each span has a name mentioned on it in the UI 71 | * This is the trace name 72 | */ 73 | ctf_string(trace_name, trace_name) 74 | /* 75 | * Each trace takes place in a specific machine-endpoint 76 | * This is identified by a name, a port number and an ip 77 | */ 78 | ctf_string(service_name, service) 79 | ctf_integer(int, port_no, port) 80 | ctf_string(ip, ip) 81 | /* 82 | * According to the tracing semantics each trace should have 83 | * a trace id, a span id and a parent span id 84 | */ 85 | ctf_integer(long, trace_id, trace) 86 | ctf_integer(long, span_id, span) 87 | ctf_integer(long, parent_span_id, parent_span) 88 | /* 89 | * The following is the real annotated information 90 | */ 91 | ctf_string(key, key) 92 | ctf_integer(int64_t, val, val) 93 | ) 94 | ) 95 | TRACEPOINT_LOGLEVEL( 96 | zipkin, 97 | keyval_integer, 98 | TRACE_WARNING) 99 | /* 100 | * In this event we follow the same semantics but we trace timestamp 101 | * annotations 102 | */ 103 | 104 | TRACEPOINT_EVENT( 105 | zipkin, 106 | timestamp, 107 | TP_ARGS(const char *, trace_name, const char *, service, 108 | int, port, const char *, ip, long, trace, 109 | long, span, long, parent_span, 110 | const char *, event), 111 | 112 | TP_FIELDS( 113 | ctf_string(trace_name, trace_name) 114 | ctf_string(service_name, service) 115 | ctf_integer(int, port_no, port) 116 | ctf_string(ip, ip) 117 | ctf_integer(long, trace_id, trace) 118 | ctf_integer(long, span_id, span) 119 | ctf_integer(long, parent_span_id, parent_span) 120 | ctf_string(event, event) 121 | ) 122 | ) 123 | TRACEPOINT_LOGLEVEL( 124 | zipkin, 125 | timestamp, 126 | TRACE_WARNING) 127 | #endif /* _ZIPKIN_H */ 128 | 129 | #include 130 | 131 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/formatters.py: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Rackspace Hosting, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | import struct 17 | import socket 18 | 19 | from thrift.protocol import TBinaryProtocol 20 | from thrift.transport import TTransport 21 | 22 | import ttypes 23 | 24 | 25 | def hex_str(n): 26 | return '%0.16x' % (n,) 27 | 28 | 29 | def json_formatter(traces, *json_args, **json_kwargs): 30 | json_traces = [] 31 | 32 | for (trace, annotations) in traces: 33 | json_trace = { 34 | 'trace_id': hex_str(trace.trace_id), 35 | 'span_id': hex_str(trace.span_id), 36 | 'name': trace.name, 37 | 'annotations': [] 38 | } 39 | 40 | if trace.parent_span_id: 41 | json_trace['parent_span_id'] = hex_str(trace.parent_span_id) 42 | 43 | for annotation in annotations: 44 | json_annotation = { 45 | 'key': annotation.name, 46 | 'value': annotation.value, 47 | 'type': annotation.annotation_type 48 | } 49 | 50 | if annotation.endpoint: 51 | json_annotation['host'] = { 52 | 'ipv4': annotation.endpoint.ipv4, 53 | 'port': annotation.endpoint.port, 54 | 'service_name': annotation.endpoint.service_name 55 | } 56 | 57 | json_trace['annotations'].append(json_annotation) 58 | 59 | json_traces.append(json_trace) 60 | 61 | return json.dumps(json_traces, *json_args, **json_kwargs) 62 | 63 | 64 | def ipv4_to_int(ipv4): 65 | return struct.unpack('!i', socket.inet_aton(ipv4))[0] 66 | 67 | 68 | def base64_thrift(thrift_obj): 69 | trans = TTransport.TMemoryBuffer() 70 | tbp = TBinaryProtocol.TBinaryProtocol(trans) 71 | 72 | thrift_obj.write(tbp) 73 | res = trans.getvalue().encode('base64').strip() 74 | res = res.replace("\n","") 75 | #print res 76 | #print len(res) 77 | return res 78 | #return trans.getvalue().encode('base64').strip() 79 | 80 | 81 | def binary_annotation_formatter(annotation, host=None): 82 | annotation_types = { 83 | 'string': ttypes.AnnotationType.STRING, 84 | 'bytes': ttypes.AnnotationType.BYTES, 85 | } 86 | 87 | annotation_type = annotation_types[annotation.annotation_type] 88 | 89 | value = annotation.value 90 | 91 | if isinstance(value, unicode): 92 | value = value.encode('utf-8') 93 | 94 | return ttypes.BinaryAnnotation( 95 | annotation.name, 96 | value, 97 | annotation_type, 98 | host) 99 | 100 | 101 | def base64_thrift_formatter(trace, annotations): 102 | thrift_annotations = [] 103 | binary_annotations = [] 104 | 105 | for annotation in annotations: 106 | host = None 107 | if annotation.endpoint: 108 | host = ttypes.Endpoint( 109 | ipv4=ipv4_to_int(annotation.endpoint.ipv4), 110 | port=annotation.endpoint.port, 111 | service_name=annotation.endpoint.service_name) 112 | 113 | if annotation.annotation_type == 'timestamp': 114 | thrift_annotations.append(ttypes.Annotation( 115 | timestamp=annotation.value, 116 | value=annotation.name, 117 | host=host)) 118 | else: 119 | binary_annotations.append( 120 | binary_annotation_formatter(annotation, host)) 121 | 122 | thrift_trace = ttypes.Span( 123 | trace_id=trace.trace_id, 124 | name=trace.name, 125 | id=trace.span_id, 126 | parent_id=trace.parent_span_id, 127 | annotations=thrift_annotations, 128 | binary_annotations=binary_annotations 129 | ) 130 | 131 | return base64_thrift(thrift_trace) 132 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/trace.py: -------------------------------------------------------------------------------- 1 | import math 2 | import time 3 | import random 4 | 5 | 6 | class Trace(object): 7 | """ 8 | An L{ITrace} provider which delegates to zero or more L{ITracers} and 9 | allows setting a default L{IEndpoint} to associate with L{IAnnotation}s 10 | 11 | @ivar _tracers: C{list} of one or more L{ITracer} providers. 12 | @ivar _endpoint: An L{IEndpoint} provider. 13 | """ 14 | def __init__(self, name, trace_id=None, span_id=None, 15 | parent_span_id=None, tracers=None): 16 | """ 17 | @param name: C{str} describing the current span. 18 | @param trace_id: C{int} or C{None} 19 | @param span_id: C{int} or C{None} 20 | @param parent_span_id: C{int} or C{None} 21 | 22 | @param tracers: C{list} of L{ITracer} providers, primarily useful 23 | for unit testing. 24 | """ 25 | self.name = name 26 | # If no trace_id and span_id are given we want to generate new 27 | # 64-bit integer ids. 28 | self.trace_id = trace_id 29 | self.span_id = span_id 30 | 31 | # If no parent_span_id is given then we assume there is no parent span 32 | # and leave it as None. 33 | self.parent_span_id = parent_span_id 34 | 35 | # If no tracers are given we get the global list of tracers. 36 | self._tracers = tracers 37 | 38 | # By default no endpoint will be associated with annotations recorded 39 | # to this trace. 40 | self._endpoint = None 41 | 42 | def __ne__(self, other): 43 | return not self == other 44 | 45 | def __repr__(self): 46 | return ( 47 | '{0.__class__.__name__}({0.name!r}, trace_id={0.trace_id!r}, ' 48 | 'span_id={0.span_id!r}, parent_span_id={0.parent_span_id!r})' 49 | ).format(self) 50 | 51 | def set_endpoint(self, endpoint): 52 | """ 53 | Set a default L{IEndpoint} provider for the current L{Trace}. 54 | All annotations recorded after this endpoint is set will use it, 55 | unless they provide their own endpoint. 56 | """ 57 | self._endpoint = endpoint 58 | 59 | 60 | class Endpoint(object): 61 | 62 | def __init__(self, ipv4, port, service_name): 63 | """ 64 | @param ipv4: C{str} ipv4 address. 65 | @param port: C{int} port number. 66 | @param service_name: C{str} service name. 67 | """ 68 | self.ipv4 = ipv4 69 | self.port = port 70 | self.service_name = service_name 71 | 72 | def __ne__(self, other): 73 | return not self == other 74 | 75 | def __repr__(self): 76 | return ('{0.__class__.__name__}({0.ipv4!r}, {0.port!r}, ' 77 | '{0.service_name!r})').format(self) 78 | 79 | 80 | class Annotation(object): 81 | 82 | def __init__(self, name, value, annotation_type, endpoint=None): 83 | """ 84 | @param name: C{str} name of this annotation. 85 | 86 | @param value: A value of the appropriate type based on 87 | C{annotation_type}. 88 | 89 | @param annotation_type: C{str} the expected type of our C{value}. 90 | 91 | @param endpoint: An optional L{IEndpoint} provider to associate with 92 | this annotation or C{None} 93 | """ 94 | self.name = name 95 | self.value = value 96 | self.annotation_type = annotation_type 97 | self.endpoint = endpoint 98 | 99 | def __ne__(self, other): 100 | return not self == other 101 | 102 | def __repr__(self): 103 | return ( 104 | '{0.__class__.__name__}({0.name!r}, {0.value!r}, ' 105 | '{0.annotation_type!r}, {0.endpoint})' 106 | ).format(self) 107 | 108 | @classmethod 109 | def timestamp(cls, name, timestamp=None): 110 | if timestamp is None: 111 | timestamp = math.trunc(time.time() * 1000 * 1000) 112 | 113 | return cls(name, timestamp, 'timestamp') 114 | 115 | @classmethod 116 | def client_send(cls, timestamp=None): 117 | return cls.timestamp(constants.CLIENT_SEND, timestamp) 118 | 119 | @classmethod 120 | def client_recv(cls, timestamp=None): 121 | return cls.timestamp(constants.CLIENT_RECV, timestamp) 122 | 123 | @classmethod 124 | def server_send(cls, timestamp=None): 125 | return cls.timestamp(constants.SERVER_SEND, timestamp) 126 | 127 | @classmethod 128 | def server_recv(cls, timestamp=None): 129 | return cls.timestamp(constants.SERVER_RECV, timestamp) 130 | 131 | @classmethod 132 | def string(cls, name, value): 133 | return cls(name, value, 'string') 134 | 135 | @classmethod 136 | def bytes(cls, name, value): 137 | return cls(name, value, 'bytes') 138 | -------------------------------------------------------------------------------- /blkin-lib/ztracer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Marios Kogias 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or 6 | * without modification, are permitted provided that the following 7 | * conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials 15 | * provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 24 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ZTRACER_H 31 | 32 | #define ZTRACER_H 33 | 34 | #include 35 | #include 36 | 37 | namespace ZTracer { 38 | using std::string; 39 | 40 | const char* const CLIENT_SEND = "cs"; 41 | const char* const CLIENT_RECV = "cr"; 42 | const char* const SERVER_SEND = "ss"; 43 | const char* const SERVER_RECV = "sr"; 44 | const char* const WIRE_SEND = "ws"; 45 | const char* const WIRE_RECV = "wr"; 46 | const char* const CLIENT_SEND_FRAGMENT = "csf"; 47 | const char* const CLIENT_RECV_FRAGMENT = "crf"; 48 | const char* const SERVER_SEND_FRAGMENT = "ssf"; 49 | const char* const SERVER_RECV_FRAGMENT = "srf"; 50 | 51 | static inline int ztrace_init() { return blkin_init(); } 52 | 53 | class Endpoint : private blkin_endpoint { 54 | private: 55 | string _ip; // storage for blkin_endpoint.ip, see copy_ip() 56 | string _name; // storage for blkin_endpoint.name, see copy_name() 57 | 58 | friend class Trace; 59 | public: 60 | Endpoint(const char *name) 61 | { 62 | blkin_init_endpoint(this, "0.0.0.0", 0, name); 63 | } 64 | Endpoint(const char *ip, int port, const char *name) 65 | { 66 | blkin_init_endpoint(this, ip, port, name); 67 | } 68 | 69 | // copy constructor and operator need to account for ip/name storage 70 | Endpoint(const Endpoint &rhs) : _ip(rhs._ip), _name(rhs._name) 71 | { 72 | blkin_init_endpoint(this, _ip.size() ? _ip.c_str() : rhs.ip, 73 | rhs.port, 74 | _name.size() ? _name.c_str(): rhs.name); 75 | } 76 | const Endpoint& operator=(const Endpoint &rhs) 77 | { 78 | _ip.assign(rhs._ip); 79 | _name.assign(rhs._name); 80 | blkin_init_endpoint(this, _ip.size() ? _ip.c_str() : rhs.ip, 81 | rhs.port, 82 | _name.size() ? _name.c_str() : rhs.name); 83 | return *this; 84 | } 85 | 86 | // Endpoint assumes that ip and name will be string literals, and 87 | // avoids making a copy and freeing on destruction. if you need to 88 | // initialize Endpoint with a temporary string, copy_ip/copy_name() 89 | // will store it in a std::string and assign from that 90 | void copy_ip(const string &newip) 91 | { 92 | _ip.assign(newip); 93 | ip = _ip.c_str(); 94 | } 95 | void copy_name(const string &newname) 96 | { 97 | _name.assign(newname); 98 | name = _name.c_str(); 99 | } 100 | 101 | void copy_address_from(const Endpoint *endpoint) 102 | { 103 | _ip.assign(endpoint->ip); 104 | ip = _ip.c_str(); 105 | port = endpoint->port; 106 | } 107 | void share_address_from(const Endpoint *endpoint) 108 | { 109 | ip = endpoint->ip; 110 | port = endpoint->port; 111 | } 112 | void set_port(int p) { port = p; } 113 | }; 114 | 115 | class Trace : private blkin_trace { 116 | private: 117 | string _name; // storage for blkin_trace.name, see copy_name() 118 | 119 | public: 120 | // default constructor zero-initializes blkin_trace valid() 121 | // will return false on a default-constructed Trace until 122 | // init() 123 | Trace() 124 | { 125 | // zero-initialize so valid() returns false 126 | name = NULL; 127 | info.trace_id = 0; 128 | info.span_id = 0; 129 | info.parent_span_id = 0; 130 | endpoint = NULL; 131 | } 132 | 133 | // construct a Trace with an optional parent 134 | Trace(const char *name, const Endpoint *ep, const Trace *parent = NULL) 135 | { 136 | if (parent && parent->valid()) { 137 | blkin_init_child(this, parent, ep ? : parent->endpoint, 138 | name); 139 | } else { 140 | blkin_init_new_trace(this, name, ep); 141 | } 142 | } 143 | 144 | // construct a Trace from blkin_trace_info 145 | Trace(const char *name, const Endpoint *ep, 146 | const blkin_trace_info *i, bool child=false) 147 | { 148 | if (child) 149 | blkin_init_child_info(this, i, ep, name); 150 | else { 151 | blkin_init_new_trace(this, name, ep); 152 | set_info(i); 153 | } 154 | } 155 | 156 | // copy constructor and operator need to account for name storage 157 | Trace(const Trace &rhs) : _name(rhs._name) 158 | { 159 | name = _name.size() ? _name.c_str() : rhs.name; 160 | info = rhs.info; 161 | endpoint = rhs.endpoint; 162 | } 163 | const Trace& operator=(const Trace &rhs) 164 | { 165 | _name.assign(rhs._name); 166 | name = _name.size() ? _name.c_str() : rhs.name; 167 | info = rhs.info; 168 | endpoint = rhs.endpoint; 169 | return *this; 170 | } 171 | 172 | // return true if the Trace has been initialized 173 | bool valid() const { return info.trace_id != 0; } 174 | operator bool() const { return valid(); } 175 | 176 | // (re)initialize a Trace with an optional parent 177 | int init(const char *name, const Endpoint *ep, 178 | const Trace *parent = NULL) 179 | { 180 | if (parent && parent->valid()) 181 | return blkin_init_child(this, parent, 182 | ep ? : parent->endpoint, name); 183 | 184 | return blkin_init_new_trace(this, name, ep); 185 | } 186 | 187 | // (re)initialize a Trace from blkin_trace_info 188 | int init(const char *name, const Endpoint *ep, 189 | const blkin_trace_info *i, bool child=false) 190 | { 191 | if (child) 192 | return blkin_init_child_info(this, i, ep, _name.c_str()); 193 | 194 | return blkin_set_trace_properties(this, i, _name.c_str(), ep); 195 | } 196 | 197 | // Trace assumes that name will be a string literal, and avoids 198 | // making a copy and freeing on destruction. if you need to 199 | // initialize Trace with a temporary string, copy_name() will store 200 | // it in a std::string and assign from that 201 | void copy_name(const string &newname) 202 | { 203 | _name.assign(newname); 204 | name = _name.c_str(); 205 | } 206 | 207 | const blkin_trace_info* get_info() const { return &info; } 208 | void set_info(const blkin_trace_info *i) { info = *i; } 209 | 210 | // record key-value annotations 211 | void keyval(const char *key, const char *val) const 212 | { 213 | if (valid()) 214 | BLKIN_KEYVAL_STRING(this, endpoint, key, val); 215 | } 216 | void keyval(const char *key, int64_t val) const 217 | { 218 | if (valid()) 219 | BLKIN_KEYVAL_INTEGER(this, endpoint, key, val); 220 | } 221 | void keyval(const char *key, const char *val, const Endpoint *ep) const 222 | { 223 | if (valid()) 224 | BLKIN_KEYVAL_STRING(this, ep, key, val); 225 | } 226 | void keyval(const char *key, int64_t val, const Endpoint *ep) const 227 | { 228 | if (valid()) 229 | BLKIN_KEYVAL_INTEGER(this, ep, key, val); 230 | } 231 | 232 | // record timestamp annotations 233 | void event(const char *event) const 234 | { 235 | if (valid()) 236 | BLKIN_TIMESTAMP(this, endpoint, event); 237 | } 238 | void event(const char *event, const Endpoint *ep) const 239 | { 240 | if (valid()) 241 | BLKIN_TIMESTAMP(this, ep, event); 242 | } 243 | }; 244 | 245 | } 246 | #endif /* end of include guard: ZTRACER_H */ 247 | -------------------------------------------------------------------------------- /blkin-lib/zipkin_c.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Marios Kogias 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or 6 | * without modification, are permitted provided that the following 7 | * conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials 15 | * provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 24 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "zipkin_c.h" 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define TRACEPOINT_DEFINE 37 | #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE 38 | #include "tracing/zipkin.h" 39 | #define TRACEPOINT_DEFINE 40 | #undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE 41 | 42 | #include "global/global_context.h" 43 | #include "common/TracepointProvider.h" 44 | 45 | TracepointProvider::Traits tracepoint_traits("libzipkin_tp.so", "blkin_tracing"); 46 | 47 | const char *default_ip = "NaN"; 48 | const char *default_name = "NoName"; 49 | 50 | const char* const CLIENT_SEND = "cs"; 51 | const char* const CLIENT_RECV = "cr"; 52 | const char* const SERVER_SEND = "ss"; 53 | const char* const SERVER_RECV = "sr"; 54 | const char* const WIRE_SEND = "ws"; 55 | const char* const WIRE_RECV = "wr"; 56 | const char* const CLIENT_SEND_FRAGMENT = "csf"; 57 | const char* const CLIENT_RECV_FRAGMENT = "crf"; 58 | const char* const SERVER_SEND_FRAGMENT = "ssf"; 59 | const char* const SERVER_RECV_FRAGMENT = "srf"; 60 | 61 | static int64_t random_big() 62 | { 63 | int64_t a; 64 | a = rand(); 65 | a = a << 32; 66 | int b = rand(); 67 | a = a + b; 68 | if (a<0) 69 | a = !a; 70 | return a; 71 | } 72 | 73 | int blkin_init() 74 | { 75 | static pthread_mutex_t blkin_init_mutex = PTHREAD_MUTEX_INITIALIZER; 76 | static int initialized = 0; 77 | 78 | /* 79 | * Initialize srand with sth appropriete 80 | * time is not good for archipelago: several deamons -> same timstamp 81 | */ 82 | pthread_mutex_lock(&blkin_init_mutex); 83 | if (!initialized) { 84 | int inf, seed; 85 | inf = open("/dev/urandom", O_RDONLY); //file descriptor 1 86 | read(inf, &seed, sizeof(int)); 87 | close(inf); 88 | srand(seed); 89 | initialized = 1; 90 | } 91 | pthread_mutex_unlock(&blkin_init_mutex); 92 | return 0; 93 | } 94 | 95 | int blkin_init_new_trace(struct blkin_trace *new_trace, const char *service, 96 | const struct blkin_endpoint *endpoint) 97 | { 98 | int res; 99 | if (!new_trace) { 100 | res = -EINVAL; 101 | goto OUT; 102 | } 103 | new_trace->name = service; 104 | blkin_init_trace_info(&(new_trace->info)); 105 | new_trace->endpoint = endpoint; 106 | res = 0; 107 | 108 | OUT: 109 | return res; 110 | } 111 | 112 | void blkin_init_trace_info(struct blkin_trace_info *trace_info) 113 | { 114 | trace_info->span_id = trace_info->trace_id = random_big(); 115 | trace_info->parent_span_id = 0; 116 | } 117 | 118 | int blkin_init_child_info(struct blkin_trace *child, 119 | const struct blkin_trace_info *parent_info, 120 | const struct blkin_endpoint *endpoint, 121 | const char *child_name) 122 | { 123 | int res; 124 | if ((!child) || (!parent_info) || (!endpoint)){ 125 | res = -EINVAL; 126 | goto OUT; 127 | } 128 | child->info.trace_id = parent_info->trace_id; 129 | child->info.span_id = random_big(); 130 | child->info.parent_span_id = parent_info->span_id; 131 | child->name = child_name; 132 | child->endpoint = endpoint; 133 | res = 0; 134 | 135 | OUT: 136 | return res; 137 | } 138 | 139 | int blkin_init_child(struct blkin_trace *child, 140 | const struct blkin_trace *parent, 141 | const struct blkin_endpoint *endpoint, 142 | const char *child_name) 143 | { 144 | int res; 145 | if (!parent) { 146 | res = -EINVAL; 147 | goto OUT; 148 | } 149 | if (!endpoint) 150 | endpoint = parent->endpoint; 151 | if (blkin_init_child_info(child, &parent->info, endpoint, child_name) != 0){ 152 | res = -EINVAL; 153 | goto OUT; 154 | } 155 | res = 0; 156 | 157 | OUT: 158 | return res; 159 | } 160 | 161 | int blkin_init_endpoint(struct blkin_endpoint *endp, const char *ip, 162 | int16_t port, const char *name) 163 | { 164 | int res; 165 | if (!endp){ 166 | res = -EINVAL; 167 | goto OUT; 168 | } 169 | if (!ip) 170 | ip = default_ip; 171 | 172 | endp->ip = ip; 173 | endp->port = port; 174 | endp->name = name; 175 | res = 0; 176 | 177 | OUT: 178 | return res; 179 | } 180 | 181 | int blkin_init_string_annotation(struct blkin_annotation *annotation, 182 | const char *key, const char *val, const struct blkin_endpoint *endpoint) 183 | { 184 | int res; 185 | if ((!annotation) || (!key) || (!val)){ 186 | res = -EINVAL; 187 | goto OUT; 188 | } 189 | annotation->type = ANNOT_STRING; 190 | annotation->key = key; 191 | annotation->val_str = val; 192 | annotation->endpoint = endpoint; 193 | res = 0; 194 | 195 | OUT: 196 | return res; 197 | } 198 | 199 | int blkin_init_integer_annotation(struct blkin_annotation *annotation, 200 | const char *key, int64_t val, const struct blkin_endpoint *endpoint) 201 | { 202 | int res; 203 | if ((!annotation) || (!key)) { 204 | res = -EINVAL; 205 | goto OUT; 206 | } 207 | annotation->type = ANNOT_INTEGER; 208 | annotation->key = key; 209 | annotation->val_int = val; 210 | annotation->endpoint = endpoint; 211 | res = 0; 212 | 213 | OUT: 214 | return res; 215 | } 216 | 217 | int blkin_init_timestamp_annotation(struct blkin_annotation *annotation, 218 | const char *event, const struct blkin_endpoint *endpoint) 219 | { 220 | int res; 221 | if ((!annotation) || (!event)){ 222 | res = -EINVAL; 223 | goto OUT; 224 | } 225 | annotation->type = ANNOT_TIMESTAMP; 226 | annotation->val_str = event; 227 | annotation->endpoint = endpoint; 228 | res = 0; 229 | 230 | OUT: 231 | return res; 232 | } 233 | 234 | int blkin_record(const struct blkin_trace *trace, 235 | const struct blkin_annotation *annotation) 236 | { 237 | int res; 238 | const struct blkin_endpoint *endpoint; 239 | if (!annotation || !trace || !trace->name) { 240 | res = -EINVAL; 241 | goto OUT; 242 | } 243 | TracepointProvider::initialize(g_ceph_context); 244 | endpoint = annotation->endpoint ? nullptr : trace->endpoint; 245 | if (!endpoint || !endpoint->ip || !endpoint->name) { 246 | res = -EINVAL; 247 | goto OUT; 248 | } 249 | 250 | if (annotation->type == ANNOT_STRING) { 251 | if ((!annotation->key) || (!annotation->val_str)) { 252 | res = -EINVAL; 253 | goto OUT; 254 | } 255 | tracepoint(zipkin, keyval_string, trace->name, 256 | endpoint->name, endpoint->port, endpoint->ip, 257 | trace->info.trace_id, trace->info.span_id, 258 | trace->info.parent_span_id, 259 | annotation->key, annotation->val_str); 260 | } 261 | else if (annotation->type == ANNOT_INTEGER) { 262 | if (!annotation->key) { 263 | res = -EINVAL; 264 | goto OUT; 265 | } 266 | tracepoint(zipkin, keyval_integer, trace->name, 267 | endpoint->name, endpoint->port, endpoint->ip, 268 | trace->info.trace_id, trace->info.span_id, 269 | trace->info.parent_span_id, 270 | annotation->key, annotation->val_int); 271 | } 272 | else { 273 | if (!annotation->val_str) { 274 | res = -EINVAL; 275 | goto OUT; 276 | } 277 | tracepoint(zipkin, timestamp , trace->name, 278 | endpoint->name, endpoint->port, endpoint->ip, 279 | trace->info.trace_id, trace->info.span_id, 280 | trace->info.parent_span_id, 281 | annotation->val_str); 282 | } 283 | res = 0; 284 | OUT: 285 | return res; 286 | } 287 | 288 | int blkin_get_trace_info(const struct blkin_trace *trace, 289 | struct blkin_trace_info *info) 290 | { 291 | int res; 292 | if ((!trace) || (!info)){ 293 | res = -EINVAL; 294 | goto OUT; 295 | } 296 | 297 | res = 0; 298 | *info = trace->info; 299 | OUT: 300 | return res; 301 | } 302 | 303 | int blkin_set_trace_info(struct blkin_trace *trace, 304 | const struct blkin_trace_info *info) 305 | { 306 | int res; 307 | if ((!trace) || (!info)){ 308 | res = -EINVAL; 309 | goto OUT; 310 | } 311 | 312 | res = 0; 313 | trace->info = *info; 314 | OUT: 315 | return res; 316 | } 317 | 318 | int blkin_set_trace_properties(struct blkin_trace *trace, 319 | const struct blkin_trace_info *info, 320 | const char *name, 321 | const struct blkin_endpoint *endpoint) 322 | { 323 | int res; 324 | if ((!trace) || (!info) || (!endpoint) || (!name)){ 325 | res = -EINVAL; 326 | goto OUT; 327 | } 328 | 329 | res = 0; 330 | trace->info = *info; 331 | trace->name = name; 332 | trace->endpoint = endpoint; 333 | 334 | OUT: 335 | return res; 336 | } 337 | 338 | int blkin_pack_trace_info(const struct blkin_trace_info *info, 339 | struct blkin_trace_info_packed *pinfo) 340 | { 341 | if (!info || !pinfo) { 342 | return -EINVAL; 343 | } 344 | 345 | pinfo->trace_id = __cpu_to_be64(info->trace_id); 346 | pinfo->span_id = __cpu_to_be64(info->span_id); 347 | pinfo->parent_span_id = __cpu_to_be64(info->parent_span_id); 348 | 349 | return 0; 350 | } 351 | 352 | int blkin_unpack_trace_info(const struct blkin_trace_info_packed *pinfo, 353 | struct blkin_trace_info *info) 354 | { 355 | if (!info || !pinfo) { 356 | return -EINVAL; 357 | } 358 | 359 | info->trace_id = __be64_to_cpu(pinfo->trace_id); 360 | info->span_id = __be64_to_cpu(pinfo->span_id); 361 | info->parent_span_id = __be64_to_cpu(pinfo->parent_span_id); 362 | 363 | return 0; 364 | } 365 | -------------------------------------------------------------------------------- /blkin-lib/zipkin_c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Marios Kogias 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or 6 | * without modification, are permitted provided that the following 7 | * conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials 15 | * provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 24 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ZIPKIN_C_H_ 31 | #define ZIPKIN_C_H_ 32 | 33 | #include 34 | #include 35 | 36 | #define BLKIN_TIMESTAMP(trace, endp, event) \ 37 | do { \ 38 | struct blkin_annotation __annot; \ 39 | blkin_init_timestamp_annotation(&__annot, event, endp); \ 40 | blkin_record(trace, &__annot); \ 41 | } while (0); 42 | 43 | #define BLKIN_KEYVAL_STRING(trace, endp, key, val) \ 44 | do { \ 45 | struct blkin_annotation __annot; \ 46 | blkin_init_string_annotation(&__annot, key, val, endp); \ 47 | blkin_record(trace, &__annot); \ 48 | } while (0); 49 | 50 | #define BLKIN_KEYVAL_INTEGER(trace, endp, key, val) \ 51 | do { \ 52 | struct blkin_annotation __annot; \ 53 | blkin_init_integer_annotation(&__annot, key, val, endp);\ 54 | blkin_record(trace, &__annot); \ 55 | } while (0); 56 | 57 | /** 58 | * Core annotations used by Zipkin used to denote the beginning and end of 59 | * client and server spans. 60 | * For more information refer to 61 | * https://github.com/openzipkin/zipkin-api/blob/master/thrift/zipkinCore.thrift 62 | */ 63 | 64 | #ifdef __cplusplus 65 | extern "C" { 66 | #endif 67 | extern const char* const CLIENT_SEND; 68 | extern const char* const CLIENT_RECV; 69 | extern const char* const SERVER_SEND; 70 | extern const char* const SERVER_RECV; 71 | extern const char* const WIRE_SEND; 72 | extern const char* const WIRE_RECV; 73 | extern const char* const CLIENT_SEND_FRAGMENT; 74 | extern const char* const CLIENT_RECV_FRAGMENT; 75 | extern const char* const SERVER_SEND_FRAGMENT; 76 | extern const char* const SERVER_RECV_FRAGMENT; 77 | 78 | /** 79 | * @struct blkin_endpoint 80 | * Information about an endpoint of our instrumented application where 81 | * annotations take place 82 | */ 83 | struct blkin_endpoint { 84 | const char *ip; 85 | int16_t port; 86 | const char *name; 87 | }; 88 | 89 | /** 90 | * @struct blkin_trace_info 91 | * The information exchanged between different layers offering the needed 92 | * trace semantics 93 | */ 94 | struct blkin_trace_info { 95 | int64_t trace_id; 96 | int64_t span_id; 97 | int64_t parent_span_id; 98 | }; 99 | 100 | /** 101 | * @struct blkin_trace_info_packed 102 | * 103 | * Packed version of the struct blkin_trace_info. Usefull when sending over 104 | * network. 105 | * 106 | */ 107 | struct blkin_trace_info_packed { 108 | __be64 trace_id; 109 | __be64 span_id; 110 | __be64 parent_span_id; 111 | } __attribute__((packed)); 112 | 113 | 114 | /** 115 | * @struct blkin_trace 116 | * Struct used to define the context in which an annotation happens 117 | */ 118 | struct blkin_trace { 119 | const char *name; 120 | struct blkin_trace_info info; 121 | const struct blkin_endpoint *endpoint; 122 | }; 123 | 124 | /** 125 | * @typedef blkin_annotation_type 126 | * There are 2 kinds of annotation key-val and timestamp 127 | */ 128 | typedef enum { 129 | ANNOT_STRING = 0, 130 | ANNOT_INTEGER, 131 | ANNOT_TIMESTAMP 132 | } blkin_annotation_type; 133 | 134 | /** 135 | * @struct blkin_annotation 136 | * Struct carrying information about an annotation. This information can either 137 | * be key-val or that a specific event happened 138 | */ 139 | struct blkin_annotation { 140 | blkin_annotation_type type; 141 | const char *key; 142 | union { 143 | const char *val_str; 144 | int64_t val_int; 145 | }; 146 | const struct blkin_endpoint *endpoint; 147 | }; 148 | 149 | /** 150 | * Initialize the zipkin library. 151 | * 152 | * @return 0 on success 153 | */ 154 | int blkin_init(); 155 | 156 | /** 157 | * Initialize a new blkin_trace with the information given. The new trace will 158 | * have no parent so the parent id will be zero. 159 | * 160 | * @param new_trace the blkin_trace to be initialized 161 | * @param name the trace's name 162 | * @param endpoint a pointer to a blkin_endpoint struct that contains 163 | * info about where the specific trace takes place 164 | * 165 | * @returns 0 on success or negative error code 166 | */ 167 | int blkin_init_new_trace(struct blkin_trace *new_trace, const char *name, 168 | const struct blkin_endpoint *endpoint); 169 | 170 | /** 171 | * Initialize blkin_trace_info for a root span. The new trace will 172 | * have no parent so the parent id will be zero, and the id and trace id will 173 | * be the same. 174 | * 175 | * @param trace_info the blkin_trace_info to be initialized 176 | */ 177 | void blkin_init_trace_info(struct blkin_trace_info *trace_info); 178 | 179 | /** 180 | * Initialize a blkin_trace as a child of the given parent 181 | * bkin_trace. The child trace will have the same trace_id, new 182 | * span_id and parent_span_id its parent's span_id. 183 | * 184 | * @param child the blkin_trace to be initialized 185 | * @param parent the parent blkin_trace 186 | * @param child_name the blkin_trace name of the child 187 | * 188 | * @returns 0 on success or negative error code 189 | */ 190 | int blkin_init_child(struct blkin_trace *child, 191 | const struct blkin_trace *parent, 192 | const struct blkin_endpoint *endpoint, 193 | const char *child_name); 194 | 195 | /** 196 | * Initialize a blkin_trace struct and set the blkin_trace_info field to be 197 | * child of the given blkin_trace_info. This means 198 | * Same trace_id 199 | * Different span_id 200 | * Child's parent_span_id == parent's span_id 201 | * 202 | * @param child the new child blkin_trace_info 203 | * @param info the parent's blkin_trace_info struct 204 | * @param child_name the blkin_trace struct name field 205 | * 206 | * @returns 0 on success or negative error code 207 | */ 208 | int blkin_init_child_info(struct blkin_trace *child, 209 | const struct blkin_trace_info *info, 210 | const struct blkin_endpoint *endpoint, 211 | const char *child_name); 212 | 213 | /** 214 | * Initialize a blkin_endpoint struct with the information given 215 | * 216 | * @param endp the endpoint to be initialized 217 | * @param ip the ip address of the specific endpoint 218 | * @param port the TCP/UDP port of the specific endpoint 219 | * @param name the name of the service running on the specific endpoint 220 | * 221 | * @returns 0 on success or negative error code 222 | */ 223 | int blkin_init_endpoint(struct blkin_endpoint *endpoint, 224 | const char *ip, int16_t port, const char *name); 225 | 226 | /** 227 | * Initialize a key-value blkin_annotation 228 | * 229 | * @param annotation the annotation to be initialized 230 | * @param key the annotation's key 231 | * @param val the annotation's string value 232 | * @param endpoint where did this annotation occured 233 | * 234 | * @returns 0 on success or negative error code 235 | */ 236 | int blkin_init_string_annotation(struct blkin_annotation *annotation, 237 | const char *key, const char *val, 238 | const struct blkin_endpoint *endpoint); 239 | /** 240 | * Initialize a key-value blkin_annotation 241 | * 242 | * @param annotation the annotation to be initialized 243 | * @param key the annotation's key 244 | * @param val the annotation's int value 245 | * @param endpoint where did this annotation occured 246 | * 247 | * @returns 0 on success or negative error code 248 | */ 249 | 250 | int blkin_init_integer_annotation(struct blkin_annotation *annotation, 251 | const char *key, int64_t val, 252 | const struct blkin_endpoint *endpoint); 253 | 254 | /** 255 | * Initialize a timestamp blkin_annotation 256 | * 257 | * @param annotation the annotation to be initialized 258 | * @param event the event happened to be annotated 259 | * @param endpoint where did this annotation occured 260 | * 261 | * @returns 0 on success or negative error code 262 | */ 263 | 264 | int blkin_init_timestamp_annotation(struct blkin_annotation *annot, 265 | const char *event, 266 | const struct blkin_endpoint *endpoint); 267 | 268 | /** 269 | * Log an annotation in terms of a specific trace 270 | * 271 | * @param trace the trace to which the annotation belongs 272 | * @param annotation the annotation to be logged 273 | * 274 | * @returns 0 on success or negative error code 275 | */ 276 | int blkin_record(const struct blkin_trace *trace, 277 | const struct blkin_annotation *annotation); 278 | 279 | /** 280 | * Copy a blkin_trace_info struct into a the field info of a blkin_trace struct 281 | * 282 | * @param trace the destination 283 | * @param info where to copy from 284 | * 285 | * @returns 0 on success or negative error code 286 | */ 287 | int blkin_get_trace_info(const struct blkin_trace *trace, 288 | struct blkin_trace_info *info); 289 | 290 | /** 291 | * Copy the blkin_trace_info from a blkin_trace to another blkin_trace_info 292 | * 293 | * @param trace the trace with the essential info 294 | * @param info the destination 295 | * 296 | * @returns 0 on success or negative error code 297 | */ 298 | int blkin_set_trace_info(struct blkin_trace *trace, 299 | const struct blkin_trace_info *info); 300 | 301 | /** 302 | * Set the trace information, name and endpoint of a trace. 303 | * 304 | * @param trace the trace to which the properties will be assigned 305 | * @param info blkin_trace_information with the trace identifiers 306 | * @param name span name 307 | * @param endpoint associated host 308 | * 309 | * @returns 0 on success or negative error code 310 | */ 311 | int blkin_set_trace_properties(struct blkin_trace *trace, 312 | const struct blkin_trace_info *info, 313 | const char *name, 314 | const struct blkin_endpoint *endpoint); 315 | 316 | /** 317 | * Convert a blkin_trace_info to the packed version. 318 | * 319 | * @param info The unpacked trace info. 320 | * @param pinfo The provided packed version to be initialized. 321 | * 322 | * @returns 0 on success or negative error code 323 | */ 324 | int blkin_pack_trace_info(const struct blkin_trace_info *info, 325 | struct blkin_trace_info_packed *pinfo); 326 | 327 | /** 328 | * Convert a packed blkin_trace_info to the unpacked version. 329 | * 330 | * @param pinfo The provided packed version to be unpacked. 331 | * @param info The unpacked trace info. 332 | * 333 | * @returns 0 on success or negative error code 334 | */ 335 | int blkin_unpack_trace_info(const struct blkin_trace_info_packed *pinfo, 336 | struct blkin_trace_info *info); 337 | #ifdef __cplusplus 338 | /* end to extern "C" */ 339 | } 340 | #endif 341 | 342 | #endif /* ZIPKIN_C_H_ */ 343 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/ttypes.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift Compiler (0.8.0) 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | # options string: py:twisted 7 | # 8 | 9 | from thrift.Thrift import TType, TMessageType, TException 10 | 11 | from thrift.transport import TTransport 12 | from thrift.protocol import TBinaryProtocol, TProtocol 13 | try: 14 | from thrift.protocol import fastbinary 15 | except: 16 | fastbinary = None 17 | 18 | 19 | class AnnotationType: 20 | BOOL = 0 21 | BYTES = 1 22 | I16 = 2 23 | I32 = 3 24 | I64 = 4 25 | DOUBLE = 5 26 | STRING = 6 27 | 28 | _VALUES_TO_NAMES = { 29 | 0: "BOOL", 30 | 1: "BYTES", 31 | 2: "I16", 32 | 3: "I32", 33 | 4: "I64", 34 | 5: "DOUBLE", 35 | 6: "STRING", 36 | } 37 | 38 | _NAMES_TO_VALUES = { 39 | "BOOL": 0, 40 | "BYTES": 1, 41 | "I16": 2, 42 | "I32": 3, 43 | "I64": 4, 44 | "DOUBLE": 5, 45 | "STRING": 6, 46 | } 47 | 48 | 49 | class Endpoint: 50 | """ 51 | Attributes: 52 | - ipv4 53 | - port 54 | - service_name 55 | """ 56 | 57 | thrift_spec = ( 58 | None, # 0 59 | (1, TType.I32, 'ipv4', None, None, ), # 1 60 | (2, TType.I16, 'port', None, None, ), # 2 61 | (3, TType.STRING, 'service_name', None, None, ), # 3 62 | ) 63 | 64 | def __init__(self, ipv4=None, port=None, service_name=None,): 65 | self.ipv4 = ipv4 66 | self.port = port 67 | self.service_name = service_name 68 | 69 | def read(self, iprot): 70 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 71 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 72 | return 73 | iprot.readStructBegin() 74 | while True: 75 | (fname, ftype, fid) = iprot.readFieldBegin() 76 | if ftype == TType.STOP: 77 | break 78 | if fid == 1: 79 | if ftype == TType.I32: 80 | self.ipv4 = iprot.readI32(); 81 | else: 82 | iprot.skip(ftype) 83 | elif fid == 2: 84 | if ftype == TType.I16: 85 | self.port = iprot.readI16(); 86 | else: 87 | iprot.skip(ftype) 88 | elif fid == 3: 89 | if ftype == TType.STRING: 90 | self.service_name = iprot.readString(); 91 | else: 92 | iprot.skip(ftype) 93 | else: 94 | iprot.skip(ftype) 95 | iprot.readFieldEnd() 96 | iprot.readStructEnd() 97 | 98 | def write(self, oprot): 99 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 100 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 101 | return 102 | oprot.writeStructBegin('Endpoint') 103 | if self.ipv4 is not None: 104 | oprot.writeFieldBegin('ipv4', TType.I32, 1) 105 | oprot.writeI32(self.ipv4) 106 | oprot.writeFieldEnd() 107 | if self.port is not None: 108 | oprot.writeFieldBegin('port', TType.I16, 2) 109 | oprot.writeI16(self.port) 110 | oprot.writeFieldEnd() 111 | if self.service_name is not None: 112 | oprot.writeFieldBegin('service_name', TType.STRING, 3) 113 | oprot.writeString(self.service_name) 114 | oprot.writeFieldEnd() 115 | oprot.writeFieldStop() 116 | oprot.writeStructEnd() 117 | 118 | def validate(self): 119 | return 120 | 121 | 122 | def __repr__(self): 123 | L = ['%s=%r' % (key, value) 124 | for key, value in self.__dict__.iteritems()] 125 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 126 | 127 | def __eq__(self, other): 128 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 129 | 130 | def __ne__(self, other): 131 | return not (self == other) 132 | 133 | class Annotation: 134 | """ 135 | Attributes: 136 | - timestamp 137 | - value 138 | - host 139 | """ 140 | 141 | thrift_spec = ( 142 | None, # 0 143 | (1, TType.I64, 'timestamp', None, None, ), # 1 144 | (2, TType.STRING, 'value', None, None, ), # 2 145 | (3, TType.STRUCT, 'host', (Endpoint, Endpoint.thrift_spec), None, ), # 3 146 | ) 147 | 148 | def __init__(self, timestamp=None, value=None, host=None,): 149 | self.timestamp = timestamp 150 | self.value = value 151 | self.host = host 152 | 153 | def read(self, iprot): 154 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 155 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 156 | return 157 | iprot.readStructBegin() 158 | while True: 159 | (fname, ftype, fid) = iprot.readFieldBegin() 160 | if ftype == TType.STOP: 161 | break 162 | if fid == 1: 163 | if ftype == TType.I64: 164 | self.timestamp = iprot.readI64(); 165 | else: 166 | iprot.skip(ftype) 167 | elif fid == 2: 168 | if ftype == TType.STRING: 169 | self.value = iprot.readString(); 170 | else: 171 | iprot.skip(ftype) 172 | elif fid == 3: 173 | if ftype == TType.STRUCT: 174 | self.host = Endpoint() 175 | self.host.read(iprot) 176 | else: 177 | iprot.skip(ftype) 178 | else: 179 | iprot.skip(ftype) 180 | iprot.readFieldEnd() 181 | iprot.readStructEnd() 182 | 183 | def write(self, oprot): 184 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 185 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 186 | return 187 | oprot.writeStructBegin('Annotation') 188 | if self.timestamp is not None: 189 | oprot.writeFieldBegin('timestamp', TType.I64, 1) 190 | oprot.writeI64(self.timestamp) 191 | oprot.writeFieldEnd() 192 | if self.value is not None: 193 | oprot.writeFieldBegin('value', TType.STRING, 2) 194 | oprot.writeString(self.value) 195 | oprot.writeFieldEnd() 196 | if self.host is not None: 197 | oprot.writeFieldBegin('host', TType.STRUCT, 3) 198 | self.host.write(oprot) 199 | oprot.writeFieldEnd() 200 | oprot.writeFieldStop() 201 | oprot.writeStructEnd() 202 | 203 | def validate(self): 204 | return 205 | 206 | 207 | def __repr__(self): 208 | L = ['%s=%r' % (key, value) 209 | for key, value in self.__dict__.iteritems()] 210 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 211 | 212 | def __eq__(self, other): 213 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 214 | 215 | def __ne__(self, other): 216 | return not (self == other) 217 | 218 | class BinaryAnnotation: 219 | """ 220 | Attributes: 221 | - key 222 | - value 223 | - annotation_type 224 | - host 225 | """ 226 | 227 | thrift_spec = ( 228 | None, # 0 229 | (1, TType.STRING, 'key', None, None, ), # 1 230 | (2, TType.STRING, 'value', None, None, ), # 2 231 | (3, TType.I32, 'annotation_type', None, None, ), # 3 232 | (4, TType.STRUCT, 'host', (Endpoint, Endpoint.thrift_spec), None, ), # 4 233 | ) 234 | 235 | def __init__(self, key=None, value=None, annotation_type=None, host=None,): 236 | self.key = key 237 | self.value = value 238 | self.annotation_type = annotation_type 239 | self.host = host 240 | 241 | def read(self, iprot): 242 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 243 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 244 | return 245 | iprot.readStructBegin() 246 | while True: 247 | (fname, ftype, fid) = iprot.readFieldBegin() 248 | if ftype == TType.STOP: 249 | break 250 | if fid == 1: 251 | if ftype == TType.STRING: 252 | self.key = iprot.readString(); 253 | else: 254 | iprot.skip(ftype) 255 | elif fid == 2: 256 | if ftype == TType.STRING: 257 | self.value = iprot.readString(); 258 | else: 259 | iprot.skip(ftype) 260 | elif fid == 3: 261 | if ftype == TType.I32: 262 | self.annotation_type = iprot.readI32(); 263 | else: 264 | iprot.skip(ftype) 265 | elif fid == 4: 266 | if ftype == TType.STRUCT: 267 | self.host = Endpoint() 268 | self.host.read(iprot) 269 | else: 270 | iprot.skip(ftype) 271 | else: 272 | iprot.skip(ftype) 273 | iprot.readFieldEnd() 274 | iprot.readStructEnd() 275 | 276 | def write(self, oprot): 277 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 278 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 279 | return 280 | oprot.writeStructBegin('BinaryAnnotation') 281 | if self.key is not None: 282 | oprot.writeFieldBegin('key', TType.STRING, 1) 283 | oprot.writeString(self.key) 284 | oprot.writeFieldEnd() 285 | if self.value is not None: 286 | oprot.writeFieldBegin('value', TType.STRING, 2) 287 | oprot.writeString(self.value) 288 | oprot.writeFieldEnd() 289 | if self.annotation_type is not None: 290 | oprot.writeFieldBegin('annotation_type', TType.I32, 3) 291 | oprot.writeI32(self.annotation_type) 292 | oprot.writeFieldEnd() 293 | if self.host is not None: 294 | oprot.writeFieldBegin('host', TType.STRUCT, 4) 295 | self.host.write(oprot) 296 | oprot.writeFieldEnd() 297 | oprot.writeFieldStop() 298 | oprot.writeStructEnd() 299 | 300 | def validate(self): 301 | return 302 | 303 | 304 | def __repr__(self): 305 | L = ['%s=%r' % (key, value) 306 | for key, value in self.__dict__.iteritems()] 307 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 308 | 309 | def __eq__(self, other): 310 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 311 | 312 | def __ne__(self, other): 313 | return not (self == other) 314 | 315 | class Span: 316 | """ 317 | Attributes: 318 | - trace_id 319 | - name 320 | - id 321 | - parent_id 322 | - annotations 323 | - binary_annotations 324 | """ 325 | 326 | thrift_spec = ( 327 | None, # 0 328 | (1, TType.I64, 'trace_id', None, None, ), # 1 329 | None, # 2 330 | (3, TType.STRING, 'name', None, None, ), # 3 331 | (4, TType.I64, 'id', None, None, ), # 4 332 | (5, TType.I64, 'parent_id', None, None, ), # 5 333 | (6, TType.LIST, 'annotations', (TType.STRUCT,(Annotation, Annotation.thrift_spec)), None, ), # 6 334 | None, # 7 335 | (8, TType.LIST, 'binary_annotations', (TType.STRUCT,(BinaryAnnotation, BinaryAnnotation.thrift_spec)), None, ), # 8 336 | ) 337 | 338 | def __init__(self, trace_id=None, name=None, id=None, parent_id=None, annotations=None, binary_annotations=None,): 339 | self.trace_id = trace_id 340 | self.name = name 341 | self.id = id 342 | self.parent_id = parent_id 343 | self.annotations = annotations 344 | self.binary_annotations = binary_annotations 345 | 346 | def read(self, iprot): 347 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 348 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 349 | return 350 | iprot.readStructBegin() 351 | while True: 352 | (fname, ftype, fid) = iprot.readFieldBegin() 353 | if ftype == TType.STOP: 354 | break 355 | if fid == 1: 356 | if ftype == TType.I64: 357 | self.trace_id = iprot.readI64(); 358 | else: 359 | iprot.skip(ftype) 360 | elif fid == 3: 361 | if ftype == TType.STRING: 362 | self.name = iprot.readString(); 363 | else: 364 | iprot.skip(ftype) 365 | elif fid == 4: 366 | if ftype == TType.I64: 367 | self.id = iprot.readI64(); 368 | else: 369 | iprot.skip(ftype) 370 | elif fid == 5: 371 | if ftype == TType.I64: 372 | self.parent_id = iprot.readI64(); 373 | else: 374 | iprot.skip(ftype) 375 | elif fid == 6: 376 | if ftype == TType.LIST: 377 | self.annotations = [] 378 | (_etype3, _size0) = iprot.readListBegin() 379 | for _i4 in xrange(_size0): 380 | _elem5 = Annotation() 381 | _elem5.read(iprot) 382 | self.annotations.append(_elem5) 383 | iprot.readListEnd() 384 | else: 385 | iprot.skip(ftype) 386 | elif fid == 8: 387 | if ftype == TType.LIST: 388 | self.binary_annotations = [] 389 | (_etype9, _size6) = iprot.readListBegin() 390 | for _i10 in xrange(_size6): 391 | _elem11 = BinaryAnnotation() 392 | _elem11.read(iprot) 393 | self.binary_annotations.append(_elem11) 394 | iprot.readListEnd() 395 | else: 396 | iprot.skip(ftype) 397 | else: 398 | iprot.skip(ftype) 399 | iprot.readFieldEnd() 400 | iprot.readStructEnd() 401 | 402 | def write(self, oprot): 403 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 404 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 405 | return 406 | oprot.writeStructBegin('Span') 407 | if self.trace_id is not None: 408 | oprot.writeFieldBegin('trace_id', TType.I64, 1) 409 | oprot.writeI64(self.trace_id) 410 | oprot.writeFieldEnd() 411 | if self.name is not None: 412 | oprot.writeFieldBegin('name', TType.STRING, 3) 413 | oprot.writeString(self.name) 414 | oprot.writeFieldEnd() 415 | if self.id is not None: 416 | oprot.writeFieldBegin('id', TType.I64, 4) 417 | oprot.writeI64(self.id) 418 | oprot.writeFieldEnd() 419 | if self.parent_id is not None: 420 | oprot.writeFieldBegin('parent_id', TType.I64, 5) 421 | oprot.writeI64(self.parent_id) 422 | oprot.writeFieldEnd() 423 | if self.annotations is not None: 424 | oprot.writeFieldBegin('annotations', TType.LIST, 6) 425 | oprot.writeListBegin(TType.STRUCT, len(self.annotations)) 426 | for iter12 in self.annotations: 427 | iter12.write(oprot) 428 | oprot.writeListEnd() 429 | oprot.writeFieldEnd() 430 | if self.binary_annotations is not None: 431 | oprot.writeFieldBegin('binary_annotations', TType.LIST, 8) 432 | oprot.writeListBegin(TType.STRUCT, len(self.binary_annotations)) 433 | for iter13 in self.binary_annotations: 434 | iter13.write(oprot) 435 | oprot.writeListEnd() 436 | oprot.writeFieldEnd() 437 | oprot.writeFieldStop() 438 | oprot.writeStructEnd() 439 | 440 | def validate(self): 441 | return 442 | 443 | 444 | def __repr__(self): 445 | L = ['%s=%r' % (key, value) 446 | for key, value in self.__dict__.iteritems()] 447 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 448 | 449 | def __eq__(self, other): 450 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 451 | 452 | def __ne__(self, other): 453 | return not (self == other) 454 | --------------------------------------------------------------------------------