C++ opentracing zipkin

Useful page : https://github.com/openzipkin/b3-propagation & other official websites

Steps to run attached scripts

  1. Download opentracing: https://github.com/opentracing/opentracing-cpp
  1. Download and install OpenTracing implementation for Zipkin  : https://github.com/rnburn/zipkin-cpp-opentracing
  2. Download ZipKin backend server :curl -sSL https://zipkin.io/quickstart.sh | bash -s
  3. Run opentracingtest/build.sh
  4. Start zipkin backend: java -jar zipkin.jar
  5. Start ./server
  6. Start ./client
  7. 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 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

 

转载于:https://www.cnblogs.com/resibe-3/p/8628561.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值