├── COPYRIGHT ├── INSTALL.md ├── Makefile.am ├── README.md ├── babeltrace-plugins ├── .gitignore ├── json │ ├── README.md │ └── src │ │ └── babeltrace_json.py ├── scribe_client │ ├── __init__.py │ └── scribe_client.py └── zipkin │ ├── README.md │ ├── src │ ├── babeltrace_zipkin.py │ └── zipkin_logic │ │ ├── __init__.py │ │ ├── formatters.py │ │ ├── trace.py │ │ ├── ttypes.py │ │ └── zipkin_client.py │ └── zipkin_trace.h ├── blkin.pc.in ├── blkin.spec.in ├── configure.ac ├── debian ├── blkin-babeltrace.dirs.in ├── blkin-babeltrace.install.in ├── blkin-dev.dirs ├── blkin-dev.install ├── blkin.dirs ├── blkin.install ├── changelog ├── compat ├── control ├── copyright ├── docs ├── postinst.in ├── postrm.in ├── rules └── source │ └── format ├── m4 └── ax_python_module.m4 └── src ├── blkin-front.c ├── blkin-front.h ├── tests ├── test.cc ├── test_p.cc └── testc.c ├── tp.c ├── zipkin_c.c ├── zipkin_c.h ├── zipkin_trace.h ├── ztracer.cc └── ztracer.hpp /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 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | #blkin 2 | 3 | ## By Hand 4 | 5 | See the RPM and Debian sections below for installing build 6 | dependencies. 7 | 8 | If building the Babeltrace plugins and the configure 9 | script cannot find the babeltrace python module, then 10 | set the following enviornment variables. 11 | 12 | ``` 13 | export PYTHON="python3" 14 | export PYTHON_CONFIG="/usr/bin/python3-config" 15 | ``` 16 | 17 | After untarring the distribution and changing into its 18 | directory. 19 | 20 | ``` 21 | autoreconf -fi 22 | ./configure 23 | make 24 | sudo make install 25 | ``` 26 | 27 | ## RPM 28 | 29 | If you have cloned directly from the git repo, 30 | then you have to generate the Makefile and 31 | tarball first. But if you have the tarball, 32 | then skip to rpmbuild. 33 | 34 | Note: Fedora does not yet package the Babeltrace Python bindings, 35 | so the BlkKin rpm installation excludes the Babeltrace plugins. 36 | 37 | ``` 38 | sudo yum install boost-devel lttng-tools liblttng-ust-devel 39 | autoreconf -fi 40 | ./configure 41 | make dist 42 | rpmbuild -ta blkin-*.xz 43 | cd ~/rpmbuild 44 | sudo rpm -ivh $(ls RPMS/x86_64/blkin* | grep -v debuginfo) 45 | ``` 46 | 47 | ## Debian 48 | 49 | If you have cloned directly from the git repo, 50 | then you have to generate the Makefile first. 51 | Otherwise, skip to debuild. 52 | 53 | ``` 54 | sudo apt-get install libboost-all-dev lttng-tools liblttng-ust-dev python3-babeltrace 55 | autoreconf -fi 56 | debuild -i -us -uc -b -j9 57 | sudo dpkg -i ../*.deb 58 | ``` 59 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 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 | ACLOCAL_AMFLAGS = -I m4 30 | EXTRA_DIST = README.md INSTALL.md blkin.spec blkin.pc 31 | 32 | noinst_PROGRAMS = src/tests/testc src/tests/testpp src/tests/testppp 33 | lib_LTLIBRARIES = src/libblkin-front.la src/libzipkin-c.la src/libzipkin-cpp.la 34 | pkginclude_HEADERS = src/zipkin_c.h src/zipkin_trace.h src/ztracer.hpp src/blkin-front.h 35 | 36 | pkgconfigdir = $(libdir)/pkgconfig 37 | dist_pkgconfig_DATA = blkin.pc 38 | 39 | AM_CPPFLAGS = -Isrc -I$(srcdir)/src 40 | 41 | src_tests_testc_SOURCES = src/tests/testc.c 42 | src_tests_testc_LDADD = src/libblkin-front.la 43 | 44 | src_tests_testpp_SOURCES = src/tests/test.cc 45 | src_tests_testpp_LDADD = src/libzipkin-cpp.la -lboost_thread -lboost_system 46 | 47 | src_tests_testppp_SOURCES = src/tests/test_p.cc 48 | src_tests_testppp_LDADD = src/libzipkin-cpp.la -lboost_thread -lboost_system 49 | 50 | src_libblkin_front_la_SOURCES = src/blkin-front.c 51 | src_libblkin_front_la_LIBADD = -ldl -llttng-ust 52 | 53 | src_libzipkin_cpp_la_SOURCES = src/ztracer.cc src/ztracer.hpp 54 | src_libzipkin_cpp_la_LIBADD = src/libblkin-front.la 55 | 56 | src_libzipkin_c_la_SOURCES = src/zipkin_c.c src/zipkin_c.h src/zipkin_trace.h src/tp.c 57 | src_libzipkin_c_la_LIBADD = -ldl -llttng-ust 58 | 59 | dist_doc_DATA = README.md INSTALL.md COPYRIGHT 60 | 61 | if WITH_BABEL 62 | dist_bin_SCRIPTS = \ 63 | babeltrace-plugins/zipkin/src/babeltrace_zipkin \ 64 | babeltrace-plugins/json/src/babeltrace_json 65 | 66 | CLEANFILES = $(dist_bin_SCRIPTS) 67 | 68 | babeltrace-plugins/zipkin/src/babeltrace_zipkin: $(srcdir)/babeltrace-plugins/zipkin/src/babeltrace_zipkin.py 69 | cp $(srcdir)/babeltrace-plugins/zipkin/src/babeltrace_zipkin.py $@ 70 | chmod +x $@ 71 | 72 | babeltrace-plugins/json/src/babeltrace_json: $(srcdir)/babeltrace-plugins/json/src/babeltrace_json.py 73 | cp $(srcdir)/babeltrace-plugins/json/src/babeltrace_json.py $@ 74 | chmod +x $@ 75 | 76 | zipkin_logicdir = $(pythondir)/zipkin_logic 77 | zipkin_logic_PYTHON = \ 78 | babeltrace-plugins/zipkin/src/zipkin_logic/formatters.py \ 79 | babeltrace-plugins/zipkin/src/zipkin_logic/trace.py \ 80 | babeltrace-plugins/zipkin/src/zipkin_logic/__init__.py \ 81 | babeltrace-plugins/zipkin/src/zipkin_logic/zipkin_client.py \ 82 | babeltrace-plugins/zipkin/src/zipkin_logic/ttypes.py 83 | 84 | scribe_clientdir = $(pythondir)/scribe_client 85 | scribe_client_PYTHON = \ 86 | babeltrace-plugins/scribe_client/scribe_client.py \ 87 | babeltrace-plugins/scribe_client/__init__.py 88 | 89 | noinst_SCRIPTS = \ 90 | debian/blkin-babeltrace.dirs \ 91 | debian/blkin-babeltrace.install \ 92 | debian/postinst \ 93 | debian/postrm 94 | 95 | py_subst = sed -e 's![@]PYTHONDIR[@]!$(pythondir)!g' 96 | 97 | debian/blkin-babeltrace.dirs: $(srcdir)/debian/blkin-babeltrace.dirs.in 98 | $(py_subst) $(srcdir)/debian/blkin-babeltrace.dirs.in > $@ 99 | debian/blkin-babeltrace.install: $(srcdir)/debian/blkin-babeltrace.install.in 100 | $(py_subst) $(srcdir)/debian/blkin-babeltrace.install.in > $@ 101 | debian/postinst: $(srcdir)/debian/postinst.in 102 | $(py_subst) $(srcdir)/debian/postinst.in > $@ 103 | debian/postrm: $(srcdir)/debian/postrm.in 104 | $(py_subst) $(srcdir)/debian/postrm.in > $@ 105 | endif # WITH_BABEL 106 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #blkin 2 | 3 | BlkKin is a project that enables you to trace low-overhead applications using 4 | LTTng following the tracing semantics that are 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. So, the BlkKin 10 | library gives the user the API to easily instrument C/C++ applications. In 11 | order to instrument applications you should take a look at ``blkin-lib/tests`` 12 | for some testcases and at the ``blkin-lib/zipkin_c.h`` file 13 | 14 | As a tracing backend BlkKin uses LTTng. So you must have LTTng installed. 15 | 16 | In order to visualize the aggregated information you can use Twitter's 17 | [Zipkin](http://twitter.github.io/zipkin/) and send the data that you created, 18 | by running the equivalent babeltrace plugin. In order to do you can run 19 | 20 | ``` 21 | ./zipkin/src/babeltrace_zipkin.py -s 22 | -p 23 | 24 | ``` 25 | 26 | within the babeltrace-plugins directory. 27 | 28 | In case you have not used the blkin-lib to instrument your application, you can 29 | still send your data to a Scribe server. To do that you can use another 30 | Babeltrace plugin. This plugin tranforms LTTng trace data to a JSON format and 31 | sends them to a Scribe sever.To do so we can equivalently run 32 | 33 | ``` 34 | ./json/src/babeltrace_json.py -s 35 | -p 36 | ``` 37 | within the babeltrace-plugins directory 38 | 39 | Both of these plugins require that you have installed Babeltrace with its 40 | Python bindings enabled. 41 | The path to the lttng traces should not be the root directory but the directory 42 | where the channel directories are included. 43 | 44 | ## Dependencies 45 | 46 | * libboost-all-dev 47 | * lttng-tools 48 | -------------------------------------------------------------------------------- /babeltrace-plugins/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/file -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['evemt'] = 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 | -------------------------------------------------------------------------------- /babeltrace-plugins/scribe_client/__init__.py: -------------------------------------------------------------------------------- 1 | from scribe_client import * 2 | -------------------------------------------------------------------------------- /babeltrace-plugins/scribe_client/scribe_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # scribe_client.py 3 | 4 | from __future__ import print_function 5 | from scribe import scribe 6 | from thrift.transport import TTransport, TSocket 7 | from thrift.protocol import TBinaryProtocol 8 | 9 | class ScribeClient(object): 10 | 11 | def __init__(self, port, host): 12 | print(host) 13 | self.port = port 14 | self.host = host 15 | self.openConnection() 16 | 17 | def openConnection(self): 18 | socket = TSocket.TSocket(host=self.host, port=self.port) 19 | self.transport = TTransport.TFramedTransport(socket) 20 | protocol = TBinaryProtocol.TBinaryProtocol(trans=self.transport, 21 | strictRead=False, 22 | strictWrite=False) 23 | self.client = scribe.Client(protocol) 24 | self.transport.open() 25 | 26 | def log(self, category, message): 27 | log_entry = scribe.LogEntry(category, message) 28 | result = self.client.Log(messages=[log_entry]) 29 | return result # 0 for success 30 | 31 | def close(self): 32 | self.transport.close() 33 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/file -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 | try: 51 | provider, kind = name.split(":") 52 | if provider != "zipkin": 53 | raise 54 | except: 55 | continue 56 | 57 | #create a zipkin trace from event info 58 | trace = zipkin.create_trace(event) 59 | 60 | #create a zipkin annotation from event info 61 | annotation = zipkin.create_annotation(event, kind) 62 | 63 | #record the trace 64 | zipkin.record(trace, annotation) 65 | 66 | zipkin.close() 67 | 68 | if __name__ == "__main__": 69 | main(sys.argv[1:]) 70 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marioskogias/blkin/10dcc95541457c4d4faa0224aadf99e5b2f5eec6/babeltrace-plugins/zipkin/src/zipkin_logic/__init__.py -------------------------------------------------------------------------------- /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 | from __future__ import print_function 16 | 17 | import json 18 | import struct 19 | import socket 20 | 21 | from thrift.protocol import TBinaryProtocol 22 | from thrift.transport import TTransport 23 | 24 | import ttypes 25 | 26 | 27 | def hex_str(n): 28 | return '%0.16x' % (n,) 29 | 30 | 31 | def json_formatter(traces, *json_args, **json_kwargs): 32 | json_traces = [] 33 | 34 | for (trace, annotations) in traces: 35 | json_trace = { 36 | 'trace_id': hex_str(trace.trace_id), 37 | 'span_id': hex_str(trace.span_id), 38 | 'name': trace.name, 39 | 'annotations': [] 40 | } 41 | 42 | if trace.parent_span_id: 43 | json_trace['parent_span_id'] = hex_str(trace.parent_span_id) 44 | 45 | for annotation in annotations: 46 | json_annotation = { 47 | 'key': annotation.name, 48 | 'value': annotation.value, 49 | 'type': annotation.annotation_type 50 | } 51 | 52 | if annotation.endpoint: 53 | json_annotation['host'] = { 54 | 'ipv4': annotation.endpoint.ipv4, 55 | 'port': annotation.endpoint.port, 56 | 'service_name': annotation.endpoint.service_name 57 | } 58 | 59 | json_trace['annotations'].append(json_annotation) 60 | 61 | json_traces.append(json_trace) 62 | 63 | return json.dumps(json_traces, *json_args, **json_kwargs) 64 | 65 | 66 | def ipv4_to_int(ipv4): 67 | return struct.unpack('!i', socket.inet_aton(ipv4))[0] 68 | 69 | 70 | def base64_thrift(thrift_obj): 71 | trans = TTransport.TMemoryBuffer() 72 | tbp = TBinaryProtocol.TBinaryProtocol(trans) 73 | 74 | thrift_obj.write(tbp) 75 | res = trans.getvalue().encode('base64').strip() 76 | res = res.replace("\n","") 77 | #print(res) 78 | #print(len(res)) 79 | return res 80 | #return trans.getvalue().encode('base64').strip() 81 | 82 | 83 | def binary_annotation_formatter(annotation, host=None): 84 | annotation_types = { 85 | 'string': ttypes.AnnotationType.STRING, 86 | 'bytes': ttypes.AnnotationType.BYTES, 87 | } 88 | 89 | annotation_type = annotation_types[annotation.annotation_type] 90 | 91 | value = annotation.value 92 | 93 | if isinstance(value, unicode): 94 | value = value.encode('utf-8') 95 | 96 | return ttypes.BinaryAnnotation( 97 | annotation.name, 98 | value, 99 | annotation_type, 100 | host) 101 | 102 | 103 | def base64_thrift_formatter(trace, annotations): 104 | thrift_annotations = [] 105 | binary_annotations = [] 106 | 107 | for annotation in annotations: 108 | host = None 109 | if annotation.endpoint: 110 | host = ttypes.Endpoint( 111 | ipv4=ipv4_to_int(annotation.endpoint.ipv4), 112 | port=annotation.endpoint.port, 113 | service_name=annotation.endpoint.service_name) 114 | 115 | if annotation.annotation_type == 'timestamp': 116 | thrift_annotations.append(ttypes.Annotation( 117 | timestamp=annotation.value, 118 | value=annotation.name, 119 | host=host)) 120 | else: 121 | binary_annotations.append( 122 | binary_annotation_formatter(annotation, host)) 123 | 124 | thrift_trace = ttypes.Span( 125 | trace_id=trace.trace_id, 126 | name=trace.name, 127 | id=trace.span_id, 128 | parent_id=trace.parent_span_id, 129 | annotations=thrift_annotations, 130 | binary_annotations=binary_annotations 131 | ) 132 | 133 | return base64_thrift(thrift_trace) 134 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /babeltrace-plugins/zipkin/src/zipkin_logic/zipkin_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from __future__ import print_function 4 | from scribe_client import ScribeClient 5 | from trace import Annotation, Trace, Endpoint 6 | from collections import defaultdict 7 | from formatters import base64_thrift_formatter 8 | 9 | 10 | class ZipkinClient(ScribeClient): 11 | 12 | DEFAULT_END_ANNOTATIONS = ("ss", "cr", "end") 13 | 14 | def __init__(self, port, host): 15 | super(ZipkinClient, self).__init__(port, host) 16 | self._annotations_for_trace = defaultdict(list) 17 | 18 | def create_trace(self, event): 19 | service = event["trace_name"] 20 | trace_id = event["trace_id"] 21 | span_id = event["span_id"] 22 | parent_span = event["parent_span_id"] 23 | if parent_span == 0: 24 | parent_span = None 25 | trace = Trace(service, trace_id, span_id, parent_span) 26 | return trace 27 | 28 | def create_annotation(self, event, kind): 29 | if kind == "keyval": 30 | key = event["key"] 31 | val = event["val"] 32 | annotation = Annotation.string(key, val) 33 | elif kind == "timestamp": 34 | timestamp = event.timestamp 35 | #timestamp has different digit length 36 | timestamp = str(timestamp) 37 | timestamp = timestamp[:-3] 38 | event_name = event["event"] 39 | annotation = Annotation.timestamp(event_name, int(timestamp)) 40 | 41 | # create and set endpoint 42 | port = event["port_no"] 43 | service = event["service_name"] 44 | ip = event["ip"] 45 | endpoint = Endpoint(ip, int(port), service) 46 | annotation.endpoint = endpoint 47 | 48 | print(annotation) 49 | return annotation 50 | 51 | def record(self, trace, annotation): 52 | self.scribe_log(trace, [annotation]) 53 | ''' 54 | trace_key = (trace.trace_id, trace.span_id) 55 | self._annotations_for_trace[trace_key].append(annotation) 56 | if (annotation.name in self.DEFAULT_END_ANNOTATIONS): 57 | saved_annotations = self._annotations_for_trace[trace_key] 58 | del self._annotations_for_trace[trace_key] 59 | self.scribe_log(trace, saved_annotations) 60 | print("Record event") 61 | ''' 62 | 63 | def scribe_log(self, trace, annotations): 64 | trace._endpoint = None 65 | message = base64_thrift_formatter(trace, annotations) 66 | category = 'zipkin' 67 | return self.log(category, message) 68 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /blkin.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: BlkKin Dapper-style Tracer 7 | Description: BlkKin is a library that enables Dapper-style traces with Zipkin + LTTng 8 | Version: @VERSION@ 9 | Requires: 10 | Requires.private: lttng-ust 11 | Libs: -L${libdir} -lzipkin-cpp 12 | Cflags: -I${includedir}/blkin 13 | 14 | -------------------------------------------------------------------------------- /blkin.spec.in: -------------------------------------------------------------------------------- 1 | Name: blkin 2 | Version: @VERSION@ 3 | Release: 1%{?dist} 4 | Summary: blkin is a Dapper-style tracing library to be used with Zipkin 5 | 6 | Group: Development/Libraries 7 | License: BSD 8 | URL: https://github.com/marioskogias/blkin 9 | Source0: blkin-%{version}.tar.xz 10 | Provides: libblkin-front.so()(64bit), libzipkin-cpp.so()(64bit) 11 | 12 | BuildRequires: boost-devel, pkgconfig(lttng-ust) 13 | Requires: pkgconfig 14 | 15 | %description 16 | blkin is a C/C++ library that enables you to get traces from C/C++ applications 17 | according to the tracing semantics mentioned in the Dapper paper and 18 | implemented in Zipkin 19 | 20 | As a tracing backend blkin uses LTTng 21 | 22 | 23 | %package devel 24 | Summary: blkin library headers and development files 25 | Group: Development/Libraries 26 | 27 | %description devel 28 | Support for developing programs using the blkin tracing library 29 | 30 | %prep 31 | %setup -q 32 | 33 | 34 | %build 35 | autoreconf -i 36 | 37 | %{configure} --prefix=%{_prefix} 38 | 39 | make %{?_smp_mflags} 40 | 41 | 42 | %install 43 | make install prefix=%{_prefix} DESTDIR=%{buildroot} 44 | %{__rm} %{buildroot}%{_libdir}/*.la 45 | 46 | 47 | %files 48 | %doc README.md 49 | %doc COPYRIGHT 50 | %{_libdir}/lib*so* 51 | 52 | %files devel 53 | %{_libdir}/lib*.a 54 | %{_libdir}/pkgconfig/blkin.pc 55 | %{_includedir}/blkin/blkin-front.h 56 | %{_includedir}/blkin/zipkin_c.h 57 | %{_includedir}/blkin/zipkin_trace.h 58 | %{_includedir}/blkin/ztracer.hpp 59 | 60 | %changelog 61 | * Mon Nov 3 2014 Andrew Shewmaker 0.1 62 | - Initial packaging 63 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_INIT([blkin], [0.1], [Marios-Evaggelos Kogias ], [blkin], [https://github.com/marioskogias/blkin]) 5 | 6 | AC_CONFIG_MACRO_DIR([m4]) 7 | 8 | # Automake 9 | AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz]) 10 | 11 | # Libtool 12 | LT_INIT 13 | 14 | # Checks for programs. 15 | AC_PROG_CC 16 | AC_PROG_CXX 17 | 18 | PKG_CHECK_MODULES([LTTNG_UST], [lttng-ust > 2.5]) 19 | 20 | AC_CHECK_LIB(boost_system, main, [], AC_MSG_NOTICE(["Boost system library not found."])) 21 | 22 | AC_CHECK_LIB(boost_thread, main, [], AC_MSG_NOTICE(["Boost thread library not found."])) 23 | 24 | AM_PATH_PYTHON([3.0], , [AC_MSG_NOTICE(Python3 required for optional Babeltrace plugins.)]) 25 | 26 | # Python bindings for Babeltrace plugins 27 | AC_ARG_WITH([babeltrace], 28 | AS_HELP_STRING([--without-babeltrace], [Ignore presence of babeltrace and disable it])) 29 | 30 | have_babeltrace=check 31 | AS_IF([test "x$with_babeltrace" != "xno"], 32 | [AX_PYTHON_MODULE([babeltrace], [have_babeltrace=no])], 33 | [have_babeltrace=no]) 34 | 35 | AS_IF([test "x$have_babeltrace" != "xno"], 36 | [have_babeltrace=yes], 37 | [AS_IF([test "x$with_babeltrace" = "xyes"], 38 | [AC_MSG_ERROR([babeltrace requested but not found]) 39 | ]) 40 | ]) 41 | AM_CONDITIONAL([WITH_BABEL], [test "x$have_babeltrace" = "xyes"]) 42 | 43 | # Compiler flags 44 | 45 | AC_SUBST(AM_CXXFLAGS) 46 | AM_CXXFLAGS="${AM_CXXFLAGS}" 47 | 48 | AC_CONFIG_FILES([Makefile 49 | blkin.pc 50 | blkin.spec]) 51 | 52 | AC_OUTPUT 53 | -------------------------------------------------------------------------------- /debian/blkin-babeltrace.dirs.in: -------------------------------------------------------------------------------- 1 | @PYTHONDIR@/zipkin_logic 2 | @PYTHONDIR@/scribe_client 3 | -------------------------------------------------------------------------------- /debian/blkin-babeltrace.install.in: -------------------------------------------------------------------------------- 1 | /usr/bin/babeltrace_json 2 | /usr/bin/babeltrace_zipkin 3 | @PYTHONDIR@/zipkin_logic/*.py 4 | @PYTHONDIR@/scribe_client/*.py 5 | -------------------------------------------------------------------------------- /debian/blkin-dev.dirs: -------------------------------------------------------------------------------- 1 | usr/lib 2 | usr/include/blkin 3 | -------------------------------------------------------------------------------- /debian/blkin-dev.install: -------------------------------------------------------------------------------- 1 | usr/include/blkin/* 2 | usr/lib/*/pkgconfig/blkin.pc 3 | usr/lib/*/lib*.a 4 | -------------------------------------------------------------------------------- /debian/blkin.dirs: -------------------------------------------------------------------------------- 1 | usr/lib 2 | -------------------------------------------------------------------------------- /debian/blkin.install: -------------------------------------------------------------------------------- 1 | usr/lib/*/lib*so* 2 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | blkin (0.1-1) experimental; urgency=low 2 | 3 | * Initial release 4 | 5 | -- Andrew Shewmaker Thu, 06 Nov 2014 13:55:44 -0800 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: blkin 2 | Priority: optional 3 | Maintainer: Andrew Shewmaker 4 | Build-Depends: debhelper (>= 9), libboost-all-dev, lttng-tools, liblttng-ust-dev 5 | Standards-Version: 3.9.5 6 | Section: libs 7 | Homepage: https://github.com/marioskogias/blkin 8 | Vcs-Git: https://github.com/agshew/blkin.git 9 | Vcs-Browser: https://github.com/agshew/blkin 10 | 11 | Package: blkin-dev 12 | Section: libdevel 13 | Architecture: any 14 | Depends: blkin (= ${binary:Version}), ${misc:Depends} 15 | Description: Support for developing programs using the blkin tracing library 16 | blkin is a C/C++ library that enables you to get traces from C/C++ applications 17 | according to the tracing semantics mentioned in the Dapper paper and 18 | implemented in Zipkin 19 | . 20 | As a tracing backend blkin uses LTTng 21 | 22 | Package: blkin 23 | Architecture: any 24 | Depends: ${shlibs:Depends}, ${misc:Depends} 25 | Description: Dapper-style tracing library to be used with Zipkin 26 | blkin is a C/C++ library that enables you to get traces from C/C++ applications 27 | according to the tracing semantics mentioned in the Dapper paper and 28 | implemented in Zipkin 29 | . 30 | As a tracing backend blkin uses LTTng 31 | 32 | Package: blkin-babeltrace 33 | Section: utils 34 | Architecture: any 35 | Depends: blkin (= ${binary:Version}), ${misc:Depends}, python, python3-babeltrace 36 | Description: Translate and send traces to Zipkin and Scribe for visualization 37 | Use babeltrace_zipkin.py to send blkin traces to Zipkin. 38 | Use babeltrace_json.py to send any LTTng traces to a Scribe server. 39 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: blkin 3 | Source: https://github.com/marioskogias/blkin/blob/master/COPYRIGHT 4 | 5 | Files: * 6 | Copyright: 2014 Marios Kogias 7 | License: BSD 8 | Copyright 2014 Marios Kogias 9 | All rights reserved. 10 | . 11 | Redistribution and use in source and binary forms, with or 12 | without modification, are permitted provided that the following 13 | conditions are met: 14 | . 15 | 1. Redistributions of source code must retain the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer. 18 | 2. Redistributions in binary form must reproduce the above 19 | copyright notice, this list of conditions and the following 20 | disclaimer in the documentation and/or other materials 21 | provided with the distribution. 22 | . 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS 24 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 30 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 | POSSIBILITY OF SUCH DAMAGE. 35 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README.md 2 | -------------------------------------------------------------------------------- /debian/postinst.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "postinst $@" 5 | 6 | (python -m compileall -q -f "@PYTHONDIR@/zipkin_logic/" || /bin/true) 7 | (python -m compileall -q -f "@PYTHONDIR@/scribe_client/" || /bin/true) 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /debian/postrm.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "postrm $@" 5 | 6 | (rm -rf "@PYTHONDIR@/zipkin_logic/" || /bin/true) 7 | (rm -rf "@PYTHONDIR@/scribe_client/" || /bin/true) 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # See debhelper(7) (uncomment to enable) 3 | # output every command that modifies files on the build system. 4 | #DH_VERBOSE = 1 5 | 6 | DEB_BUILD_OPTIONS = nocheck 7 | 8 | # see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* 9 | DPKG_EXPORT_BUILDFLAGS = 1 10 | include /usr/share/dpkg/default.mk 11 | 12 | # see FEATURE AREAS in dpkg-buildflags(1) 13 | #export DEB_BUILD_MAINT_OPTIONS = hardening=+all 14 | 15 | # see ENVIRONMENT in dpkg-buildflags(1) 16 | # package maintainers to append CFLAGS 17 | #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic 18 | # package maintainers to append LDFLAGS 19 | #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed 20 | 21 | 22 | # main packaging script based on dh7 syntax 23 | %: 24 | dh $@ 25 | 26 | # debmake generated override targets 27 | #override_dh_auto_configure: 28 | # dh_auto_configure -- \ 29 | # -without-babeltrace 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /m4/ax_python_module.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_python_module.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_PYTHON_MODULE(modname[, fatal]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Checks for Python module. 12 | # 13 | # If fatal is non-empty then absence of a module will trigger an error. 14 | # 15 | # LICENSE 16 | # 17 | # Copyright (c) 2008 Andrew Collier 18 | # 19 | # Copying and distribution of this file, with or without modification, are 20 | # permitted in any medium without royalty provided the copyright notice 21 | # and this notice are preserved. This file is offered as-is, without any 22 | # warranty. 23 | 24 | #serial 6 25 | 26 | AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE]) 27 | AC_DEFUN([AX_PYTHON_MODULE],[ 28 | if test -z $PYTHON; 29 | then 30 | PYTHON="python" 31 | fi 32 | PYTHON_NAME=`basename $PYTHON` 33 | AC_MSG_CHECKING($PYTHON_NAME module: $1) 34 | $PYTHON -c "import $1" 2>/dev/null 35 | if test $? -eq 0; 36 | then 37 | AC_MSG_RESULT(yes) 38 | eval AS_TR_CPP(HAVE_PYMOD_$1)=yes 39 | else 40 | AC_MSG_RESULT(no) 41 | eval AS_TR_CPP(HAVE_PYMOD_$1)=no 42 | # 43 | if test -n "$2" 44 | then 45 | AC_MSG_ERROR(failed to find required module $1) 46 | exit 1 47 | fi 48 | fi 49 | ]) 50 | -------------------------------------------------------------------------------- /src/blkin-front.c: -------------------------------------------------------------------------------- 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 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include /* srand, rand */ 36 | #include /* time */ 37 | #include 38 | #include 39 | 40 | /* Function pointers to be resolved during initialization */ 41 | int (*blkin_init_new_trace)(struct blkin_trace *new_trace, char *name, 42 | struct blkin_endpoint *endpoint); 43 | 44 | int (*blkin_init_child)(struct blkin_trace *child, struct blkin_trace *parent, 45 | struct blkin_endpoint *endpoint, char *child_name); 46 | 47 | int (*blkin_init_child_info)(struct blkin_trace *child, 48 | struct blkin_trace_info *info, struct blkin_endpoint *endpoint, 49 | char *child_name); 50 | 51 | int (*blkin_init_endpoint)(struct blkin_endpoint * endp, char *ip, 52 | int port, char *name); 53 | 54 | int (*blkin_init_string_annotation)(struct blkin_annotation *annotation, 55 | char *key, char *val, struct blkin_endpoint * endpoint); 56 | 57 | int (*blkin_init_timestamp_annotation)(struct blkin_annotation *annot, 58 | char *event, struct blkin_endpoint * endpoint); 59 | 60 | int (*blkin_record)(struct blkin_trace *trace, 61 | struct blkin_annotation *annotation); 62 | 63 | int (*blkin_get_trace_info)(struct blkin_trace *trace, 64 | struct blkin_trace_info *info); 65 | 66 | int (*blkin_set_trace_info)(struct blkin_trace *trace, 67 | struct blkin_trace_info *info); 68 | int (*blkin_pack_trace_info)(struct blkin_trace_info *info, 69 | struct blkin_trace_info_packed *pinfo); 70 | 71 | int (*blkin_unpack_trace_info)(struct blkin_trace_info_packed *pinfo, 72 | struct blkin_trace_info *info); 73 | 74 | static int resolve_symbols() 75 | { 76 | void *handle; 77 | char *error; 78 | 79 | handle = dlopen("libzipkin-c.so", RTLD_LAZY); 80 | if (!handle) { 81 | fprintf(stderr, "%s\n", dlerror()); 82 | return -ENOENT; 83 | } 84 | dlerror(); 85 | 86 | *(void **) (&blkin_init_new_trace) = dlsym(handle, "_blkin_init_new_trace"); 87 | if ((error = dlerror()) != NULL) { 88 | fprintf(stderr, "%s\n", error); 89 | return -ENXIO; 90 | } 91 | 92 | *(void **) (&blkin_init_child) = dlsym(handle, "_blkin_init_child"); 93 | if ((error = dlerror()) != NULL) { 94 | fprintf(stderr, "%s\n", error); 95 | return -ENXIO; 96 | } 97 | 98 | *(void **) (&blkin_init_child_info) = dlsym(handle, "_blkin_init_child_info"); 99 | if ((error = dlerror()) != NULL) { 100 | fprintf(stderr, "%s\n", error); 101 | return -ENXIO; 102 | } 103 | 104 | *(void **) (&blkin_init_endpoint) = dlsym(handle, "_blkin_init_endpoint"); 105 | if ((error = dlerror()) != NULL) { 106 | fprintf(stderr, "%s\n", error); 107 | return -ENXIO; 108 | } 109 | 110 | *(void **) (&blkin_init_string_annotation) = dlsym(handle, "_blkin_init_string_annotation"); 111 | if ((error = dlerror()) != NULL) { 112 | fprintf(stderr, "%s\n", error); 113 | return -ENXIO; 114 | } 115 | 116 | *(void **) (&blkin_init_timestamp_annotation) = dlsym(handle, "_blkin_init_timestamp_annotation"); 117 | if ((error = dlerror()) != NULL) { 118 | fprintf(stderr, "%s\n", error); 119 | return -ENXIO; 120 | } 121 | 122 | *(void **) (&blkin_record) = dlsym(handle, "_blkin_record"); 123 | if ((error = dlerror()) != NULL) { 124 | fprintf(stderr, "%s\n", error); 125 | return -ENXIO; 126 | } 127 | 128 | *(void **) (&blkin_set_trace_info) = dlsym(handle, "_blkin_set_trace_info"); 129 | if ((error = dlerror()) != NULL) { 130 | fprintf(stderr, "%s\n", error); 131 | return -ENXIO; 132 | } 133 | 134 | *(void **) (&blkin_get_trace_info) = dlsym(handle, "_blkin_get_trace_info"); 135 | if ((error = dlerror()) != NULL) { 136 | fprintf(stderr, "%s\n", error); 137 | return -ENXIO; 138 | } 139 | 140 | *(void **) (&blkin_pack_trace_info) = dlsym(handle, "_blkin_pack_trace_info"); 141 | if ((error = dlerror()) != NULL) { 142 | fprintf(stderr, "%s\n", error); 143 | return -ENXIO; 144 | } 145 | 146 | *(void **) (&blkin_unpack_trace_info) = dlsym(handle, "_blkin_unpack_trace_info"); 147 | if ((error = dlerror()) != NULL) { 148 | fprintf(stderr, "%s\n", error); 149 | return -ENXIO; 150 | } 151 | 152 | return 0; 153 | } 154 | 155 | static pthread_mutex_t blkin_init_mutex = PTHREAD_MUTEX_INITIALIZER; 156 | static int initialized = 0; 157 | 158 | int blkin_init(void) 159 | { 160 | /* 161 | * Initialize srand with sth appropriete 162 | * time is not good for archipelago: several deamons -> same timstamp 163 | */ 164 | int inf, seed; 165 | inf = open("/dev/urandom", O_RDONLY); //file descriptor 1 166 | read(inf, &seed, sizeof(int)); 167 | srand(seed); 168 | int ret; 169 | pthread_mutex_lock(&blkin_init_mutex); 170 | if (!initialized) { 171 | ret = resolve_symbols(); 172 | if (ret >= 0) { 173 | initialized = 1; 174 | } 175 | } 176 | pthread_mutex_unlock(&blkin_init_mutex); 177 | return ret; 178 | 179 | } 180 | -------------------------------------------------------------------------------- /src/blkin-front.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 | #include 31 | 32 | /* Define extern function pointers to be resolved during initialization */ 33 | extern int (*blkin_init_new_trace)(struct blkin_trace *new_trace, char *name, 34 | struct blkin_endpoint *endpoint); 35 | 36 | extern int (*blkin_init_child)(struct blkin_trace *child, struct blkin_trace *parent, 37 | struct blkin_endpoint *endpoint, char *child_name); 38 | 39 | extern int (*blkin_init_child_info)(struct blkin_trace *child, 40 | struct blkin_trace_info *info, struct blkin_endpoint *endpoint, 41 | char *child_name); 42 | 43 | extern int (*blkin_init_endpoint)(struct blkin_endpoint * endp, char *ip, 44 | int port, char *name); 45 | 46 | extern int (*blkin_init_string_annotation)(struct blkin_annotation *annotation, 47 | char *key, char *val, struct blkin_endpoint * endpoint); 48 | 49 | extern int (*blkin_init_timestamp_annotation)(struct blkin_annotation *annot, 50 | char *event, struct blkin_endpoint * endpoint); 51 | 52 | extern int (*blkin_record)(struct blkin_trace *trace, 53 | struct blkin_annotation *annotation); 54 | 55 | extern int (*blkin_get_trace_info)(struct blkin_trace *trace, 56 | struct blkin_trace_info *info); 57 | 58 | extern int (*blkin_set_trace_info)(struct blkin_trace *trace, 59 | struct blkin_trace_info *info); 60 | extern int (*blkin_pack_trace_info)(struct blkin_trace_info *info, 61 | struct blkin_trace_info_packed *pinfo); 62 | 63 | extern int (*blkin_unpack_trace_info)(struct blkin_trace_info_packed *pinfo, 64 | struct blkin_trace_info *info); 65 | 66 | int blkin_init(void); 67 | -------------------------------------------------------------------------------- /src/tests/test.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 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define SOCK_PATH "socket" 39 | 40 | struct message { 41 | int actual_message; 42 | struct blkin_trace_info trace_info; 43 | message(int s) : actual_message(s) {}; 44 | message() {} 45 | }; 46 | 47 | class Parent { 48 | private: 49 | int s, s2; 50 | ZTracer::ZTraceEndpointRef e; 51 | ZTracer::ZTraceRef tr; 52 | public: 53 | Parent() 54 | { 55 | e = ZTracer::create_ZTraceEndpoint("0.0.0.0", 1, "parent"); 56 | connect(); 57 | } 58 | void operator()() 59 | { 60 | struct sockaddr_un remote; 61 | int t; 62 | std::cout << "I am parent process : " << getpid() << std::endl; 63 | 64 | /* Wait for connection */ 65 | t = sizeof(remote); 66 | if ((s2 = accept(s, (struct sockaddr *)&remote, (socklen_t *)&t)) == -1) { 67 | std::cerr << "accept" << std::endl; 68 | exit(1); 69 | } 70 | 71 | std::cerr << "Connected" << std::endl; 72 | 73 | for (int i=0;i<10;i++) { 74 | process(); 75 | 76 | wait_response(); 77 | 78 | /*Log received*/ 79 | tr->event("parent end"); 80 | } 81 | } 82 | 83 | void process() 84 | { 85 | struct message msg(rand()); 86 | /*Init trace*/ 87 | tr = ZTracer::create_ZTrace("parent process", e); 88 | /*Annotate*/ 89 | tr->event("parent start"); 90 | /*Set trace info to the message*/ 91 | tr->get_trace_info(&msg.trace_info); 92 | 93 | /*send*/ 94 | send(s2, &msg, sizeof(struct message), 0); 95 | } 96 | 97 | void wait_response() 98 | { 99 | char ack; 100 | recv(s2, &ack, 1, 0); 101 | } 102 | 103 | void connect() 104 | { 105 | /*create and bind socket*/ 106 | int len; 107 | struct sockaddr_un local, remote; 108 | 109 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 110 | std::cerr << "socket" << std::endl; 111 | exit(1); 112 | } 113 | 114 | local.sun_family = AF_UNIX; 115 | strcpy(local.sun_path, SOCK_PATH); 116 | unlink(local.sun_path); 117 | len = strlen(local.sun_path) + sizeof(local.sun_family); 118 | if (bind(s, (struct sockaddr *)&local, len) == -1) { 119 | std::cerr << "bind" << std::endl; 120 | exit(1); 121 | } 122 | 123 | if (listen(s, 5) == -1) { 124 | std::cerr << "listen" << std::endl; 125 | exit(1); 126 | } 127 | 128 | std::cout << "Waiting for a connection..." << std::endl; 129 | } 130 | 131 | }; 132 | 133 | class Child { 134 | private: 135 | int s; 136 | ZTracer::ZTraceEndpointRef e; 137 | ZTracer::ZTraceRef tr; 138 | public: 139 | Child() 140 | { 141 | e = ZTracer::create_ZTraceEndpoint("0.0.0.1", 2, "child"); 142 | } 143 | void operator()() 144 | { 145 | /*Connect to the socket*/ 146 | soc_connect(); 147 | 148 | for (int i=0;i<10;i++) 149 | process(); 150 | } 151 | 152 | void process() 153 | { 154 | struct message msg; 155 | recv(s, &msg, sizeof(struct message), 0); 156 | 157 | tr = ZTracer::create_ZTrace("Child process", e, &msg.trace_info, true); 158 | tr->event("child start"); 159 | 160 | usleep(10); 161 | std::cout << "Message received : " << msg.actual_message << ::std::endl; 162 | tr->event("child end"); 163 | 164 | send(s, "*", 1, 0); 165 | } 166 | 167 | 168 | void soc_connect() 169 | { 170 | int len; 171 | struct sockaddr_un remote; 172 | 173 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 174 | std::cerr << "socket" << std::endl; 175 | exit(1); 176 | } 177 | 178 | std::cout << "Trying to connect...\n" << std::endl; 179 | 180 | remote.sun_family = AF_UNIX; 181 | strcpy(remote.sun_path, SOCK_PATH); 182 | len = strlen(remote.sun_path) + sizeof(remote.sun_family); 183 | if (connect(s, (struct sockaddr *)&remote, len) == -1) { 184 | std::cerr << "connect" << std::endl;; 185 | exit(1); 186 | } 187 | 188 | std::cout << "Connected" << std::endl; 189 | } 190 | 191 | }; 192 | int main(int argc, const char *argv[]) 193 | { 194 | int r = ZTracer::ztrace_init(); 195 | if (r < 0) { 196 | std::cout << "Error initializing blkin" << std::endl; 197 | return -1; 198 | } 199 | Parent p; 200 | Child c; 201 | boost::thread workerThread1(p); 202 | boost::thread workerThread2(c); 203 | workerThread1.join(); 204 | workerThread2.join(); 205 | 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /src/tests/test_p.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 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define SOCK_PATH "socket" 39 | 40 | struct message { 41 | int actual_message; 42 | struct blkin_trace_info trace_info; 43 | message(int s) : actual_message(s) {}; 44 | message() {} 45 | }; 46 | 47 | class Parent { 48 | private: 49 | int s, s2; 50 | ZTracer::ZTraceEndpointRef e; 51 | ZTracer::ZTraceRef tr; 52 | public: 53 | Parent() 54 | { 55 | e = ZTracer::create_ZTraceEndpoint("0.0.0.0", 1, "parent"); 56 | connect(); 57 | } 58 | void operator()() 59 | { 60 | struct sockaddr_un remote; 61 | int t; 62 | std::cout << "I am parent process : " << getpid() << std::endl; 63 | 64 | /* Wait for connection */ 65 | t = sizeof(remote); 66 | if ((s2 = accept(s, (struct sockaddr *)&remote, (socklen_t *)&t)) == -1) { 67 | std::cerr << "accept" << std::endl; 68 | exit(1); 69 | } 70 | 71 | std::cerr << "Connected" << std::endl; 72 | 73 | for (int i=0;i<10;i++) { 74 | process(); 75 | 76 | wait_response(); 77 | 78 | /*Log received*/ 79 | tr->event("parent end"); 80 | } 81 | } 82 | 83 | void process() 84 | { 85 | struct message msg(rand()); 86 | /*Init trace*/ 87 | tr = ZTracer::create_ZTrace("parent process", e); 88 | /*Annotate*/ 89 | tr->event("parent start"); 90 | /*Set trace info to the message*/ 91 | tr->get_trace_info(&msg.trace_info); 92 | 93 | /*send*/ 94 | send(s2, &msg, sizeof(struct message), 0); 95 | } 96 | 97 | void wait_response() 98 | { 99 | char ack; 100 | recv(s2, &ack, 1, 0); 101 | } 102 | 103 | void connect() 104 | { 105 | /*create and bind socket*/ 106 | int len; 107 | struct sockaddr_un local, remote; 108 | 109 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 110 | std::cerr << "socket" << std::endl; 111 | exit(1); 112 | } 113 | 114 | local.sun_family = AF_UNIX; 115 | strcpy(local.sun_path, SOCK_PATH); 116 | unlink(local.sun_path); 117 | len = strlen(local.sun_path) + sizeof(local.sun_family); 118 | if (bind(s, (struct sockaddr *)&local, len) == -1) { 119 | std::cerr << "bind" << std::endl; 120 | exit(1); 121 | } 122 | 123 | if (listen(s, 5) == -1) { 124 | std::cerr << "listen" << std::endl; 125 | exit(1); 126 | } 127 | 128 | std::cout << "Waiting for a connection..." << std::endl; 129 | } 130 | 131 | }; 132 | 133 | class Child { 134 | private: 135 | int s; 136 | ZTracer::ZTraceEndpointRef e; 137 | ZTracer::ZTraceRef tr; 138 | public: 139 | Child() 140 | { 141 | e = ZTracer::create_ZTraceEndpoint("0.0.0.1", 2, "child"); 142 | } 143 | void operator()() 144 | { 145 | /*Connect to the socket*/ 146 | soc_connect(); 147 | 148 | for (int i=0;i<10;i++) 149 | process(); 150 | } 151 | 152 | void process() 153 | { 154 | struct message msg; 155 | recv(s, &msg, sizeof(struct message), 0); 156 | 157 | tr = ZTracer::create_ZTrace("Child process", e, &msg.trace_info, true); 158 | tr->event("child start"); 159 | 160 | usleep(10); 161 | std::cout << "Message received : " << msg.actual_message << ::std::endl; 162 | tr->event("child end"); 163 | 164 | send(s, "*", 1, 0); 165 | } 166 | 167 | 168 | void soc_connect() 169 | { 170 | int len; 171 | struct sockaddr_un remote; 172 | 173 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 174 | std::cerr << "socket" << std::endl; 175 | exit(1); 176 | } 177 | 178 | std::cout << "Trying to connect...\n" << std::endl; 179 | 180 | remote.sun_family = AF_UNIX; 181 | strcpy(remote.sun_path, SOCK_PATH); 182 | len = strlen(remote.sun_path) + sizeof(remote.sun_family); 183 | if (connect(s, (struct sockaddr *)&remote, len) == -1) { 184 | std::cerr << "connect" << std::endl;; 185 | exit(1); 186 | } 187 | 188 | std::cout << "Connected" << std::endl; 189 | } 190 | 191 | }; 192 | int main(int argc, const char *argv[]) 193 | { 194 | if (fork()) { 195 | int r = ZTracer::ztrace_init(); 196 | if (r < 0) { 197 | std::cout << "Error initializing blkin" << std::endl; 198 | exit(1); 199 | } 200 | Parent p; 201 | p(); 202 | exit(0); 203 | } else { 204 | int r = ZTracer::ztrace_init(); 205 | if (r < 0) { 206 | std::cout << "Error initializing blkin" << std::endl; 207 | exit(1); 208 | } 209 | Child c; 210 | c(); 211 | exit(0); 212 | } 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /src/tests/testc.c: -------------------------------------------------------------------------------- 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 | /* 31 | * In this example we have 2 processes communicating over a unix socket. 32 | * We are going to trace the communication with our library 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | 44 | #define SOCK_PATH "/tmp/socket" 45 | 46 | struct message { 47 | char actual_message[20]; 48 | struct blkin_trace_info trace_info; 49 | }; 50 | 51 | void process_a() 52 | { 53 | int i, r; 54 | printf("I am process A: %d\n", getpid()); 55 | 56 | r = blkin_init(); 57 | if (r < 0) { 58 | fprintf(stderr, "Could not initialize blkin\n"); 59 | exit(1); 60 | } 61 | 62 | /*initialize endpoint*/ 63 | struct blkin_endpoint endp; 64 | blkin_init_endpoint(&endp, "10.0.0.1", 5000, "service a"); 65 | 66 | struct blkin_trace trace; 67 | struct blkin_annotation ant; 68 | struct message msg = {.actual_message = "message"}; 69 | char ack; 70 | 71 | /*create and bind socket*/ 72 | int s, s2, t, len; 73 | struct sockaddr_un local, remote; 74 | 75 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 76 | perror("socket"); 77 | exit(1); 78 | } 79 | 80 | local.sun_family = AF_UNIX; 81 | strcpy(local.sun_path, SOCK_PATH); 82 | unlink(local.sun_path); 83 | len = strlen(local.sun_path) + sizeof(local.sun_family); 84 | if (bind(s, (struct sockaddr *)&local, len) == -1) { 85 | perror("bind"); 86 | exit(1); 87 | } 88 | 89 | if (listen(s, 5) == -1) { 90 | perror("listen"); 91 | exit(1); 92 | } 93 | 94 | printf("Waiting for a connection...\n"); 95 | t = sizeof(remote); 96 | if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) { 97 | perror("accept"); 98 | exit(1); 99 | } 100 | 101 | printf("Connected.\n"); 102 | 103 | for (i=0;i<10;i++) { 104 | 105 | /*create trace*/ 106 | blkin_init_new_trace(&trace, "process a", &endp); 107 | 108 | blkin_init_timestamp_annotation(&ant, "start", &endp); 109 | blkin_record(&trace, &ant); 110 | 111 | /*set trace fields to message*/ 112 | blkin_get_trace_info(&trace, &msg.trace_info); 113 | 114 | /*send*/ 115 | send(s2, &msg, sizeof(struct message), 0); 116 | 117 | /*wait for ack*/ 118 | recv(s2, &ack, 1, 0); 119 | 120 | /*create annotation and log*/ 121 | blkin_init_timestamp_annotation(&ant, "end", &endp); 122 | blkin_record(&trace, &ant); 123 | } 124 | close(s2); 125 | } 126 | 127 | void process_b() 128 | { 129 | int i, r; 130 | printf("I am process B: %d\n", getpid()); 131 | 132 | r = blkin_init(); 133 | if (r < 0) { 134 | fprintf(stderr, "Could not initialize blkin\n"); 135 | exit(1); 136 | } 137 | /*initialize endpoint*/ 138 | struct blkin_endpoint endp; 139 | blkin_init_endpoint(&endp, "10.0.0.2", 5001, "service b"); 140 | 141 | struct blkin_trace trace; 142 | struct blkin_annotation ant; 143 | struct message msg; 144 | int s, t, len; 145 | struct sockaddr_un remote; 146 | 147 | /*Connect*/ 148 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 149 | perror("socket"); 150 | exit(1); 151 | } 152 | 153 | printf("Trying to connect...\n"); 154 | usleep(1000); 155 | 156 | remote.sun_family = AF_UNIX; 157 | strcpy(remote.sun_path, SOCK_PATH); 158 | len = strlen(remote.sun_path) + sizeof(remote.sun_family); 159 | if (connect(s, (struct sockaddr *)&remote, len) == -1) { 160 | perror("connect"); 161 | exit(1); 162 | } 163 | 164 | printf("Connected.\n"); 165 | 166 | for (i=0;i<10;i++) { 167 | recv(s, &msg, sizeof(struct message), 0); 168 | 169 | /*create child trace*/ 170 | blkin_init_child_info(&trace, &msg.trace_info, &endp, "process b"); 171 | 172 | /*create annotation and log*/ 173 | blkin_init_timestamp_annotation(&ant, "start", &endp); 174 | blkin_record(&trace, &ant); 175 | 176 | /*Process...*/ 177 | usleep(10); 178 | printf("Message received %s\n", msg.actual_message); 179 | 180 | /*create annotation and log*/ 181 | blkin_init_timestamp_annotation(&ant, "end", &endp); 182 | blkin_record(&trace, &ant); 183 | 184 | /*send ack*/ 185 | send(s, "*", 1, 0); 186 | } 187 | } 188 | 189 | 190 | int main() 191 | { 192 | if (fork()){ 193 | process_a(); 194 | exit(0); 195 | } 196 | else{ 197 | process_b(); 198 | exit(0); 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/tp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tp.c 3 | * 4 | * Copyright (c) 2011 Mathieu Desnoyers 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Defining macro creates the code objects of the traceprobes, only do 27 | * it once per file 28 | */ 29 | #define TRACEPOINT_CREATE_PROBES 30 | /* 31 | * The header containing our TRACEPOINT_EVENTs. 32 | */ 33 | #include 34 | -------------------------------------------------------------------------------- /src/zipkin_c.c: -------------------------------------------------------------------------------- 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 | 33 | #define TRACEPOINT_DEFINE 34 | #include 35 | 36 | const char *default_ip = "NaN"; 37 | const char *default_name = "NoName"; 38 | 39 | int64_t random_big() 40 | { 41 | int64_t a; 42 | a = rand(); 43 | a = a << 32; 44 | int b = rand(); 45 | a = a + b; 46 | if (a<0) 47 | a = !a; 48 | return a; 49 | }; 50 | 51 | int _blkin_init_new_trace(struct blkin_trace *new_trace, char *service, 52 | struct blkin_endpoint *endpoint) 53 | { 54 | int res; 55 | if (!new_trace) { 56 | res = -EINVAL; 57 | goto OUT; 58 | } 59 | new_trace->name = service; 60 | new_trace->info.trace_id = random_big(); 61 | new_trace->info.span_id = random_big(); 62 | new_trace->info.parent_span_id = 0; 63 | new_trace->trace_endpoint = endpoint; 64 | res = 0; 65 | 66 | OUT: 67 | return res; 68 | } 69 | 70 | int _blkin_init_child_info(struct blkin_trace *child, 71 | struct blkin_trace_info *parent_info, struct blkin_endpoint *endpoint, 72 | char *child_name) 73 | { 74 | int res; 75 | if ((!child) || (!parent_info) || (!endpoint)){ 76 | res = -EINVAL; 77 | goto OUT; 78 | } 79 | child->info.trace_id = parent_info->trace_id; 80 | child->info.span_id = random_big(); 81 | child->info.parent_span_id = parent_info->span_id; 82 | child->name = child_name; 83 | child->trace_endpoint = endpoint; 84 | res = 0; 85 | 86 | OUT: 87 | return res; 88 | } 89 | 90 | int _blkin_init_child(struct blkin_trace *child, struct blkin_trace *parent, 91 | struct blkin_endpoint *endpoint, char *child_name) 92 | { 93 | int res; 94 | if (!parent) { 95 | res = -EINVAL; 96 | goto OUT; 97 | } 98 | if (!endpoint) 99 | endpoint = parent->trace_endpoint; 100 | if (_blkin_init_child_info(child, &parent->info, endpoint, child_name) != 0){ 101 | res = -EINVAL; 102 | goto OUT; 103 | } 104 | res = 0; 105 | 106 | OUT: 107 | return res; 108 | } 109 | 110 | int _blkin_init_endpoint(struct blkin_endpoint *endp, char *ip, int port, 111 | char *name) 112 | { 113 | int res; 114 | if (!endp){ 115 | res = -EINVAL; 116 | goto OUT; 117 | } 118 | if (!ip) 119 | ip = default_ip; 120 | 121 | endp->ip = ip; 122 | endp->port = port; 123 | endp->name = name; 124 | res = 0; 125 | 126 | OUT: 127 | return res; 128 | } 129 | 130 | int _blkin_init_string_annotation(struct blkin_annotation *annotation, char *key, 131 | char *val, struct blkin_endpoint *endpoint) 132 | { 133 | int res; 134 | if ((!annotation) || (!key) || (!val)){ 135 | res = -EINVAL; 136 | goto OUT; 137 | } 138 | annotation->type = ANNOT_STRING; 139 | annotation->key = key; 140 | annotation->val = val; 141 | annotation->annotation_endpoint = endpoint; 142 | res = 0; 143 | 144 | OUT: 145 | return res; 146 | } 147 | 148 | int _blkin_init_timestamp_annotation(struct blkin_annotation *annotation, 149 | char *event, struct blkin_endpoint *endpoint) 150 | { 151 | int res; 152 | if ((!annotation) || (!event)){ 153 | res = -EINVAL; 154 | goto OUT; 155 | } 156 | annotation->type = ANNOT_TIMESTAMP; 157 | annotation->val = event; 158 | annotation->annotation_endpoint = endpoint; 159 | res = 0; 160 | 161 | OUT: 162 | return res; 163 | } 164 | 165 | int _blkin_record(struct blkin_trace *trace, struct blkin_annotation *annotation) 166 | { 167 | int res; 168 | if ((!annotation) || (!trace)){ 169 | res = -EINVAL; 170 | goto OUT; 171 | } 172 | if (!annotation->annotation_endpoint && trace->trace_endpoint) 173 | annotation->annotation_endpoint = trace->trace_endpoint; 174 | if (!trace->name) 175 | trace->name = default_name; 176 | if (!annotation->annotation_endpoint->ip) 177 | annotation->annotation_endpoint->ip = default_ip; 178 | if (!annotation->annotation_endpoint->name) 179 | annotation->annotation_endpoint->name = default_name; 180 | 181 | if (annotation->type == ANNOT_STRING) { 182 | if ((!annotation->key) || (!annotation->val)) { 183 | res = -EINVAL; 184 | goto OUT; 185 | } 186 | tracepoint(zipkin, keyval, trace->name, 187 | annotation->annotation_endpoint->name, 188 | annotation->annotation_endpoint->port, 189 | annotation->annotation_endpoint->ip, 190 | trace->info.trace_id, trace->info.span_id, 191 | trace->info.parent_span_id, 192 | annotation->key, annotation->val); 193 | } 194 | else { 195 | if (!annotation->val) { 196 | res = -EINVAL; 197 | goto OUT; 198 | } 199 | tracepoint(zipkin, timestamp , trace->name, 200 | annotation->annotation_endpoint->name, 201 | annotation->annotation_endpoint->port, 202 | annotation->annotation_endpoint->ip, 203 | trace->info.trace_id, trace->info.span_id, 204 | trace->info.parent_span_id, 205 | annotation->val); 206 | } 207 | res = 0; 208 | OUT: 209 | return res; 210 | } 211 | 212 | int _blkin_get_trace_info(struct blkin_trace *trace, 213 | struct blkin_trace_info *info) 214 | { 215 | int res; 216 | if ((!trace) || (!info)){ 217 | res = -EINVAL; 218 | goto OUT; 219 | } 220 | 221 | *info = trace->info; 222 | OUT: 223 | return res; 224 | } 225 | 226 | int _blkin_set_trace_info(struct blkin_trace *trace, 227 | struct blkin_trace_info *info) 228 | { 229 | int res; 230 | if ((!trace) || (!info)){ 231 | res = -EINVAL; 232 | goto OUT; 233 | } 234 | 235 | trace->info = *info; 236 | 237 | OUT: 238 | return res; 239 | } 240 | 241 | int _blkin_pack_trace_info(struct blkin_trace_info *info, 242 | struct blkin_trace_info_packed *pinfo) 243 | { 244 | if (!info || !pinfo) { 245 | return -EINVAL; 246 | } 247 | 248 | info->trace_id = __be64_to_cpu(pinfo->trace_id); 249 | info->span_id = __be64_to_cpu(pinfo->span_id); 250 | info->parent_span_id = __be64_to_cpu(pinfo->parent_span_id); 251 | 252 | return 1; 253 | } 254 | 255 | int _blkin_unpack_trace_info(struct blkin_trace_info_packed *pinfo, 256 | struct blkin_trace_info *info) 257 | { 258 | if (!info || !pinfo) { 259 | return -EINVAL; 260 | } 261 | 262 | pinfo->trace_id = __cpu_to_be64(info->trace_id); 263 | pinfo->span_id = __cpu_to_be64(info->span_id); 264 | pinfo->parent_span_id = __cpu_to_be64(info->parent_span_id); 265 | 266 | return 1; 267 | } 268 | -------------------------------------------------------------------------------- /src/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 | #include 31 | #include 32 | 33 | #define BLKIN_TIMESTAMP(trace, endp, event) \ 34 | do { \ 35 | struct blkin_annotation __annot; \ 36 | blkin_init_timestamp_annotation(&__annot, event, endp); \ 37 | blkin_record(trace, &__annot); \ 38 | } while (0); 39 | 40 | #define BLKIN_KEYVAL(trace, endp, key, val) \ 41 | do { \ 42 | struct blkin_annotation __annot; \ 43 | blkin_init_string_annotation(&__annot, key, val, endp); \ 44 | blkin_record(trace, &__annot); \ 45 | } while (0); 46 | 47 | /** 48 | * @struct blkin_endpoint 49 | * Information about an endpoint of our instrumented application where 50 | * annotations take place 51 | */ 52 | struct blkin_endpoint { 53 | char *ip; 54 | int port; 55 | char *name; 56 | }; 57 | 58 | /** 59 | * @struct blkin_trace_info 60 | * The information exchanged between different layers offering the needed 61 | * trace semantics 62 | */ 63 | struct blkin_trace_info { 64 | int64_t trace_id; 65 | int64_t span_id; 66 | int64_t parent_span_id; 67 | }; 68 | 69 | /** 70 | * @struct blkin_trace_info_packed 71 | * 72 | * Packed version of the struct blkin_trace_info. Usefull when sending over 73 | * network. 74 | * 75 | */ 76 | struct blkin_trace_info_packed { 77 | __be64 trace_id; 78 | __be64 span_id; 79 | __be64 parent_span_id; 80 | } __attribute__((packed)); 81 | 82 | 83 | /** 84 | * @struct blkin_trace 85 | * Struct used to define the context in which an annotation happens 86 | */ 87 | struct blkin_trace { 88 | char *name; 89 | struct blkin_trace_info info; 90 | struct blkin_endpoint *trace_endpoint; 91 | }; 92 | 93 | /** 94 | * @typedef blkin_annotation_type 95 | * There are 2 kinds of annotation key-val and timestamp 96 | */ 97 | typedef enum { 98 | ANNOT_STRING = 0, 99 | ANNOT_TIMESTAMP 100 | } blkin_annotation_type; 101 | 102 | /** 103 | * @struct blkin_annotation 104 | * Struct carrying information about an annotation. This information can either 105 | * be key-val or that a specific event happened 106 | */ 107 | struct blkin_annotation { 108 | blkin_annotation_type type; 109 | char *key; 110 | char *val; 111 | struct blkin_endpoint *annotation_endpoint; 112 | }; 113 | 114 | #if 0 115 | /** 116 | * Initialize a new blkin_trace with the information given. The new trace will 117 | * have no parent so the parent id will be zero. 118 | * 119 | * @param new_trace the blkin_trace to be initialized 120 | * @param name the trace's name 121 | * @param endpoint a pointer to a blkin_endpoint struct that contains info about 122 | * where the specif trace takes place 123 | * 124 | * @returns 1 if success -1 if error 125 | */ 126 | int _blkin_init_new_trace(struct blkin_trace *new_trace, char *name, 127 | struct blkin_endpoint *endpoint); 128 | 129 | /** 130 | * Initialize a blkin_trace as a child of the given parent bkin_trace. The child 131 | * trace will have the same trace_id, new span_id and parent_span_id its 132 | * parent's span_id. 133 | * 134 | * @param child the blkin_trace to be initialized 135 | * @param parent the parent blkin_trace 136 | * @param child_name the blkin_trace name of the child 137 | * 138 | * @returns 1 if success -1 if error 139 | */ 140 | int _blkin_init_child(struct blkin_trace *child, struct blkin_trace *parent, 141 | struct blkin_endpoint *endpoint, 142 | char *child_name); 143 | 144 | /** 145 | * Initialize a blkin_trace struct and set the blkin_trace_info field to be 146 | * child of the given blkin_trace_info. This means 147 | * Same trace_id 148 | * Different span_id 149 | * Child's parent_span_id == parent's span_id 150 | * 151 | * @param child the new child blkin_trace_info 152 | * @param info the parent's blkin_trace_info struct 153 | * @param child_name the blkin_trace struct name field 154 | * 155 | * @returns 1 if success -1 if error 156 | */ 157 | int _blkin_init_child_info(struct blkin_trace *child, 158 | struct blkin_trace_info *info, struct blkin_endpoint *endpoint, 159 | char *child_name); 160 | 161 | /** 162 | * Initialize a blkin_endpoint struct with the information given 163 | * 164 | * @param endp the endpoint to be initialized 165 | * @param ip the ip address of the specific endpoint 166 | * @param port the TCP/UDP port of the specific endpoint 167 | * @param name the name of the service running on the specific endpoint 168 | * 169 | * @returns 1 if success -1 if error 170 | */ 171 | int _blkin_init_endpoint(struct blkin_endpoint * endp, char *ip, int port, 172 | char *name); 173 | 174 | /** 175 | * Initialize a key-value blkin_annotation 176 | * 177 | * @param annotation the annotation to be initialized 178 | * @param key the annotation's key 179 | * @param val the annotation's value 180 | * @param endpoint where did this annotation occured 181 | * 182 | * @returns 1 if success -1 if error 183 | */ 184 | int _blkin_init_string_annotation(struct blkin_annotation *annotation, char *key, 185 | char *val, 186 | struct blkin_endpoint * endpoint); 187 | 188 | /** 189 | * Initialize a timestamp blkin_annotation 190 | * 191 | * @param annotation the annotation to be initialized 192 | * @param event the event happened to be annotated 193 | * @param endpoint where did this annotation occured 194 | * 195 | * @returns 1 if success -1 if error 196 | */ 197 | int _blkin_init_timestamp_annotation(struct blkin_annotation *annot, char *event, 198 | struct blkin_endpoint * endpoint); 199 | 200 | /** 201 | * Log an annotation in terms of a specific trace 202 | * 203 | * @param trace the trace to which the annotation belongs 204 | * @param annotation the annotation to be logged 205 | * 206 | * @returns 1 if success -1 if error 207 | */ 208 | int _blkin_record(struct blkin_trace *trace, 209 | struct blkin_annotation *annotation); 210 | 211 | /** 212 | * Copy a blkin_trace_info struct into a the field info of a blkin_trace struct 213 | * 214 | * @param trace the destination 215 | * @param info where to copy from 216 | * 217 | * @returns 1 if success -1 if error 218 | */ 219 | int _blkin_get_trace_info(struct blkin_trace *trace, 220 | struct blkin_trace_info *info); 221 | 222 | /** 223 | * Copy the blkin_trace_info from a blkin_trace to another blkin_trace_info 224 | * 225 | * @param trace the trace with the essential info 226 | * @param info the destination 227 | * 228 | * @returns 1 if success -1 if error 229 | */ 230 | int _blkin_set_trace_info(struct blkin_trace *trace, 231 | struct blkin_trace_info *info); 232 | 233 | 234 | /** 235 | * Convert a blkin_trace_info to the packed version. 236 | * 237 | * @param info The unpacked trace info. 238 | * @param pinfo The provided packed version to be initialized. 239 | * 240 | * @returns 1 on success, -1 on error 241 | */ 242 | int _blkin_pack_trace_info(struct blkin_trace_info *info, 243 | struct blkin_trace_info_packed *pinfo); 244 | 245 | /** 246 | * Convert a packed blkin_trace_info to the unpacked version. 247 | * 248 | * @param pinfo The provided packed version to be unpacked. 249 | * @param info The unpacked trace info. 250 | * 251 | * @returns 1 on success, -1 on error 252 | */ 253 | int _blkin_unpack_trace_info(struct blkin_trace_info_packed *pinfo, 254 | struct blkin_trace_info *info); 255 | 256 | #endif 257 | -------------------------------------------------------------------------------- /src/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 *, trace_name, char *, service, 20 | int, port, char *, ip, long, trace, 21 | long, span, long, parent_span, 22 | char *, key, 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, 54 | TRACE_WARNING) 55 | 56 | /* 57 | * In this event we follow the same semantics but we trace timestamp annotations 58 | */ 59 | 60 | TRACEPOINT_EVENT( 61 | zipkin, 62 | timestamp, 63 | TP_ARGS(char *, trace_name, char *, service, 64 | int, port, char *, ip, long, trace, 65 | long, span, long, parent_span, 66 | char *, event), 67 | 68 | TP_FIELDS( 69 | ctf_string(trace_name, trace_name) 70 | ctf_string(service_name, service) 71 | ctf_integer(int, port_no, port) 72 | ctf_string(ip, ip) 73 | ctf_integer(long, trace_id, trace) 74 | ctf_integer(long, span_id, span) 75 | ctf_integer(long, parent_span_id, parent_span) 76 | ctf_string(event, event) 77 | ) 78 | ) 79 | TRACEPOINT_LOGLEVEL( 80 | zipkin, 81 | timestamp, 82 | TRACE_WARNING) 83 | #endif /* _ZIPKIN_H */ 84 | 85 | #include 86 | 87 | -------------------------------------------------------------------------------- /src/ztracer.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 31 | #include 32 | 33 | namespace ZTracer { 34 | int ztrace_init(void) 35 | { 36 | return blkin_init(); 37 | } 38 | 39 | char * to_cstr(string &s) 40 | { 41 | char *cstr = new char [s.length()+1]; 42 | strcpy(cstr, s.c_str()); 43 | 44 | return cstr; 45 | } 46 | 47 | char * ostr_to_cstr(ostringstream &stream) 48 | { 49 | string s; 50 | s = stream.str(); 51 | 52 | return to_cstr(s); 53 | } 54 | int ZTrace::keyval(string key, string val) 55 | { 56 | BLKIN_KEYVAL(&trace, ep->get_blkin_ep(), (char *)key.c_str(), 57 | (char *)val.c_str()); 58 | return 0; 59 | } 60 | 61 | int ZTrace::event(string event) 62 | { 63 | BLKIN_TIMESTAMP(&trace, ep->get_blkin_ep(), (char *)event.c_str()); 64 | return 0; 65 | } 66 | 67 | int ZTrace::keyval(string key, string val, ZTraceEndpointRef ep) 68 | { 69 | BLKIN_KEYVAL(&trace, ep->get_blkin_ep(), (char *)key.c_str(), 70 | (char *)val.c_str()); 71 | return 0; 72 | } 73 | 74 | int ZTrace::event(string event, ZTraceEndpointRef ep) 75 | { 76 | BLKIN_TIMESTAMP(&trace, ep->get_blkin_ep(), (char *)event.c_str()); 77 | return 0; 78 | } 79 | 80 | 81 | ZTraceEndpointRef create_ZTraceEndpoint(string ip, int port, string name) 82 | { 83 | boost::shared_ptr ret(new ZTraceEndpoint(ip, port, name)); 84 | return ret; 85 | } 86 | 87 | ZTraceRef create_ZTrace(string name, ZTraceEndpointRef ep) 88 | { 89 | boost::shared_ptr ret(new ZTrace(name, ep)); 90 | return ret; 91 | } 92 | 93 | ZTraceRef create_ZTrace(string name, ZTraceRef t) 94 | { 95 | boost::shared_ptr ret(new ZTrace(name, t)); 96 | return ret; 97 | } 98 | 99 | ZTraceRef create_ZTrace(string name, ZTraceRef t, ZTraceEndpointRef ep) 100 | { 101 | boost::shared_ptr ret(new ZTrace(name, t, ep)); 102 | return ret; 103 | } 104 | 105 | ZTraceRef create_ZTrace(string name, ZTraceEndpointRef ep, struct blkin_trace_info *info, bool child) 106 | { 107 | boost::shared_ptr ret(new ZTrace(name, ep, info, child)); 108 | return ret; 109 | } 110 | int ZTrace::get_trace_info(struct blkin_trace_info *info) 111 | { 112 | return blkin_get_trace_info(&trace, info); 113 | } 114 | int ZTrace::set_trace_info(struct blkin_trace_info *info) 115 | { 116 | return blkin_set_trace_info(&trace, info); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/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 | extern "C" { 38 | #include 39 | } 40 | 41 | using std::string; 42 | using std::ostringstream; 43 | 44 | namespace ZTracer { 45 | int ztrace_init(void); 46 | char * to_cstr(string &s); 47 | char * ostr_to_cstr(ostringstream &stream); 48 | 49 | class ZTraceEndpoint; 50 | class ZTrace; 51 | 52 | typedef boost::shared_ptr ZTraceEndpointRef; 53 | typedef boost::shared_ptr ZTraceRef; 54 | 55 | class ZTraceEndpoint { 56 | private: 57 | struct blkin_endpoint ep; 58 | char *c_ip; 59 | char *c_name; 60 | protected: 61 | struct blkin_endpoint * get_blkin_ep() 62 | { 63 | return &ep; 64 | } 65 | friend ZTrace; 66 | public: 67 | ZTraceEndpoint(string ip, int port, string endpoint_name) 68 | { 69 | c_ip = to_cstr(ip); 70 | c_name = to_cstr(endpoint_name); 71 | blkin_init_endpoint(&ep, c_ip, port, c_name); 72 | } 73 | ~ZTraceEndpoint() 74 | { 75 | //cout << "Endpoint destroyed" << std::endl; 76 | if (c_ip) 77 | delete [] c_ip; 78 | if (c_name) 79 | delete [] c_name; 80 | } 81 | }; 82 | 83 | class ZTrace { 84 | private: 85 | struct blkin_trace trace; 86 | ZTraceEndpointRef ep; 87 | char *c_name = NULL; 88 | protected: 89 | struct blkin_trace *get_blkin_trace() 90 | { 91 | return &trace; 92 | } 93 | public: 94 | ZTrace(string name, ZTraceEndpointRef ep) 95 | :ep(ep) 96 | { 97 | c_name = to_cstr(name); 98 | blkin_init_new_trace(&trace, c_name, ep->get_blkin_ep()); 99 | } 100 | 101 | ZTrace(string name, ZTraceRef t) 102 | { 103 | this->ep = t->ep; 104 | c_name = to_cstr(name); 105 | blkin_init_child(&trace, t->get_blkin_trace(), ep->get_blkin_ep(), c_name); 106 | } 107 | 108 | ZTrace(string name, ZTraceRef t, ZTraceEndpointRef ep) 109 | { 110 | this->ep = ep; 111 | c_name = to_cstr(name); 112 | blkin_init_child(&trace, t->get_blkin_trace(), ep->get_blkin_ep(), 113 | c_name); 114 | } 115 | 116 | ZTrace(string name, ZTraceEndpointRef ep, struct blkin_trace_info *info, bool child=false) 117 | { 118 | c_name = to_cstr(name); 119 | this->ep = ep; 120 | if (child) 121 | blkin_init_child_info(&trace, info, ep->get_blkin_ep(), c_name); 122 | else { 123 | blkin_init_new_trace(&trace, c_name, ep->get_blkin_ep()); 124 | blkin_set_trace_info(&trace, info); 125 | } 126 | } 127 | ~ZTrace() 128 | { 129 | if (c_name) { 130 | delete [] c_name; 131 | } 132 | } 133 | ZTraceEndpointRef get_endpoint() 134 | { 135 | return this->ep; 136 | } 137 | 138 | int get_trace_info(struct blkin_trace_info *info); 139 | int set_trace_info(struct blkin_trace_info *info); 140 | int keyval(string key, string val); 141 | int keyval(string key, string val, ZTraceEndpointRef ep); 142 | int event(string event); 143 | int event(string event, ZTraceEndpointRef ep); 144 | }; 145 | 146 | ZTraceEndpointRef create_ZTraceEndpoint(string ip, int port, string name); 147 | ZTraceRef create_ZTrace(string name, ZTraceEndpointRef ep); 148 | ZTraceRef create_ZTrace(string name, ZTraceRef t); 149 | ZTraceRef create_ZTrace(string name, ZTraceRef t, ZTraceEndpointRef ep); 150 | ZTraceRef create_ZTrace(string name, ZTraceEndpointRef ep, struct blkin_trace_info *info, bool child=false); 151 | 152 | } 153 | #endif /* end of include guard: ZTRACER_H */ 154 | --------------------------------------------------------------------------------