C++ opentracing zipkin
Useful page : https://github.com/openzipkin/b3-propagation & other official websites
Steps to run attached scripts
- Download opentracing: https://github.com/opentracing/opentracing-cpp
- Download and install OpenTracing implementation for Zipkin : https://github.com/rnburn/zipkin-cpp-opentracing
- Download ZipKin backend server :curl -sSL https://zipkin.io/quickstart.sh | bash -s
- Run opentracingtest/build.sh
- Start zipkin backend: java -jar zipkin.jar
- Start ./server
- Start ./client
- Go to http://localhsot:9411
// 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 textMapCarrierclass 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 helperstd::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 1024int 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 1024int 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.shg++ -g -O0 client.cpp -o client -lcurl -lopentracing -lzipkin -lzipkin_opentracing -pthread -std=c++11g++ -g -O0 server.cpp -o server -lcurl -lopentracing -lzipkin -lzipkin_opentracing -pthread -std=c++11
赞 (0)