Updated on 2025-11-18 GMT+08:00

Agent Access

Currently, SkyWalking and OpenTelemetry Agents are supported.

SkyWalking Access

  1. Log in to the APM console.
  2. Click on the left and choose Management & Governance > Application Performance Management.
  3. In the navigation pane, choose Link Trace > Agent Access.
  4. Select a region and application.
  5. Select SkyWalking. If the current application supports SkyWalking, OpenTelemetry will be grayed and cannot be selected.

    Figure 1 Selecting SkyWalking

  6. Select an access mode based on the application type and connect the Agent to the application by following the instructions. Note that each component under an application must have a unique name.

    • Java application access
      1. Download SkyWalking.

        Go to the SkyWalking official website to download Java Agent 8.9.0 or later (recommended). Decompress the package and save the Agent file to a directory that the Java process has the access permission.

        To enable a plug-in, place the new plug-in to the /plugins directory during startup. To disable the plug-in, delete the plug-in from the directory.

        By default, log files are output to the /logs directory.

      2. Add the startup command and restart the application.

        There are two ways to configure the Agent:

        • Configure the application startup command.
          java -javaagent:skywalking-agent-path -Dskywalking.collector.backend_service=***.**.**.**:***** -Dskywalking.agent.authentication=******* -Dskywalking.agent.service_name=Application name.Component name.Environment name -jar <User application>.jar
        • Configure the agent/config/agent.config file.
          collector.backend_service=100.79.29.107:11800
          agent.authentication=*****
          agent.service_name=Application name.Component name.Environment name
          //Configure the Java Agent path and restart the application.
          java -javaagent:skywalking-agent-path -jar User Application.jar

        If you configure the Agent in both ways, only the configuration in the startup command takes effect.

    • Python application access
      1. Download SkyWalking.
      2. Install the Python Agent through PyPI.
        pip install "apache-skywalking"
        pip install "apache-skywalking[http]"
        pip install "apache-skywalking[kafka]"
        pip install apache-skywalking==0.7.0

        After the SkyWalking Python Agent is installed using pip, the sw-python script will be installed in your environment.

      3. Connect the Agent.

        To connect the Agent, you need to configure the access point, token, and application name in your startup file:

        from skywalking import agent, config
                  config.init(
                  collector_address='***.**.**.**:*****',
                  authentication='*******',
                  service_name='apply name',
                  )
                  agent.start()
      4. Restart the application.

        sw-python CLI provides the run option. You can use this option to run your application.

        Original command:

        gunicorn app.wsgi

        New command:

        sw-python run gunicorn app.wsgi

        The SkyWalking Python Agent will then start with your application.

    • Go application access
      1. Download SkyWalking.
      2. Run the following command to install the SkyWalking Go SDK:
        go get -u github.com/SkyAPM/go2sky-plugins/sql
      3. Connect the SDK to APM.

        Import the SDK package to the main.go file.

        import (
                "github.com/SkyAPM/go2sky"
                "github.com/SkyAPM/go2sky/reporter"
              )

        Add the SDK to the main method.

        r, err := reporter.NewGRPCReporter(***.**.**.**:*****,
        reporter.WithCDS(0),
        reporter.WithAuthentication(******))
        if err != nil {
            log.Fatalf("new reporter error %v \n", err)
        }
        defer r.Close()
        tracer, err := go2sky.NewTracer(<Application name.Component name.Environment name>,
        go2sky.WithReporter(r))
        if err != nil {
            log.Fatalf("create tracer error %v \n", err)
        }
        go2sky.SetGlobalTracer(tracer)
    • Node.js application access
      1. Download SkyWalking.
      2. Use the newly recommended library. The original module is SkyAPM-nodejs. Ensure that Node.js 10 or later is used. Run the following command on the console:
        npm i skywalking-backend-js
      3. Connect the Agent.

        To connect the Agent, you need to configure the access point, token, and application name in your startup file:

        const { default: agent } = require('skywalking-backend-js');
              agent.start({
                serviceName: 'Application name.Component name.Environment name',
                collectorAddress: '***.**.**.**:*****',
                authorization: '*********'
              });
      4. Restart the application. Start the project using the common command. If no error is reported and data is reported normally, the startup is successful. If an error is reported, check the configuration and version. If no data is reported, check whether the token and application name are correct.
    • PHP application access
      1. Download SkyWalking.
        • Use pecl.net (recommended) to install the Agent. You can run the following command on the console:
          pecl install skywalking_agent
        • Alternatively, install the Agent using the source code:
          git clone --recursive https://github.com/apache/skywalking-php.git
          cd skywalking-php
          phpize
          ./configure
          make
          make install
      2. Connect the Agent.

        Modify the following configuration items in the php.ini file:

        [skywalking]
        extension=skywalking.so
        skywalking.app_code = Application name.Component name.Environment name
        skywalking.enable = 1
        skywalking.version = 8
        skywalking.grpc = ***.**.**.***:*****
        skywalking.authentication = ******
        skywalking.error_handler_enable = 0
      3. Restart the application.
        • Method 1: Set the value of daemonize to no in the php-fpm.conf file.
        • Method 2: Run the nohup command to restart php-fpm:
          nohup /usr/local/services/php7/sbin/php-fpm > /usr/local/services/php7/log/php-fpm-output.log 2>&1 &
    • .NET application access
      1. Download SkyWalking.

        Add the SkyAPM .NET Core Agent library.

        dotnet add package SkyAPM.Agent.AspNetCore
      2. Connect the Agent.

        Download the configuration file generation tool SkyAPM.DotNet.CLI.

        dotnet tool install -g SkyAPM.DotNet.CLI 

        Use the tool to generate the skyapm.json file.

        dotnet skyapm config Application name.Component name.Environment name ***.**.**.***:*****

        Modify Authentication in the skyapm.json file.

        Authentication: "***********"

        Add the environment variables ASPNETCORE_HOSTINGSTARTUPASSEMBLIES and SKYWALKING__SERVICENAME to the launchSettings.json file under Properties.

        environmentVariables: {
              "SKYWALKING__SERVICENAME": "Application name.Component name.Environment name'',
              "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore"
              } 

