diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index efef18d..1be4465 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: - name: Run clang-format run: find ./ -iname "*.h" -o -iname "*.cc" | xargs ./run-clang-format/run-clang-format.py - test: + unit-test: runs-on: ubuntu-20.04 steps: - run: | @@ -56,38 +56,18 @@ jobs: - name: Run coverage test run: | ./coverage.sh - - name: upload coverage data to codecov - uses: codecov/codecov-action@v2 - with: - fail_ci_if_error: true - files: ./coverage_report/coverage.dat - name: codecov-cpp2sky - verbose: true - e2e-cpp: + e2e-test: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - name: Prepare service container run: | - docker compose -f test/e2e/docker/docker-compose.e2e.yml up -d + docker compose -f test/e2e/docker/docker-compose.yml up -d - name: Run e2e run: | + sleep 10 pip3 install --upgrade pip pip3 install setuptools pip3 install -r test/e2e/requirements.txt - python3 test/e2e/main.py --expected_file=test/e2e/data/expected.yaml --max_retry_times=3 --target_path=/ping - - e2e-python: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v3 - - name: Prepare service container - run: | - docker compose -f test/e2e/docker/docker-compose.e2e-python.yml up -d - - name: Run e2e - run: | - pip3 install --upgrade pip - pip3 install setuptools - pip3 install -r test/e2e/requirements.txt - python3 test/e2e/main.py --expected_file=test/e2e/data/expected-python.yaml --max_retry_times=3 --target_path=/ping2 + python3 test/e2e/main.py --expected_file=test/e2e/data/all_expected.yaml --max_retry_times=3 diff --git a/README.md b/README.md index d82f46b..44b25fe 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # cpp2sky ![cpp2sky test](https://github.com/SkyAPM/cpp2sky/workflows/cpp2sky%20test/badge.svg) -![codecov test](https://codecov.io/gh/SkyAPM/cpp2sky/branch/main/graph/badge.svg) Distributed tracing and monitor SDK in CPP for Apache SkyWalking APM. This SDK is compatible with C++ 17, C++ 14, and C++ 11. diff --git a/test/e2e/data/interm.py b/test/e2e/bridge.py similarity index 66% rename from test/e2e/data/interm.py rename to test/e2e/bridge.py index e885abe..d356064 100644 --- a/test/e2e/data/interm.py +++ b/test/e2e/bridge.py @@ -4,10 +4,7 @@ from skywalking.decorators import runnable if __name__ == '__main__': - config.init(collector='collector:19876', service='interm') - config.logging_level = 'DEBUG' - - config.flask_collect_http_params = True + config.init() agent.start() from flask import Flask, Response @@ -16,7 +13,7 @@ @app.route("/users", methods=["POST", "GET"]) def application(): - res = requests.get("http://consumer:8080/pong") + res = requests.get("http://provider:8081/pong2") return Response(status=res.status_code) PORT = 8082 diff --git a/test/e2e/consumer.cc b/test/e2e/consumer.cc index d257de8..52ad116 100644 --- a/test/e2e/consumer.cc +++ b/test/e2e/consumer.cc @@ -1,4 +1,3 @@ - // Copyright 2020 SkyAPM // Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,11 +36,50 @@ int main() { httplib::Server svr; auto tracer = createInsecureGrpcTracer(config); - svr.Get("/pong", [&](const httplib::Request& req, httplib::Response& res) { - auto parent = req.get_header_value(kPropagationHeader.data()); - auto tracing_context = tracer->newContext(createSpanContext(parent)); + // C++ + svr.Get("/ping", [&](const httplib::Request& req, httplib::Response& res) { + auto tracing_context = tracer->newContext(); + + { + StartEntrySpan entry_span(tracing_context, "/ping"); + + { + std::string target_address = "provider:8081"; + + StartExitSpan exit_span(tracing_context, entry_span.get(), "/pong"); + exit_span.get()->setPeer(target_address); + + httplib::Client cli("provider", 8081); + httplib::Headers headers = { + {kPropagationHeader.data(), + *tracing_context->createSW8HeaderValue(target_address)}}; + auto res = cli.Get("/pong", headers); + } + } + + tracer->report(std::move(tracing_context)); + }); + + // Python + svr.Get("/ping2", [&](const httplib::Request& req, httplib::Response& res) { + auto tracing_context = tracer->newContext(); + + { + StartEntrySpan entry_span(tracing_context, "/ping2"); + + { + std::string target_address = "bridge:8082"; + + StartExitSpan exit_span(tracing_context, entry_span.get(), "/users"); + exit_span.get()->setPeer(target_address); - { StartEntrySpan entry_span(tracing_context, "/pong"); } + httplib::Client cli("bridge", 8082); + httplib::Headers headers = { + {kPropagationHeader.data(), + *tracing_context->createSW8HeaderValue(target_address)}}; + auto res = cli.Get("/users", headers); + } + } tracer->report(std::move(tracing_context)); }); diff --git a/test/e2e/data/all_expected.yaml b/test/e2e/data/all_expected.yaml new file mode 100644 index 0000000..4fdd89a --- /dev/null +++ b/test/e2e/data/all_expected.yaml @@ -0,0 +1,154 @@ +segmentItems: +- segmentSize: 2 + segments: + # Segment from provider in [consumer -> provider] case. + - segmentId: not null + spans: + - componentId: 9000 + endTime: gt 0 + isError: false + operationName: /pong + parentSpanId: -1 + peer: '' + refs: + - networkAddress: provider:8081 + parentEndpoint: /ping + parentService: consumer + parentServiceInstance: node_0 + parentSpanId: 1 + parentTraceSegmentId: not null + refType: CrossProcess + traceId: not null + skipAnalysis: false + spanId: 0 + spanLayer: Http + spanType: Entry + startTime: gt 0 + # Segment from provider in [consumer -> bridge -> provider] case. + - segmentId: not null + spans: + - componentId: 9000 + endTime: gt 0 + isError: false + operationName: /pong2 + parentSpanId: -1 + peer: '' + refs: + - networkAddress: provider:8081 + parentEndpoint: /pong2 + parentService: bridge + parentServiceInstance: not null + parentSpanId: 1 + parentTraceSegmentId: not null + refType: CrossProcess + traceId: not null + skipAnalysis: false + spanId: 0 + spanLayer: Http + spanType: Entry + startTime: gt 0 + serviceName: provider +- segmentSize: 1 + segments: + # Segment from bridge in [consumer -> bridge -> provider] case. + - segmentId: not null + spans: + - componentId: 7002 + endTime: gt 0 + isError: false + operationName: /pong2 + parentSpanId: 0 + peer: provider:8081 + skipAnalysis: false + spanId: 1 + spanLayer: Http + spanType: Exit + startTime: gt 0 + tags: + - key: http.method + value: GET + - key: http.url + value: http://provider:8081/pong2 + - key: http.status_code + value: '200' + - componentId: 7001 + endTime: gt 0 + isError: false + operationName: /users + parentSpanId: -1 + peer: not null + refs: + - networkAddress: bridge:8082 + parentEndpoint: /ping2 + parentService: consumer + parentServiceInstance: node_0 + parentSpanId: 1 + parentTraceSegmentId: not null + refType: CrossProcess + traceId: not null + skipAnalysis: false + spanId: 0 + spanLayer: Http + spanType: Entry + startTime: gt 0 + tags: + - key: http.method + value: GET + - key: http.url + value: http://bridge:8082/users + - key: http.status_code + value: '200' + serviceName: bridge +- segmentSize: 2 + segments: + # Segment from consumer [consumer -> provider] case. + - segmentId: not null + spans: + - componentId: 9000 + endTime: gt 0 + isError: false + operationName: /ping + parentSpanId: -1 + peer: '' + skipAnalysis: false + spanId: 0 + spanLayer: Http + spanType: Entry + startTime: gt 0 + - componentId: 9000 + endTime: gt 0 + isError: false + operationName: /pong + parentSpanId: 0 + peer: provider:8081 + skipAnalysis: false + spanId: 1 + spanLayer: Http + spanType: Exit + startTime: gt 0 + # Segment from consumer [consumer -> bridge -> provider] case. + - segmentId: not null + spans: + - componentId: 9000 + endTime: gt 0 + isError: false + operationName: /ping2 + parentSpanId: -1 + peer: '' + skipAnalysis: false + spanId: 0 + spanLayer: Http + spanType: Entry + startTime: gt 0 + - componentId: 9000 + endTime: gt 0 + isError: false + operationName: /users + parentSpanId: 0 + peer: bridge:8082 + skipAnalysis: false + spanId: 1 + spanLayer: Http + spanType: Exit + startTime: gt 0 + serviceName: consumer \ No newline at end of file diff --git a/test/e2e/data/expected-python.yaml b/test/e2e/data/expected-python.yaml deleted file mode 100644 index b6ef378..0000000 --- a/test/e2e/data/expected-python.yaml +++ /dev/null @@ -1,102 +0,0 @@ ---- -segmentItems: - - segmentSize: 1 - segments: - - segmentId: not null - spans: - - componentId: 7002 - endTime: gt 0 - isError: false - operationName: /pong - parentSpanId: 0 - peer: 'consumer:8080' - skipAnalysis: false - spanId: 1 - spanLayer: Http - spanType: Exit - startTime: gt 0 - tags: - - key: http.method - value: GET - - key: url - value: 'http://consumer:8080/pong' - - key: status.code - value: '200' - - componentId: 7001 - endTime: gt 0 - isError: false - operationName: /users - parentSpanId: -1 - peer: not null - refs: - - networkAddress: 'interm:8082' - parentEndpoint: /ping2 - parentService: provider - parentServiceInstance: node_0 - parentSpanId: 1 - parentTraceSegmentId: not null - refType: CrossProcess - traceId: not null - skipAnalysis: false - spanId: 0 - spanLayer: Http - spanType: Entry - startTime: gt 0 - tags: - - key: http.method - value: GET - - key: url - value: 'http://interm:8082/users' - - key: status.code - value: '200' - serviceName: interm - - segmentSize: 1 - segments: - - segmentId: not null - spans: - - componentId: 9000 - endTime: gt 0 - isError: false - operationName: /ping2 - parentSpanId: -1 - skipAnalysis: false - spanId: 0 - spanLayer: Http - spanType: Entry - startTime: gt 0 - - componentId: 9000 - endTime: gt 0 - isError: false - operationName: /users - parentSpanId: 0 - peer: 'interm:8082' - skipAnalysis: false - spanId: 1 - spanLayer: Http - spanType: Exit - startTime: gt 0 - serviceName: provider - - segmentSize: 1 - segments: - - segmentId: not null - spans: - - componentId: 9000 - endTime: gt 0 - isError: false - operationName: /pong - parentSpanId: -1 - refs: - - networkAddress: 'consumer:8080' - parentEndpoint: /pong - parentService: interm - parentServiceInstance: not null - parentSpanId: 1 - parentTraceSegmentId: not null - refType: CrossProcess - traceId: not null - skipAnalysis: false - spanId: 0 - spanLayer: Http - spanType: Entry - startTime: gt 0 - serviceName: consumer diff --git a/test/e2e/data/expected.yaml b/test/e2e/data/expected.yaml deleted file mode 100644 index b3d81a1..0000000 --- a/test/e2e/data/expected.yaml +++ /dev/null @@ -1,48 +0,0 @@ -segmentItems: - - serviceName: provider - segmentSize: 1 - segments: - - segmentId: not null - spans: - - operationName: /ping - parentSpanId: -1 - spanId: 0 - spanLayer: Http - startTime: gt 0 - endTime: gt 0 - componentId: 9000 - spanType: Entry - skipAnalysis: false - - operationName: /pong - parentSpanId: 0 - spanId: 1 - spanLayer: Http - startTime: gt 0 - endTime: gt 0 - peer: consumer:8080 - componentId: 9000 - spanType: Exit - skipAnalysis: false - - serviceName: consumer - segmentSize: 1 - segments: - - segmentId: not null - spans: - - operationName: /pong - parentSpanId: -1 - spanId: 0 - spanLayer: Http - startTime: gt 0 - endTime: gt 0 - componentId: 9000 - spanType: Entry - skipAnalysis: false - refs: - - parentEndpoint: /ping - networkAddress: consumer:8080 - refType: CrossProcess - parentSpanId: 1 - parentTraceSegmentId: not null - parentServiceInstance: node_0 - parentService: provider - traceId: not null diff --git a/test/e2e/docker/Dockerfile.interm b/test/e2e/docker/Dockerfile.bridge similarity index 100% rename from test/e2e/docker/Dockerfile.interm rename to test/e2e/docker/Dockerfile.bridge diff --git a/test/e2e/docker/Dockerfile.tool b/test/e2e/docker/Dockerfile.tool index 1bb2d75..6294f60 100644 --- a/test/e2e/docker/Dockerfile.tool +++ b/test/e2e/docker/Dockerfile.tool @@ -2,7 +2,7 @@ FROM openjdk:8 WORKDIR /tests -ARG COMMIT_HASH=7dbdf726bdd12b67f09b3898bb95790eacbedf84 +ARG COMMIT_HASH=b6efe6af0a5499502b8cf8b76c7351e3f172a616 ADD https://github.com/apache/skywalking-agent-test-tool/archive/${COMMIT_HASH}.tar.gz . diff --git a/test/e2e/docker/docker-compose.dev.yml b/test/e2e/docker/docker-compose.dev.yml deleted file mode 100644 index 824e9c5..0000000 --- a/test/e2e/docker/docker-compose.dev.yml +++ /dev/null @@ -1,65 +0,0 @@ -version: "3.7" -services: - # Skywalking components. - elasticsearch: - image: elasticsearch:7.9.2 - restart: always - ports: - - 9200:9200 - healthcheck: - test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - environment: - discovery.type: single-node - expose: - - "9200" - ulimits: - memlock: - soft: -1 - hard: -1 - consul: - image: docker.io/bitnami/consul:1-debian-10 - ports: - - '8300:8300' - - '8301:8301' - - '8301:8301/udp' - - '8500:8500' - - '8600:8600' - - '8600:8600/udp' - oap: - image: apache/skywalking-oap-server:8.6.0-es7 - depends_on: - - elasticsearch - links: - - elasticsearch - ports: - - 11800:11800 - - 12800:12800 - environment: - SW_STORAGE: elasticsearch7 - SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200 - restart: always - healthcheck: - test: ["CMD-SHELL", "/skywalking/bin/swctl"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - depends_on: - - consul - - elasticsearch - ui: - image: apache/skywalking-ui:8.6.0 - depends_on: - - oap - links: - - oap - ports: - - 8080:8080 - environment: - SW_OAP_ADDRESS: oap:12800 - depends_on: - - oap diff --git a/test/e2e/docker/docker-compose.e2e.yml b/test/e2e/docker/docker-compose.e2e.yml deleted file mode 100644 index 1659a9a..0000000 --- a/test/e2e/docker/docker-compose.e2e.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: "3.7" -services: - collector: - build: - context: ../../.. - dockerfile: ./test/e2e/docker/Dockerfile.tool - ports: - - 19876:19876 - - 12800:12800 - - consumer: - build: - context: ../../.. - dockerfile: ./test/e2e/docker/Dockerfile.consumer - expose: - - 8080 - command: sh -c "GRPC_VERBOSITY=debug /tmp/bazel-bin/test/e2e/e2e_consumer" - depends_on: - - collector - - provider: - build: - context: ../../.. - dockerfile: ./test/e2e/docker/Dockerfile.provider - ports: - - 8081:8081 - command: sh -c "GRPC_VERBOSITY=debug /tmp/bazel-bin/test/e2e/e2e_provider" - depends_on: - - collector - - consumer diff --git a/test/e2e/docker/docker-compose.e2e-python.yml b/test/e2e/docker/docker-compose.yml similarity index 63% rename from test/e2e/docker/docker-compose.e2e-python.yml rename to test/e2e/docker/docker-compose.yml index afa759e..618d526 100644 --- a/test/e2e/docker/docker-compose.e2e-python.yml +++ b/test/e2e/docker/docker-compose.yml @@ -17,17 +17,26 @@ services: command: sh -c "GRPC_VERBOSITY=debug /tmp/bazel-bin/test/e2e/e2e_consumer" depends_on: - collector + - bridge + - provider - interm: + bridge: build: context: ../../.. - dockerfile: ./test/e2e/docker/Dockerfile.interm + dockerfile: ./test/e2e/docker/Dockerfile.bridge ports: - 8082:8082 - command: python3 test/e2e/data/interm.py + environment: + SW_AGENT_NAME: bridge + SW_AGENT_COLLECTOR_BACKEND_SERVICES: "collector:19876" + SW_AGENT_LOGGING_LEVEL: DEBUG + SW_FLASK_COLLECT_HTTP_PARAMS: "True" + SW_AGENT_LOG_REPORTER_ACTIVE: "False" + SW_AGENT_PROFILE_ACTIVE: "False" + command: sh -c "sleep 10 && python3 test/e2e/bridge.py" depends_on: - collector - - consumer + - provider provider: build: @@ -38,5 +47,3 @@ services: command: sh -c "GRPC_VERBOSITY=debug /tmp/bazel-bin/test/e2e/e2e_provider" depends_on: - collector - - interm - - consumer diff --git a/test/e2e/main.py b/test/e2e/main.py index 5463b2d..eb12770 100644 --- a/test/e2e/main.py +++ b/test/e2e/main.py @@ -23,9 +23,15 @@ def validate(expected_file_name): response = requests.post(url='http://0.0.0.0:12800/dataValidate', data=expected_data) if response.status_code != 200: + print('validate result: ') + print(response.content) + res = requests.get('http://0.0.0.0:12800/receiveData') actual_data = yaml.dump(yaml.load(res.content, Loader=Loader)) + print('actual data: ') + print(actual_data) + differ = Differ() diff_list = list(differ.compare( actual_data.splitlines(keepends=True), @@ -41,8 +47,7 @@ def validate(expected_file_name): parser = argparse.ArgumentParser() parser.add_argument('--expected_file', help='File name which includes expected reported value') parser.add_argument('--max_retry_times', help='Max retry times', type=int) - parser.add_argument('--target_path', help='Specify target path') - + args = parser.parse_args() retry_times = 0 @@ -50,8 +55,19 @@ def validate(expected_file_name): if retry_times > args.max_retry_times: raise RuntimeError("Max retry times exceeded") + # Test two hops: consumer -> provider by /ping + try: + requests.get('http://0.0.0.0:8080/ping', timeout=5) + except Exception as e: + print(e) + retry_times += 1 + time.sleep(2) + continue + + # Test three hops: consumer -> bridge -> provider by /ping2 + retry_times = 0 try: - requests.get('http://0.0.0.0:8081{0}'.format(args.target_path), timeout=5) + requests.get('http://0.0.0.0:8080/ping2', timeout=5) except Exception as e: print(e) retry_times += 1 diff --git a/test/e2e/provider.cc b/test/e2e/provider.cc index 28fdda3..619f132 100644 --- a/test/e2e/provider.cc +++ b/test/e2e/provider.cc @@ -1,3 +1,4 @@ + // Copyright 2020 SkyAPM // Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,50 +37,20 @@ int main() { httplib::Server svr; auto tracer = createInsecureGrpcTracer(config); - // C++ - svr.Get("/ping", [&](const httplib::Request& req, httplib::Response& res) { - auto tracing_context = tracer->newContext(); - - { - StartEntrySpan entry_span(tracing_context, "/ping"); - - { - std::string target_address = "consumer:8080"; - - StartExitSpan exit_span(tracing_context, entry_span.get(), "/pong"); - exit_span.get()->setPeer(target_address); + svr.Get("/pong", [&](const httplib::Request& req, httplib::Response& res) { + auto parent = req.get_header_value(kPropagationHeader.data()); + auto tracing_context = tracer->newContext(createSpanContext(parent)); - httplib::Client cli("consumer", 8080); - httplib::Headers headers = { - {kPropagationHeader.data(), - *tracing_context->createSW8HeaderValue(target_address)}}; - auto res = cli.Get("/pong", headers); - } - } + { StartEntrySpan entry_span(tracing_context, "/pong"); } tracer->report(std::move(tracing_context)); }); - // Python - svr.Get("/ping2", [&](const httplib::Request& req, httplib::Response& res) { - auto tracing_context = tracer->newContext(); - - { - StartEntrySpan entry_span(tracing_context, "/ping2"); - - { - std::string target_address = "interm:8082"; - - StartExitSpan exit_span(tracing_context, entry_span.get(), "/users"); - exit_span.get()->setPeer(target_address); + svr.Get("/pong2", [&](const httplib::Request& req, httplib::Response& res) { + auto parent = req.get_header_value(kPropagationHeader.data()); + auto tracing_context = tracer->newContext(createSpanContext(parent)); - httplib::Client cli("interm", 8082); - httplib::Headers headers = { - {kPropagationHeader.data(), - *tracing_context->createSW8HeaderValue(target_address)}}; - auto res = cli.Get("/users", headers); - } - } + { StartEntrySpan entry_span(tracing_context, "/pong2"); } tracer->report(std::move(tracing_context)); }); diff --git a/test/e2e/requirements.txt b/test/e2e/requirements.txt index b9612dd..c924985 100644 --- a/test/e2e/requirements.txt +++ b/test/e2e/requirements.txt @@ -1,16 +1,5 @@ -PyYAML==6.0 +PyYAML==5.3.1 requests==2.26.0 -apache-skywalking==0.6.0 -protobuf==3.18.3 -tornado==6.1 -sanic==21.12.2 +apache-skywalking==0.8.0 Flask==2.0.2 -Jinja2==3.1.2 -pymongo==3.12.0 -pymysql==1.0.2 -pyramid==2.0 -pika==1.2.0 -redis==3.5.3 -MarkupSafe==2.1.1 -itsdangerous==2.1.2 -Werkzeug==2.1.1 +Werkzeug==2.2.2 \ No newline at end of file