Useful page : https://github.com/openzipkin/b3-propagation & other official websitesjava
Steps to run attached scriptsios
// text_map_carrier.h, copy from example folder #ifndef LIGHTSTEP_TEXT_MAP_CARRIER #define LIGHTSTEP_TEXT_MAP_CARRIER #include <opentracing/propagation.h> #include <string> #include <unordered_map> using opentracing::TextMapReader; using opentracing::TextMapWriter; using opentracing::expected; using opentracing::string_view; // class textMapCarrier class TextMapCarrier : public TextMapReader, public TextMapWriter { public: TextMapCarrier(std::unordered_map<std::string, std::string> &text_map) : text_map_(text_map) {} expected<void> Set(string_view key, string_view value) const override { text_map_[key] = value; return {}; } expected<void> ForeachKey( std::function<expected<void>(string_view key, string_view value)> f) const override { for (const auto &key_value : text_map_) { auto result = f(key_value.first, key_value.second); if (!result) return result; } return {}; } std::unordered_map<std::string, std::string> &text_map_; }; // span context reader/writer helper std::string read_span_context(std::unordered_map<std::string, std::string> m) { std::string output = ""; for (auto it = m.cbegin(); it != m.cend(); it++) { output += (it->first) + ":" + it->second + ","; } return output.substr(0, output.size() - 1); } void write_span_context(std::unordered_map<std::string, std::string> &m, char *context) { char * keypair = strtok(context, ","); while(keypair != NULL) { std::string s(keypair); std::string::size_type found = s.find_first_of(':'); m.insert(std::pair<std::string, std::string>(s.substr(0,found),s.substr(found+1))); keypair =strtok(NULL, ","); } } #endif // LIGHTSTEP_TEXT_MAP_CARRIER
// client.cpp, copy from example folder #include "text_map_carrier.h" #include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <netdb.h> /* gethostbyname function */ #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <cassert> #include <iostream> #include <unordered_map> #include <zipkin/opentracing.h> using namespace zipkin; using namespace opentracing; #define MAXLINE 1024 int main() { int socket_fd; char buf[MAXLINE]; char buf2[MAXLINE]; struct sockaddr_in serv_addr ; socket_fd = socket(PF_INET, SOCK_STREAM, 0); bzero( &serv_addr, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET ; serv_addr.sin_port = htons(39152); inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); ZipkinOtTracerOptions options; options.service_name = "client_app"; auto tracer = makeZipkinOtTracer(options); assert(tracer); auto parent_span = tracer->StartSpan("startMain"); { auto child_span = tracer->StartSpan("Step1", {ChildOf(&parent_span->context())}); assert(child_span); // Set a simple tag. child_span->SetTag("simple tag", 123); // Set a complex tag. child_span->SetTag("complex tag", Values{123, Dictionary{{"abc", 123}, {"xyz", 4.0}}}); // Log simple values. child_span->Log({{"event", "simple log"}, {"abc", 123}}); // Log complex values. child_span->Log({{"event", "complex log"}, {"data", Dictionary{{"a", 1}, {"b", Values{1, 2}}}}}); sleep(1); child_span->Finish(); } // Create a follows from span. { auto child_span = tracer->StartSpan("Step1_1", {FollowsFrom(&parent_span->context())}); sleep(1); // child_span's destructor will finish the span if not done so explicitly. } // Use custom timestamps. { auto t1 = SystemClock::now(); sleep(1); auto t2 = SteadyClock::now(); auto span = tracer->StartSpan( "Step3", {ChildOf(&parent_span->context()), StartTimestamp(t1)}); assert(span); span->Finish({FinishTimestamp(t2)}); } if(connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == 0) { printf("client starts ...\n"); while(1) { static int n = 0; if( n>=6) break; char span_name[24]; sprintf(span_name, "request_%d", n++); auto child_span = tracer->StartSpan(span_name, {ChildOf(&parent_span->context())}); std::unordered_map<std::string, std::string> text_map; TextMapCarrier carrier(text_map); auto err = tracer->Inject(child_span->context(), carrier); std::string contxt = read_span_context(text_map); // for testing if(n == 2) sleep(2); printf("send message : %d\n", n); sprintf(buf, "%s\r\n%d",contxt.c_str(), n); if(write(socket_fd, buf, MAXLINE) == -1) printf("write error\n"); sleep(1); // wait for response while(read(socket_fd, buf2, MAXLINE) == -1) { sleep(1);} printf("get message from server: %s\n", buf2); child_span->Finish(); } } parent_span->Finish(); tracer->Close(); return 0; }
// server.cpp #include "text_map_carrier.h" #include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <netdb.h> /* gethostbyname function */ #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <cassert> #include <iostream> #include <unordered_map> #include <zipkin/opentracing.h> using namespace zipkin; using namespace opentracing; #define MAXLINE 1024 #define LISTENQ 1024 int main(int argc, char **argv) { int listen_fd, connect_fd; char buf[MAXLINE]; char buf2[MAXLINE]; socklen_t len; struct sockaddr_in serv_addr, client_addr; ZipkinOtTracerOptions options; options.service_name = "server_app"; auto tracer = makeZipkinOtTracer(options); listen_fd = socket(PF_INET, SOCK_STREAM, 0); bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(39152); inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) ; bind(listen_fd, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr_in)); printf("start listening ..\n"); listen(listen_fd, LISTENQ); for( ; ; ) { connect_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len); if(connect_fd < 0) continue; printf("accept from %s : %d \n", inet_ntoa(client_addr.sin_addr), client_addr.sin_port); while(1) { if (read(connect_fd, buf, MAXLINE) > -1) { char contxt[MAXLINE]; int data; sscanf(buf,"%s\r\n%d",contxt,&data); std::unordered_map<std::string, std::string> text_map; write_span_context(std::ref(text_map),&contxt[0]); TextMapCarrier carrier(text_map); auto span_context_maybe = tracer->Extract(carrier); if(!span_context_maybe) printf("error context............\n"); auto span = tracer->StartSpan("receive", {ChildOf(span_context_maybe->get())}); printf("receive message : %d\n", data); // for testing if (data == 4) sleep(2); sprintf(buf2, "back %d", data); sleep(1); if(write(connect_fd, buf2, MAXLINE) == -1) printf("write error"); span->Finish(); } sleep(1); } close(connect_fd); sleep(2); } tracer->Close(); }
# build.sh g++ -g -O0 client.cpp -o client -lcurl -lopentracing -lzipkin -lzipkin_opentracing -pthread -std=c++11 g++ -g -O0 server.cpp -o server -lcurl -lopentracing -lzipkin -lzipkin_opentracing -pthread -std=c++11