OpenTelemetry Access

  1. In the navigation pane, choose Link Trace > Agent Access.
  2. Select a region and application.
  3. Select OpenTelemetry.

    If the current application supports OpenTelemetry, SkyWalking will be grayed and cannot be selected.

    Figure 2 Selecting OpenTelemetry

  4. Select an access mode based on the application type and connect the Agent to the application by following the instructions. Note that each component under an application must have a unique name.

    • Java application access
      1. Download the OpenTelemetry Java Agent. Download the Agent (1.x is recommended). After the download, place the Agent file in a directory that the Java process can access.
      2. Add the startup command and restart the application.
        java -javaagent:opentelemetry-agent-path -Dotel.exporter.otlp.traces.endpoint=http://***.**.**.***:**** -Dotel.exporter.otlp.headers=Authentication=***** -Dotel.service.name=Application name.Component name.Environment name -Dotel.metrics.exporter=none -jar User application.jar

        Example of a startup command:

        java -javaagent:/root/my-dir/opentelemetry-javaagent.jar -Dotel.exporter.otlp.traces.endpoint=http://100.79.29.106:4317 -Dotel.exporter.otlp.headers=Authentication=QxHHU69weF2c66b5DaCSNiGJAmqnRrH55DUikIJaf3ghVygIMMzgmuNioIZsH6hyE8GEOGVbXzjIXCPUjoYuUYEdjdvB6rm00nOZTXeADOfjSR84hKPNquiQg39egulwtTzORW3pLHgi03D2mynBncuna1afpx0tCxEFrETXex2o7SPJRijJK9Z3k7PHTqgk7WiMVohcMid7TLjMRPTqj7ziFOZk2EljkQi2DSpKbOKEOBE1iHEUeYO5dB167ic5 -Dotel.service.name=default.my-service.dev -Dotel.metrics.exporter=none -jar myApp.jar
    • PHP application access
      • Method 1: Non-intrusive access
        1. Prepare the environment.

          PHP 8.0+, PECL, and composer. After the installation is complete, verify the PHP and composer versions in the shell script.

        2. Install OpenTelemetry extension components.
          1. Install the required build tool.
            sudo apt-get install gcc make autoconf
          2. Install the extension component using the build tool.
            pecl install opentelemetry-beta
            pecl install grpc
            pecl install protobuf-3.8.0
          3. Add the extension name to your php.ini file.
            [opentelemetry]
            extension=opentelemetry.so
            [PHP]
            extension=grpc.so
            extension=protobuf.so
          4. Check whether the extension has been installed and enabled.
            php --ri opentelemetry
            php --ri grpc
            php --ri protobuf
        3. Install the OpenTelemetry dependency packages required by the service framework.
          1. Install the OpenTelemetry automatic plug-in package on which the service framework depends. For example, the Slim framework requires open-telemetry/opentelemetry-auto-slim.
            composer config allow-plugins.php-http/discovery false
            composer require open-telemetry/sdk
            composer require open-telemetry/exporter-otlp
            composer require open-telemetry/transport-grpc
            composer require open-telemetry/opentelemetry-auto-slim
            composer update
          2. To connect the Agent, add the following content to the environment variables or php.ini file:
            OTEL_EXPORTER_OTLP_ENDPOINT=http://***.**.**.***:****
            OTEL_EXPORTER_OTLP_HEADERS=Authentication=******
            OTEL_EXPORTER_OTLP_PROTOCOL=grpc
            OTEL_PHP_AUTOLOAD_ENABLED=true
            OTEL_SERVICE_NAME=Application name.Component name.Environment name
      • Intrusive access: See official website.
    • Go application access

      Use the gRPC protocol to report data.

      1. Add OpenTelemetry dependencies.
        import (
         "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
         "go.opentelemetry.io/otel"
         "go.opentelemetry.io/otel/baggage"
         "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
         "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
         "google.golang.org/grpc"
         "go.opentelemetry.io/otel/propagation"
         "go.opentelemetry.io/otel/sdk/resource"
         sdktrace "go.opentelemetry.io/otel/sdk/trace"
         semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
        )
      2. Interconnect with OpenTelemetry.
        const (
         SERVICE_NAME = "Application name.Component name.Environment name"
         GRPC_ENDPOINT="***.**.**.***:****"
         GRPC_TOKEN= "****"
        )
        
        func main() {
         init := initialization()
         defer init()
         grpc := otel.Tracer ("Service name")
         method, _ := baggage.NewMember("method", "repl")
         client, _ := baggage.NewMember("client", "cli")
         bag, _ := baggage.New(method, client)
         context := baggage.ContextWithBaggage(context.Background(), bag)
         for {
          ctx, span := grpc.Start(context, "CreateSpan")
          createSpan(ctx)
          span.End()
          time.Sleep(time.Duration(1) * time.Second)
         }
        }
        func initialization() func() {
         ctx := context.Background()
         headers := map[string]string{"Authentication": APM_TOKEN}
         traceClientGrpc := otlptracegrpc.NewClient(
          otlptracegrpc.WithInsecure(),
          otlptracegrpc.WithEndpoint(APM_ENDPOINT),
          otlptracegrpc.WithHeaders(headers),
          otlptracegrpc.WithDialOption(grpc.WithBlock()))
         traceExp, err := otlptrace.New(ctx, traceClientGrpc)
         if err != nil {
          log.Fatalf("%s: %v", "can not create exporter", err)
         }
         res, err := resource.New(ctx,
         resource.WithFromEnv(),
         resource.WithProcess(),
         resource.WithTelemetrySDK(),
         resource.WithHost(),
         resource.WithAttributes(
          semconv.ServiceNameKey.String(SERVICE_NAME),
          semconv.HostNameKey.String(APM_ENDPOINT),
         ),
         )
         if err != nil {
          log.Fatalf("%s: %v", "can not create exporter", err)
         }
         bsp := sdktrace.NewBatchSpanProcessor(traceExp)
         tracerProvider := sdktrace.NewTracerProvider(
          sdktrace.WithSampler(sdktrace.AlwaysSample()),
          sdktrace.WithResource(res),
          sdktrace.WithSpanProcessor(bsp),
         )
         otel.SetTextMapPropagator(propagation.TraceContext{})
         otel.SetTracerProvider(tracerProvider)
         return func() {
          cxt, cancel := context.WithTimeout(ctx, time.Second)
          defer cancel()
          if err := traceExp.Shutdown(cxt); err != nil {
           otel.Handle(err)
          }
         }
        }
        func createSpan(ctx context.Context) {
         address := "Remote server address"
         client := http.Client {
          Transport: otelhttp.NewTransport(http.DefaultTransport),
         }
         req, err := http.NewRequestWithContext(ctx, "GET", address, nil)
         res, err := client.Do(req)
         if err != nil {
          log.Println(err)
         } else {
          res.Body.Close()
         }
        }
        
    • Python application access
      • Non-intrusive access
        1. Download related packages.
          pip install opentelemetry-distro
          pip install opentelemetry-exporter-otlp
          opentelemetry-bootstrap -a install
        2. Run the following command to start the Python application.

          To connect the Agent, you need to configure the token, endpoint, service name, and host name to your startup file:

          opentelemetry-instrument     --traces_exporter otlp     --service_name Application name.Component name.Environment name     --resource_attributes host.name=host.name     --exporter_otlp_endpoint http://***.**.**.***:****     --exporter_otlp_headers Authentication=********
               python myapp.py
    • Node.js application access
      • Intrusive access
        1. Add dependencies.
          npm install --save @grpc/grpc-js @opentelemetry/exporter-trace-otlp-grpc @opentelemetry/instrumentation-express @opentelemetry/instrumentation-http @opentelemetry/resources @opentelemetry/sdk-node @opentelemetry/sdk-trace-base @opentelemetry/semantic-conventions
        2. Interconnect with OpenTelemetry.

          Add the following content to the top of the express entry file:

              const { NodeSDK } = require("@opentelemetry/sdk-node");
              const { Resource } = require("@opentelemetry/resources");
              const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-grpc");
              const { ExpressInstrumentation } = require("@opentelemetry/instrumentation-express");
              const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http");
              const { SemanticResourceAttributes } = require("@opentelemetry/semantic-conventions");
              const { BatchSpanProcessor } = require("@opentelemetry/sdk-trace-base");
              const grpc = require("@grpc/grpc-js");
          
                const service_name = "Application name.Component name.Environment name";
                const endpoint = "http://***.**.**.***:****";
                const authentication = "****";
          
          
              const metadata = new grpc.Metadata();
              metadata.set("Authentication", authentication);
              const exporter = new OTLPTraceExporter({url: endpoint, metadata});
              const sdk = new NodeSDK({
                spanProcessor: new BatchSpanProcessor(exporter),
                resource: new Resource({
                  [SemanticResourceAttributes.HOST_NAME]: require("os").hostname(), // your host name
                  [SemanticResourceAttributes.SERVICE_NAME]: service_name,
                }),
                instrumentations: [HttpInstrumentation, ExpressInstrumentation],
              });
              sdk.start();
          
      • Non-intrusive access

        For details, see the official website.

    • C++ application access
      1. Use CMake to connect to OpenTelemetry.
      2. Check the environment requirements.
        1. C++ version ≥ 14 (earlier OpenTelemetry-cpp: C++ version ≥ 11)
        2. Check supported C++ versions and development platforms.
      3. Prepare the environment.
        1. Install the build tool Bazel. For details, see Bazel Installation Guide.
        2. Build the OpenTelemetry C++ library to set up the environment.
          git clone https://github.com/open-telemetry/opentelemetry-cpp.git
              cd opentelemetry-cpp
              bazel build //...
      4. Use the OpenTelemetry C++ library in the project.
        • Example WORKSPACE file:
          load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
          load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
          load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
          
          http_archive(
              name = "io_opentelemetry_cpp",
              sha256 = "<sha256>", # specify sha256 based on the URL specified in the urls parameter.
              strip_prefix = "opentelemetry-cpp-1.10.0",
              urls = [
                  "https://github.com/open-telemetry/opentelemetry-cpp/archive/refs/tags/v1.10.0.tar.gz"
              ],
          )
          
          # Load OpenTelemetry dependencies after load.
          load("@io_opentelemetry_cpp//bazel:repository.bzl", "opentelemetry_cpp_deps")
          
          opentelemetry_cpp_deps()
          
          # (required after v1.8.0) Load extra dependencies required for OpenTelemetry
          load("@io_opentelemetry_cpp//bazel:extra_deps.bzl", "opentelemetry_extra_deps")
          
          opentelemetry_extra_deps()
          
          # Load gRPC dependencies after load.
          load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
          
          grpc_deps()
          
          # Load extra gRPC dependencies due to https://github.com/grpc/grpc/issues/20511
          load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
          
          grpc_extra_deps()
        • BUILD file:
          # Copyright The OpenTelemetry Authors
          # SPDX-License-Identifier: Apache-2.0
          
          cc_binary(
              name = "example_http_server",
              srcs = [
                  "server.cc",
                  "server.h",
              ],
              tags = ["ostream"],
              deps = [
                  "@io_opentelemetry_cpp//api",
                  "@io_opentelemetry_cpp//exporters/ostream:ostream_span_exporter",
                  "@io_opentelemetry_cpp//ext:headers",
                  "@io_opentelemetry_cpp//sdk/src/trace",
                  "@io_opentelemetry_cpp//exporters/otlp:otlp_grpc_exporter",
              ],
          )
        • The test code contains the server.cc and server.h files.

          server.cc file:

          #include "server.h"
            #include "opentelemetry/trace/context.h"
            #include "opentelemetry/trace/semantic_conventions.h"
          
            #include "opentelemetry/exporters/ostream/span_exporter_factory.h"
            #include "opentelemetry/sdk/trace/exporter.h"
            #include "opentelemetry/sdk/trace/processor.h"
            #include "opentelemetry/sdk/trace/simple_processor_factory.h"
            #include "opentelemetry/sdk/trace/tracer_context.h"
            #include "opentelemetry/sdk/trace/tracer_context_factory.h"
            #include "opentelemetry/sdk/trace/tracer_provider_factory.h"
            #include "opentelemetry/trace/provider.h"
          
            #include "opentelemetry/context/propagation/global_propagator.h"
            #include "opentelemetry/context/propagation/text_map_propagator.h"
            #include "opentelemetry/trace/propagation/http_trace_context.h"
          
            #include <cstring>
            #include <string>
            #include <unistd.h>
            #include <iostream>
            #include <vector>
            #include "opentelemetry/ext/http/client/http_client.h"
            #include "opentelemetry/nostd/shared_ptr.h"
          
            #include "opentelemetry/sdk/trace/tracer_provider.h"
            #include "opentelemetry/exporters/otlp/otlp_grpc_exporter_factory.h"
          
            #include <iostream>
            #include <thread>
          
            namespace trace = opentelemetry::trace;
            namespace trace_sdk = opentelemetry::sdk::trace;
            namespace otlp = opentelemetry::exporter::otlp;
          
            namespace {
          
              using namespace opentelemetry::trace;
              namespace context = opentelemetry::context;
              opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts;
          
              uint16_t server_port = 8800;
              constexpr const char *server_name = "localhost";
          
              std::string getHostName() {
                  char hostname[256];
                  if (gethostname(hostname, sizeof(hostname)) == 0) {
                      return hostname;
                  } else {
                      return "default_hostname";
                  }
              }
          
              template<typename T>
              class HttpTextMapCarrier : public opentelemetry::context::propagation::TextMapCarrier {
              public:
                  HttpTextMapCarrier(T &headers) : headers_(headers) {}
          
                  HttpTextMapCarrier() = default;
          
                  virtual opentelemetry::nostd::string_view Get(opentelemetry::nostd::string_view key) const noexcept override {
                      std::string key_to_compare = key.data();
                      // Header's first letter seems to be automatically capitalized by our test http-server, so
                      // compare accordingly.
                      if (key == opentelemetry::trace::propagation::kTraceParent) {
                          key_to_compare = "Traceparent";
                      } else if (key == opentelemetry::trace::propagation::kTraceState) {
                          key_to_compare = "Tracestate";
                      }
                      auto it = headers_.find(key_to_compare);
                      if (it != headers_.end()) {
                          return it->second;
                      }
                      return "";
                  }
          
                  virtual void Set(opentelemetry::nostd::string_view key, opentelemetry::nostd::string_view value) noexcept override {
                      headers_.insert(std::pair<std::string, std::string>(std::string(key), std::string(value)));
                  }
          
                  T headers_;
              };
          
              void InitTracer() {
                  // Change this parameter based on the configuration of the access site.
          
          
                std::string endpoint = "http://***.**.**.***:****";
                std::string token = "******";
                std::string serviceName = "Application name.Component name.Environment name";
          
          
                opts.endpoint = endpoint;
                opts.metadata.insert(std::pair<std::string, std::string>("authentication", token));
                // Create OTLP exporter instance
                auto exporter = otlp::OtlpGrpcExporterFactory::Create(opts);
                auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter));
          
                opentelemetry::sdk::resource::ResourceAttributes attributes = {
                    {"service.name", serviceName},
                    {"host.name",    getHostName()}
                };
                auto resource = opentelemetry::sdk::resource::Resource::Create(attributes);
          
                std::shared_ptr <opentelemetry::trace::TracerProvider> provider = trace_sdk::TracerProviderFactory::Create(std::move(processor), std::move(resource));
                // Set the global trace provider
                trace::Provider::SetTracerProvider(provider);
              }
          
              void CleanupTracer() {
                // We call ForceFlush to prevent to cancel running exportings, It's optional.
                opentelemetry::nostd::shared_ptr <opentelemetry::trace::TracerProvider> provider = trace::Provider::GetTracerProvider();
                if (provider) {
                    static_cast<trace_sdk::TracerProvider *>(provider.get())->ForceFlush();
                }
          
                std::shared_ptr <opentelemetry::trace::TracerProvider> none;
                trace::Provider::SetTracerProvider(none);
              }
          
              opentelemetry::nostd::shared_ptr <opentelemetry::trace::Tracer> get_tracer(std::string tracer_name) {
                auto provider = opentelemetry::trace::Provider::GetTracerProvider();
                return provider->GetTracer(tracer_name);
              }
          
              class RequestHandler : public HTTP_SERVER_NS::HttpRequestCallback {
              public:
                virtual int onHttpRequest(HTTP_SERVER_NS::HttpRequest const &request, HTTP_SERVER_NS::HttpResponse &response) override {
                    StartSpanOptions options;
                    options.kind = SpanKind::kServer;  // server
                    std::string span_name = request.uri;
          
                    // extract context from http header
                    std::map <std::string, std::string> &request_headers =
                            const_cast<std::map <std::string, std::string> &>(request.headers);
                    const HttpTextMapCarrier<std::map < std::string, std::string>>
                    carrier(request_headers);
                    auto prop = context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();
                    auto current_ctx = context::RuntimeContext::GetCurrent();
                    auto new_context = prop->Extract(carrier, current_ctx);
                    options.parent = GetSpan(new_context)->GetContext();
          
                    // start span with parent context extracted from http header
                    auto span = get_tracer("http-server")
                            ->StartSpan(span_name,
                            {{"server.address", server_name},
                            {"server.port",    server_port},
                            {"http.method",    request.method},
                            {"url.scheme",     "http"},
                            {"http.request.body.size",
                            static_cast<uint64_t>(request.content.length())},
                            {"client.address", request.client}},
                            options);
          
                    auto scope = get_tracer("http_server")->WithActiveSpan(span);
          
                    for (auto &kv : request.headers) {
                        span->SetAttribute("http.header." + std::string(kv.first.data()), kv.second);
                    }
                    if (request.uri == "/helloworld") {
                        span->AddEvent("Processing request");
                        response.headers[HTTP_SERVER_NS::CONTENT_TYPE] = HTTP_SERVER_NS::CONTENT_TYPE_TEXT;
                        response.body = "Welcome to the APM demo!";
                        span->End();
                        return 200;
                    }
                    span->End();
                    return 404;
                }
              };
            }  // namespace
          
            int main(int argc, char *argv[]) {
                InitTracer();
          
                // The port the validation service listens to can be specified via the command line.
                if (argc > 1) {
                  server_port = (uint16_t) atoi(argv[1]);
                }
          
                HttpServer http_server(server_name, server_port);
                RequestHandler req_handler;
                http_server.AddHandler("/helloworld", &req_handler);
                auto root_span = get_tracer("http_server")->StartSpan(__func__);
                Scope scope(root_span);
                http_server.Start();
                std::cout << "Server is running..Press ctrl-c to exit...
          ";
                while (1) {
                  std::this_thread::sleep_for(std::chrono::seconds(100));
                }
                http_server.Stop();
                root_span->End();
                CleanupTracer();
                return 0;
            }
          

          server.h file:

          // Copyright The OpenTelemetry Authors
          // SPDX-License-Identifier: Apache-2.0
          
          #pragma once
          
          #include <atomic>
          #include <string>
          #include "opentelemetry/ext/http/server/http_server.h"
          
          namespace {
          
              class HttpServer : public HTTP_SERVER_NS::HttpRequestCallback {
          
              protected:
                  HTTP_SERVER_NS::HttpServer server_;
                  std::string server_url_;
                  uint16_t port_;
                  std::atomic<bool> is_running_{false};
          
              public:
                  HttpServer(std::string server_name = "test_server", uint16_t port = 8800) : port_(port) {
                      server_.setServerName(server_name);
                      server_.setKeepalive(false);
                  }
          
                  void AddHandler(std::string path, HTTP_SERVER_NS::HttpRequestCallback *request_handler) {
                      server_.addHandler(path, *request_handler);
                  }
          
                  void Start() {
                      if (!is_running_.exchange(true)) {
                          server_.addListeningPort(port_);
                          server_.start();
                      }
                  }
          
                  void Stop() {
                      if (is_running_.exchange(false)) {
                          server_.stop();
                      }
                  }
          
                  ~HttpServer() { Stop(); }
              };
          
          }  // namespace
    • .NET application access
      1. Add OpenTelemetry dependencies.
        dotnet add package OpenTelemetry
        dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
        dotnet add package OpenTelemetry.Extensions.Hosting
      2. Interconnect with OpenTelemetry.

        Add the following code to the top of the entry file:

        using OpenTelemetry;
        using OpenTelemetry.Resources;
        using OpenTelemetry.Trace;
        using OpenTelemetry.Exporter;

        Add the following content between WebApplication.CreateBuilder() and builder.Build() in the entry file:

        builder.Services.AddOpenTelemetry()
          .ConfigureResource(resource => resource
              .AddService(Application name.Component name.Environment name)
              .AddAttributes(new Dictionary<string, object> {
                  ["host.name"] = System.Net.Dns.GetHostName()
              })
          )
          .WithTracing(tracing => tracing
              .AddAspNetCoreInstrumentation()
              .AddOtlpExporter(opt => {
                  opt.Endpoint = new Uri(***.**.**.***:****);
                  opt.Headers = "Authentication=" + ******;
                  opt.Protocol = OtlpExportProtocol.Grpc;
              })
          );

        For details about non-intrusive access, see the official website.