{"id":20317630,"url":"https://github.com/dynatrace/oneagent-sdk-for-c","last_synced_at":"2025-04-11T17:55:49.793Z","repository":{"id":48713616,"uuid":"112596763","full_name":"Dynatrace/OneAgent-SDK-for-C","owner":"Dynatrace","description":"Enables custom tracing of native applications in Dynatrace","archived":false,"fork":false,"pushed_at":"2023-07-04T10:51:28.000Z","size":27408,"stargazers_count":19,"open_issues_count":1,"forks_count":3,"subscribers_count":17,"default_branch":"master","last_synced_at":"2023-08-09T03:34:41.611Z","etag":null,"topics":["agent","apm","data-ingestion","dev-program","dynatrace","oneagent","sdk","sdk-cpp"],"latest_commit_sha":null,"homepage":"https://www.dynatrace.com/support/help/extend-dynatrace/oneagent-sdk/what-is-oneagent-sdk/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dynatrace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-30T10:12:45.000Z","updated_at":"2023-07-24T06:33:18.000Z","dependencies_parsed_at":"2023-01-30T00:16:00.816Z","dependency_job_id":null,"html_url":"https://github.com/Dynatrace/OneAgent-SDK-for-C","commit_stats":null,"previous_names":[],"tags_count":9,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-C","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-C/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-C/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-C/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dynatrace","download_url":"https://codeload.github.com/Dynatrace/OneAgent-SDK-for-C/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224673883,"owners_count":17350997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","apm","data-ingestion","dev-program","dynatrace","oneagent","sdk","sdk-cpp"],"created_at":"2024-11-14T18:34:25.481Z","updated_at":"2025-04-11T17:55:49.772Z","avatar_url":"https://github.com/Dynatrace.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dynatrace OneAgent SDK for C/C++\n\nThis SDK enables Dynatrace customers to extend request level visibility into any native process. The SDK is C based and thus can be used in any C or C++ application. It can also be used in other languages via language bindings.\nIn order to use the development kit you need to have access to the source code of the application in question.\n\nThis is the official C/C++ implementation of the [Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK/).\n\n\u003c!-- Generate with https://github.com/jonschlinkert/markdown-toc --\u003e\n\n\u003c!-- toc --\u003e\n\n- [Package contents](#package-contents)\n- [Features](#features)\n- [Documentation](#documentation)\n- [Getting started](#getting-started)\n  * [Getting the SDK](#getting-the-sdk)\n  * [Building and linking against the Dynatrace OneAgent SDK](#building-and-linking-against-the-dynatrace-oneagent-sdk)\n    + [Using CMake](#using-cmake)\n    + [Auto-linking with Visual Studio](#auto-linking-with-visual-studio)\n    + [Other build systems](#other-build-systems)\n  * [Using CMake to build the samples](#using-cmake-to-build-the-samples)\n  * [Initializing the Dynatrace OneAgent SDK](#initializing-the-dynatrace-oneagent-sdk)\n    + [Special considerations for Solaris SPARC](#special-considerations-for-solaris-sparc)\n- [How to instrument your application](#how-to-instrument-your-application)\n  * [General notes](#general-notes)\n  * [Trace remote calls](#trace-remote-calls)\n  * [Trace SQL based database calls](#trace-sql-based-database-calls)\n  * [Trace incoming web requests](#trace-incoming-web-requests)\n  * [Trace outgoing web requests](#trace-outgoing-web-requests)\n  * [Trace asynchronous activities](#trace-asynchronous-activities)\n  * [Trace messaging](#trace-messaging)\n  * [Trace custom service methods](#trace-custom-service-methods)\n  * [Add custom request attributes](#add-custom-request-attributes)\n  * [Retrieve a W3C trace context](#retrieve-a-w3c-trace-context)\n- [Using the Dynatrace OneAgent SDK with forked child processes (only available on Linux)](#using-the-dynatrace-oneagent-sdk-with-forked-child-processes-only-available-on-linux)\n- [Troubleshooting](#troubleshooting)\n  * [Problems with initializing the SDK](#problems-with-initializing-the-sdk)\n  * [Problems occuring after initialization](#problems-occuring-after-initialization)\n- [Requirements](#requirements)\n  * [Version support and compatibility table](#version-support-and-compatibility-table)\n- [Help \u0026 Support](#help--support)\n  * [Read the manual](#read-the-manual)\n  * [Let us help you](#let-us-help-you)\n- [Release Notes](#release-notes)\n\n\u003c!-- tocstop --\u003e\n\n\u003ca name=\"package-contents\"\u003e\u003c/a\u003e\n\n## Package contents\n\nThe SDK package includes\n- `lib` and `include`: The libraries and header files necessary for instrumenting applications.\n- `*.cmake`: Optional support files to use the libraries more easily with the CMake build system.\n- `samples/sample1`: A simple sample application.\n- `docs`: Reference documentation.\n\n\u003ca name=\"features\"\u003e\u003c/a\u003e\n\n## Features\n\n- [Trace any remote call end-to-end across processes and different programming languages.](#trace-remote-calls)\n- [Trace any SQL-based database call.](#trace-sql-based-database-calls)\n- [Trace incoming and outgoing web requests.](#trace-incoming-web-requests)\n- [Trace asynchronous processing within one process.](#trace-outgoing-web-requests)\n- [Trace messaging systems and messaging queues.](#trace-messaging)\n- [Trace custom service methods.](#trace-custom-service-methods)\n- [Add custom request attributes to any currently traced service.](#add-custom-request-attributes)\n\nWhen tracing incoming or outgoing calls, requests or messages, this SDK is compatible with other OneAgent SDKs and OneAgent code modules in general.\n\nSee [Planned features for OneAgent\nSDK](https://answers.dynatrace.com/spaces/483/dynatrace-product-ideas/idea/198106/planned-features-for-oneagent-sdk.html) for details on\nupcoming features.\n\n\u003ca name=\"documentation\"\u003e\u003c/a\u003e\n\n## Documentation\n\nThe reference documentation is included in this package. The most recent version is also available online at \u003chttps://dynatrace.github.io/OneAgent-SDK-for-C/\u003e.\n\nA high level documentation/description of OneAgent SDK concepts is available at \u003chttps://github.com/Dynatrace/OneAgent-SDK/\u003e.\n\n\u003ca name=\"getting-started\"\u003e\u003c/a\u003e\n\n## Getting started\n\n\u003ca name=\"getting-the-sdk\"\u003e\u003c/a\u003e\n\n### Getting the SDK\n\nTo start using the Dynatrace OneAgent SDK for C/C++, simply download the latest source archive from [releases](https://github.com/Dynatrace/OneAgent-SDK-for-C/releases).\nThe source archive also includes all necessary artifacts (e.g. the static and dynamic library files), so this is all you need.\nExtract the archive to a local folder on your machine and then add the appropriate \"include\" and \"lib\" paths to your build system.\n\nTo see if your platform is supported, refer to [requirements](#requirements).\n\n\u003ca name=\"building-and-linking-against-the-dynatrace-oneagent-sdk\"\u003e\u003c/a\u003e\n\n### Building and linking against the Dynatrace OneAgent SDK\n\nThe SDK doesn't have to be compiled, you only need to link your application to the SDK libraries.\n\n\u003ca name=\"using-cmake\"\u003e\u003c/a\u003e\n\n#### Using CMake\n\nIf you use CMake to generate build files for your application, you should be able to use the provided `onesdk-config.cmake` script ala\n\n```CMake\ninclude(\"path/to/sdk-package/onesdk-config.cmake\")\ntarget_link_libraries(your_application onesdk_static)\n```\n\n\u003ca name=\"auto-linking-with-visual-studio\"\u003e\u003c/a\u003e\n\n#### Auto-linking with Visual Studio\n\nIf you use Visual Studio to build a Windows application, you can use the SDK's auto-linking feature. To do this, simply define the preprocessor macro `ONESDK_AUTO_LINK` before including any SDK header file.\nAside from that, you only have to add the appropriate \"include\" and \"lib\" paths.\n\n\u003ca name=\"other-build-systems\"\u003e\u003c/a\u003e\n\n#### Other build systems\n\nIf you use another build system you have to configure it to\n- add an \"include\" path to `path/to/sdk-package/include`\n- add a \"lib\" path to the appropriate platform subdirectory under `lib` (e.g. `path/to/sdk-package/lib/linux-x86_64`)\n- link the appropriate library (e.g. `libonesdk_static.a`)\n\nThe SDK contains code that dynamically loads the agent library (`.dll`/`.so`/...), so depending on your platform you might need to link\nadditional libraries (e.g. under Linux you would typically add `-ldl` to the linker command line).\n\nOn Windows, when using Visual Studio 2015 or later, you also have to link `legacy_stdio_definitions.lib`.\n\n\u003ca name=\"using-cmake-to-build-the-samples\"\u003e\u003c/a\u003e\n\n### Using CMake to build the samples\n\nAssuming that you have a C++11 compiler and suitable build system installed (e.g. Visual Studio or g++ \u0026 make), which are supported and correctly detected by CMake, creating build files for the samples can be as easy as\n\n```\nC:\\onesdk\\samples\u003emkdir build\nC:\\onesdk\\samples\u003ecd build\nC:\\onesdk\\samples\\build\u003ecmake ..\n  *snip* a lot of CMake output\n-- Build files have been written to: C:/onesdk/samples/build\nC:\\onesdk\\samples\\build\u003e\n```\n\nThen simply use your build system to build the samples (e.g. \"make\" or open \u0026 build the generated solution in Visual Studio).\n\n\u003ca name=\"initializing-the-dynatrace-oneagent-sdk\"\u003e\u003c/a\u003e\n\n### Initializing the Dynatrace OneAgent SDK\n\nTo initialize the OneAgent SDK, you call [`onesdk_initialize`][refd_initialize], like in the following sample. It is higly recommended that\nyou call [`onesdk_shutdown`][refd_shutdown] when the application is done using the SDK (typically just before exiting):\n\n```C\n#include \u003conesdk/onesdk.h\u003e\n#include \u003cstdio.h\u003e\n\nstatic void mycallback(char const* message) {\n    fputs(message, stderr);\n}\n\nint main(int argc, char** argv) {\n    onesdk_stub_process_cmdline_args(argc, argv, 1);  /* optional: let the SDK process command line arguments   */\n    onesdk_stub_strip_sdk_cmdline_args(\u0026argc, argv);  /* optional: remove SDK command line arguments from argv  */\n\n    /* Initialize SDK */\n    onesdk_result_t const onesdk_init_result = onesdk_initialize();\n\n    /* optional: Set logging callbacks. */\n    onesdk_agent_set_warning_callback(mycallback); /* Highly recommended. */\n    onesdk_agent_set_verbose_callback(mycallback); /* Recommended for development \u0026 debugging. */\n\n    /* ... use SDK ... */\n\n    /* Shut down SDK */\n    if (onesdk_init_result == ONESDK_SUCCESS)\n        onesdk_shutdown();\n\n    return 0;\n}\n```\n\n\u003e 📕 [Reference documentation for initialization and shutdown](https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html)  \n\u003e 📕 [Miscellaneous functions](https://dynatrace.github.io/OneAgent-SDK-for-C/group__misc.html)\n\n\u003ca name=\"special-considerations-for-solaris-sparc\"\u003e\u003c/a\u003e\n\n#### Special considerations for Solaris SPARC\n\nFor agents older than 1.173, auto-configuration is not supported for the OneAgent SDK for C/C++ on Solaris SPARC. Thus you must either use\n[`onesdk_stub_set_variable`][refd_set_variable] before calling [`initialize`][refd_initialize], or set certain environment variables. If you\nuse [`onesdk_stub_process_cmdline_args`][refd_process_cmdline_args], you can also use command line options. If you are familiar with [manual\ninjection for Apache or Java on\nSolaris](https://www.dynatrace.com/support/help/setup-and-configuration/oneagent/solaris/installation/install-oneagent-on-solaris/#expand-464manual-oneagent-injection),\nthis may sound familiar to you.\n\nThe following options must be set (to specify on the command line, use the `set_variable`-name but prepend `--dt_`):\n\n|`set_variable`|Environment variable |Value                                                                                      |\n|:-------------|:--------------------|:------------------------------------------------------------------------------------------|\n|`home`        |`DT_HOME`            |Your Dynatrace OneAgent installation folder, e.g. `/opt/dynatrace/oneagent/`.              |\n|`tenant`      |`DT_TENANT`          |The environment ID of your Dynatrace environment.                                          |\n|`tenantToken` |`DT_TENANTTOKEN`     |The token that OneAgent uses to connect to Dynatrace Server. **Not** an API or PaaS token! |\n|`server`      |`DT_CONNECTION_POINT`|One or multiple HTTP addresses that represent Dynatrace Servers or ActiveGates.            |\n\nPlease obtain the values of all these variables (except for `home` / `DT_HOME`) from `$DT_HOME/dynatrace-env.sh`. You can also use this\nscript directly to set the environment variables (except `DT_HOME`), or start your SDK-using application with\n`$DT_HOME/dynatrace-agent\u003cbitness\u003e.sh \u003cexecutable\u003e \u003cother command line arguments\u003e` (but you still need to set `home` / `DT_HOME`).\n\nFor example, to set `home` via [`onesdk_stub_set_variable`][refd_set_variable], do something like\n`onesdk_stub_set_variable(ONESDK_XSTR(\"home=/opt/dynatrace/oneagent\"), 0);` in your code OR set the `DT_HOME` environment variable, OR, if\nyour application calls [`onesdk_stub_process_cmdline_args`][refd_process_cmdline_args], you can pass `--dt_home=/opt/dynatrace/oneagent` on\nthe command line.\n\nThere is an additional option you may want to set: `loglevelcon` / `DT_LOGLEVELCON` can be set to `none` to stop the agent from writing to\nstderr (see also [Troubleshooting](#troubleshooting)).\n\n[refd_initialize]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#gac3d473d2899bdb54196f864ae0ccf3eb\n[refd_shutdown]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#gab65ee07ae9c61fae6d0ca0b4afbd8bb1\n[refd_set_variable]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#ga1271327bb21c71ed5f8d92de0629ebfc\n[refd_process_cmdline_args]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#ga77bf723c281e4e2963933a57ff1ec51c\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-remote-calls\"\u003e\u003c/a\u003e\n\n\u003ca name=\"how-to-instrument-your-application\"\u003e\u003c/a\u003e\n\n## How to instrument your application\n\nThis section gives samples of how to instrument your application for each supported feature. Refer to the [documentation](#documentation)\nfor more details.\n\n### General notes\n\nThe core API for instrumenting your application is the \"tracer\". Depending on the kind of operation you want to trace,\nyou use one of the `onesdk_*tracer_create` functions to create a tracer, then potentially set additional information using\nsetter functions before you start the tracer using `onesdk_tracer_start`. If an error or exception happens, you can capture it\nusing `onesdk_tracer_error`. Finally, you need to call `onesdk_tracer_end` to signal the end of the operation and also free up\nany resources allocated for the tracer.\n\nWhenever you start a tracer (i.e., call `onesdk_tracer_start`), the tracer becomes a child of the previously active tracer\non this thread and the new tracer then becomes the active tracer. You may only end the active tracer.\nIf you do, the tracer that was active before it (its parent) becomes active again.\nPut another way, tracers must be ended in reverse order of starting them\n(you can think of this being like HTML tags where you must also close the child tag before you can close the parent tag).\n\nWhile the tracer's automatic parent-child relationship works very intuitively in most cases,\nit does not work with **asynchronous patterns**, where the same thread handles multiple logically\nseparate operations in an interleaved way on the same thread. If you need to instrument\nsuch patterns with the SDK, you need to end your tracer before the thread is potentially reused\nby any other operation (e.g., before yielding to the event loop). To later continue the trace,\ncapture an in-process link before and later resume using the in-process link tracer, as explained in\n[Trace asynchronous activities](#trace-asynchronous-activities). This approach is rather awkward and\nmay lead to complex and difficult to interpret traces. If your application makes extensive use of\nasynchronous patterns of the kind that is difficult to instrument with the SDK, consider using\nthe [OpenTelemetry support of Dynatrace](https://www.dynatrace.com/support/help/shortlink/opent-cpp) instead.\n\n\u003e See also:\n\u003e\n\u003e 📕 [Reference documentation for common tracer functions](https://dynatrace.github.io/OneAgent-SDK-for-C/group__tracers.html)\n\n\u003ca name=\"trace-remote-calls\"\u003e\u003c/a\u003e\n\n### Trace remote calls\n\nYou can use the SDK to trace proprietary IPC communication from one process to the other. This will enable you to see full Service Flow,\nPurePath and Smartscape topology for remoting technologies that Dynatrace is not aware of.\n\nInstrumenting an outgoing remote call:\n\n```C\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_outgoingremotecalltracer_create(\n        onesdk_asciistr(\"remote service method\"),\n        onesdk_asciistr(\"logical service name\"),\n        onesdk_asciistr(\"deployed service endpoint\"),\n        ONESDK_CHANNEL_TYPE_TCP_IP,           /* channel type     */\n        onesdk_asciistr(\"localhost:12345\")    /* channel endpoint, host/ip:port in case of TCP_IP */ );\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* get byte representation of tag */\n    onesdk_size_t byte_tag_size = 0;\n    onesdk_tracer_get_outgoing_dynatrace_byte_tag(tracer, NULL, 0, \u0026byte_tag_size);\n    unsigned char* byte_tag = NULL;\n    if (byte_tag_size != 0) {\n        byte_tag = (unsigned char*)malloc(byte_tag_size);\n        if (byte_tag != NULL)\n            byte_tag_size = onesdk_tracer_get_outgoing_dynatrace_byte_tag(tracer, byte_tag, byte_tag_size, NULL);\n    }\n\n    /* ... do the actual remote call (send along `byte_tag` so the other side can continue tracing) ... */\n\n    /* release tag memory */\n    free(byte_tag);\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end and release tracer */\n    onesdk_tracer_end(tracer);\n```\n\nInstrumenting an incoming remote call:\n\n```C\n    unsigned char const* byte_tag = ...;    /* pointer to the byte tag that we received from the caller */\n    onesdk_size_t byte_tag_size = ...;      /* size of the byte tag that we received from the caller    */\n\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_incomingremotecalltracer_create(\n        onesdk_asciistr(\"remote service method\"),\n        onesdk_asciistr(\"logical service name\"),\n        onesdk_asciistr(\"deployed service endpoint\"));\n\n    /* set the tag that we got from the caller */\n    if (byte_tag_size != 0)\n        onesdk_tracer_set_incoming_dynatrace_byte_tag(tracer, byte_tag, byte_tag_size);\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* ... do the actual work ... */\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end \u0026 release tracer */\n    onesdk_tracer_end(tracer);\n```\n\n\u003e 📕 [Reference documentation for remote call tracers](https://dynatrace.github.io/OneAgent-SDK-for-C/group__remote__calls.html)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-sql-based-database-calls\"\u003e\u003c/a\u003e\n\u003ca name=\"trace-sql-based-database-calls\"\u003e\u003c/a\u003e\n\n### Trace SQL based database calls\n\nTo trace database requests you need a database info object which stores the information about your database which does not change between\nindividual requests. This will typically be created somewhere in your initialization code (after initializing the SDK):\n\n```C\nonesdk_databaseinfo_handle_t db_info_handle = ONESDK_INVALID_HANDLE;\n\n/* ... */\n\n    db_info_handle = onesdk_databaseinfo_create(\n        onesdk_asciistr(\"database name\"),   /* the name of the database that you connect to */\n        onesdk_asciistr(ONESDK_DATABASE_VENDOR_POSTGRESQL),   /* the type of the database   */\n        ONESDK_CHANNEL_TYPE_TCP_IP,         /* channel type     */\n        onesdk_asciistr(\"localhost:12345\")  /* channel endpoint */ );\n```\n\nThen you can trace the SQL database requests:\n\n```C\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_databaserequesttracer_create_sql(\n        db_info_handle,\n        onesdk_asciistr(\"SELECT foo FROM bar;\"));\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* ... perform the database request, consume results ... */\n\n    /* optional: set number of returned rows */\n    onesdk_databaserequesttracer_set_returned_row_count(tracer, 42);\n    /* optional: set number of round trips between client and database */\n    onesdk_databaserequesttracer_set_round_trip_count(tracer, 3);\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end \u0026 release tracer */\n    onesdk_tracer_end(tracer);\n```\n\nFinally, release the database info object in your cleanup code (before shutting down the SDK):\n\n```C\n    onesdk_databaseinfo_delete(db_info_handle);\n    db_info_handle = ONESDK_INVALID_HANDLE;\n```\n\nPlease note that SQL database traces are only created if they occur within some other SDK trace (e.g. incoming remote call).\n\n\u003e 📕 [Reference documentation for database request tracers](https://dynatrace.github.io/OneAgent-SDK-for-C/group__database__requests.html)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-incoming-web-requests\"\u003e\u003c/a\u003e\n\u003ca name=\"trace-incoming-web-requests\"\u003e\u003c/a\u003e\n\n### Trace incoming web requests\n\nTo trace incoming web requests you first need to create a web application info object which describes your web application:\n\n```C\nonesdk_webapplicationinfo_handle_t web_application_info_handle = ONESDK_INVALID_HANDLE;\n\n/* ... */\n\n    web_application_info_handle = onesdk_webapplicationinfo_create(\n        onesdk_asciistr(\"example.com\"),         /* name of the web server that hosts your application */\n        onesdk_asciistr(\"MyWebApplication\"),    /* unique name for your web application               */\n        onesdk_asciistr(\"/my-web-app/\")         /* context root of your web application               */ );\n```\n\nThen you can trace incoming web requests:\n\n```C\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_incomingwebrequesttracer_create(\n        web_application_info_handle,\n        onesdk_asciistr(\"/my-web-app/content.html?q1=1\u0026q2=2#frag\"),\n        onesdk_asciistr(\"GET\"));\n\n    /* add information about the incoming request */\n    onesdk_incomingwebrequesttracer_set_remote_address(tracer, onesdk_asciistr(\"1.2.3.4:56789\"));\n    onesdk_incomingwebrequesttracer_add_request_header(tracer,\n        onesdk_asciistr(\"Connection\"), onesdk_asciistr(\"keep-alive\"));\n    onesdk_incomingwebrequesttracer_add_request_header(tracer,\n        onesdk_asciistr(\"Pragma\"), onesdk_asciistr(\"no-cache\"));\n    /* ... */\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* ... service the web request ... */\n\n    /* add information about the response */\n    onesdk_incomingwebrequesttracer_add_response_header(tracer,\n        onesdk_asciistr(\"Transfer-Encoding\"), onesdk_asciistr(\"chunked\"));\n    onesdk_incomingwebrequesttracer_add_response_header(tracer,\n        onesdk_asciistr(\"Content-Length\"), onesdk_asciistr(\"1234\"));\n    onesdk_incomingwebrequesttracer_set_status_code(tracer, 200);\n    /* ... */\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end \u0026 release tracer */\n    onesdk_tracer_end(tracer);\n```\n\nAnd release the web application info object before shutting down the SDK:\n\n```C\n    onesdk_webapplicationinfo_delete(web_application_info_handle);\n    web_application_info_handle = ONESDK_INVALID_HANDLE;\n```\n\n\u003e 📕 [Reference documentation for incoming web request tracers](https://dynatrace.github.io/OneAgent-SDK-for-C/group__incoming__web__requests.html)\n\u003e\n\u003e ➡️ [Trace outgoing web requests](#trace-outgoing-web-requests)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-outgoing-web-requests\"\u003e\u003c/a\u003e\n\u003ca name=\"trace-outgoing-web-requests\"\u003e\u003c/a\u003e\n\n### Trace outgoing web requests\n\nYou can use the SDK to trace web requests sent by your application:\n\n```C\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_outgoingwebrequesttracer_create(\n        onesdk_asciistr(\"http://example.org:1234/my/rest-service/resources?filter=foo\"),\n        onesdk_asciistr(\"GET\"));\n\n    /* add information about the request we're about to send */\n    onesdk_outgoingwebrequesttracer_add_request_header(tracer,\n        onesdk_asciistr(\"Accept-Charset\"), onesdk_asciistr(\"utf-8\"));\n    onesdk_outgoingwebrequesttracer_add_request_header(tracer,\n        onesdk_asciistr(\"Pragma\"), onesdk_asciistr(\"no-cache\"));\n    /* ... */\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* get string representation of tag */\n    onesdk_size_t string_tag_size = 0;\n    onesdk_tracer_get_outgoing_dynatrace_string_tag(tracer, NULL, 0, \u0026string_tag_size);\n    char* string_tag = NULL;\n    if (string_tag_size != 0) {\n        string_tag = (char*)malloc(string_tag_size);\n        if (string_tag != NULL)\n            string_tag_size = onesdk_tracer_get_outgoing_dynatrace_string_tag(tracer, string_tag, string_tag_size, NULL);\n    }\n\n    /* ... actually send the HTTP request, sending along `string_tag` as an HTTP header\n           (use the macro `ONESDK_DYNATRACE_HTTP_HEADER_NAME` for the header name),\n           receive the reply and decode it ... */\n\n    /* release tag memory */\n    free(string_tag);\n\n    /* add information about the response */\n    onesdk_outgoingwebrequesttracer_add_response_header(tracer,\n        onesdk_asciistr(\"Transfer-Encoding\"), onesdk_asciistr(\"chunked\"));\n    onesdk_outgoingwebrequesttracer_add_response_header(tracer,\n        onesdk_asciistr(\"Content-Length\"), onesdk_asciistr(\"1234\"));\n    onesdk_outgoingwebrequesttracer_set_status_code(tracer, 200);\n    /* ... */\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end and release tracer */\n    onesdk_tracer_end(tracer);\n```\n\n\u003e 📕 [Reference documentation for outgoing web request tracers](https://dynatrace.github.io/OneAgent-SDK-for-C/group__outgoing__web__requests.html)\n\u003e\n\u003e ➡️ [Trace incoming web requests](#trace-incoming-web-requests)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-asynchronous-activities\"\u003e\u003c/a\u003e\n\u003ca name=\"trace-asynchronous-activities\"\u003e\u003c/a\u003e\n\n### Trace asynchronous activities\n\nMany applications schedule work in some asynchronous fashion. Automatic linking of tracers will not work in such scenarios - it can only link to the innermost active tracer on the current thread.\nTo link the asynchronous parts to the currently active tracer, you first have to create an in-process link:\n\n```C\n    /* create in-process link */\n    onesdk_size_t in_process_link_size = 0;\n    onesdk_inprocesslink_create(NULL, 0, \u0026in_process_link_size);\n    unsigned char* in_process_link = NULL;\n    if (in_process_link_size != 0) {\n        in_process_link = (unsigned char*)malloc(in_process_link_size);\n        if (in_process_link != NULL)\n            in_process_link_size = onesdk_inprocesslink_create(in_process_link, in_process_link_size, NULL);\n    }\n\n    /* ... start/queue asynchronous work (send along `in_process_link` so the other side can continue tracing) ... */\n\n    /* release in-process link memory */\n    free(in_process_link);\n```\n\nOnce you have the in-process link, you can create an in-process link tracer to continue tracing in another thread:\n\n```C\n    unsigned char const* in_process_link = ...;  /* pointer to the in-process link */\n    onesdk_size_t in_process_link_size = ...;    /* size of the in-process link    */\n\n    /* create in-process link tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_inprocesslinktracer_create(\n        in_process_link,\n        in_process_link_size);\n\n    /* start tracer (\"activates\" the in-process link) */\n    onesdk_tracer_start(tracer);\n\n    /* ... do the work - new tracers started here will be linked to wherever the in-process link was created ... */\n\n    /* end \u0026 release tracer (\"deactivates\" the in-process link) */\n    onesdk_tracer_end(tracer);\n```\n\nNote that you can re-use in-process links to create multiple in-process link tracers.\n\n\u003e 📕 [Reference documentation for in-process link functions](https://dynatrace.github.io/OneAgent-SDK-for-C/group__in__process__links.html)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-messaging\"\u003e\u003c/a\u003e\n\u003ca name=\"trace-messaging\"\u003e\u003c/a\u003e\n\n### Trace messaging\n\nTo trace interaction with a messaging system, such as sending and receiving messages from message queues, you need a messaging system info\nobject which stores the information about your messaging system that does not change between individual requests. This will typically be\ncreated somewhere in your initialization code (after initializing the SDK):\n\n```C\n    onesdk_messagingsysteminfo_handle_t messagingsysteminfo_handle = onesdk_messagingsysteminfo_create(\n        onesdk_asciistr(ONESDK_MESSAGING_VENDOR_RABBIT_MQ), // vendor name\n        onesdk_asciistr(\"myqueue\"),                         // destination name\n        ONESDK_MESSAGING_DESTINATION_TYPE_QUEUE,            // destination type\n        ONESDK_CHANNEL_TYPE_TCP_IP,                         // channel type\n        onesdk_asciistr(\"example.com:1234\"));               // channel endpoint\n```\n\nThen you can trace sending, receiving and processing of messages.\n\nTracing the sending of messages is straightforward and works like other tracers:\n\n```C\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_outgoingmessagetracer_create(messagingsysteminfo_handle);\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* get byte representation of tag (an ASCII string representation is also supported) */\n    onesdk_size_t byte_tag_size = 0;\n    onesdk_tracer_get_outgoing_dynatrace_byte_tag(tracer, NULL, 0, \u0026byte_tag_size);\n    unsigned char* byte_tag = NULL;\n    if (byte_tag_size != 0) {\n        byte_tag = (unsigned char*)malloc(byte_tag_size);\n        if (byte_tag != NULL)\n            byte_tag_size = onesdk_tracer_get_outgoing_dynatrace_byte_tag(tracer, byte_tag, byte_tag_size, NULL);\n    }\n\n    /* ... do the actual message sending (send along `byte_tag` so the other side can continue tracing) ... */\n    mymessage_add_header(mymessage, ONESDK_DYNATRACE_MESSAGE_PROPERTY_NAME, byte_tag, byte_tag_size);\n    mymessage_send(mymessage);\n\n    /* release tag memory */\n    free(byte_tag);\n\n    /* optional: set message ID, if provided by the messaging system */\n    onesdk_outgoingmessagetracer_set_vendor_message_id(tracer, onesdk_asciistr(mymessage_get_id_str(mymessage)));\n\n    /* optional: set correlation ID, if you have one (usually application-defined) */\n    onesdk_outgoingmessagetracer_set_correlation_id(tracer, onesdk_asciistr(mycorrelationid);\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end and release tracer */\n    onesdk_tracer_end(tracer);\n```\n\nFor the other side, we distinguish two activities: Receiving the message an processing it. You can (optionally) use a tracer around\nreceiving one or multiple messages if you are interested in the time the actual receiving takes. For the processing of the message, i.e.,\nany business logic that is executed in response to the message content, there is a different tracer. Note that only the tracer for\nprocessing messages supports an incoming tag. This is because the incoming tag must be set before starting the tracer and this cannot be\ndone for the receive-tracer, as the tag is normally part of the message content or headers, thus available only after message receipt.\n\nThe following example shows using the message receive and process tracers in the recommended combination, i.e., starting the process tracer\ninside the receive tracer:\n\n```C\n    onesdk_tracer_handle_t receive_tracer = onesdk_incomingmessagereceivetracer_create(messagingsysteminfo_handle);\n\n    /* start receive_tracer */\n    onesdk_tracer_start(receive_tracer);\n\n    while (/* ... e.g., a message is available in the queue, or only once ... */) {\n        /* ... actually receive a message, ... */\n\n        unsigned char const* byte_tag = mymessage_get_header_optional(mymessage, ONESDK_DYNATRACE_MESSAGE_PROPERTY_NAME);\n        onesdk_size_t byte_tag_size = ...;      /* size of the byte tag that we received (Note: byte_tag is not null-terminated) */\n\n        /* create process_tracer */\n        onesdk_tracer_handle_t const process_tracer = onesdk_incomingmessageprocesstracer_create(messagingsysteminfo_handle);\n\n        /* set the tag that we got from the message */\n        if (byte_tag_size != 0)\n            onesdk_tracer_set_incoming_dynatrace_byte_tag(process_tracer, byte_tag, byte_tag_size);\n\n        /* optional: set message ID, if provided by the messaging system */\n        onesdk_outgoingmessagetracer_set_vendor_message_id(process_tracer, onesdk_asciistr(mymessage_get_id_str(mymessage)));\n\n        /* optional: set correlation ID, if you have one (usually application-defined) */\n        onesdk_outgoingmessagetracer_set_correlation_id(process_tracer, onesdk_asciistr(mycorrelationid));\n\n        /* start process_tracer */\n        onesdk_tracer_start(process_tracer);\n\n        /* ... do the actual work: process the message content, do something in response, ... */\n\n        /* set error information */\n        if (something_went_wrong_with_processing)\n            onesdk_tracer_error(process_tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n        /* end \u0026 release process_tracer */\n        onesdk_tracer_end(process_tracer);\n    }\n    /* set error information */\n    if (something_went_wrong_with_receiving)\n        onesdk_tracer_error(receive_tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n    onesdk_tracer_end(receive_tracer);\n```\n\nNote that currently, the receive tracer will never create a new PurePath, so if it is not started inside another started tracer, nothing\nwill be traced by it (although the message process tracer will still work).\n\n\nYou should not forget to release the messaging system info object in your cleanup code (before shutting down the SDK):\n\n```C\n    onesdk_messagingsysteminfo_delete(messagingsysteminfo_handle);\n    messagingsysteminfo_handle = ONESDK_INVALID_HANDLE;\n```\n\n\u003e 📕 [Reference documentation for messaging tracers](https://dynatrace.github.io/OneAgent-SDK-for-C/group__messaging.html)  \n\u003e 📗 [Documentation on messaging tracers in the specification repository](https://github.com/Dynatrace/OneAgent-SDK#messaging)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-trace-custom-service-methods\"\u003e\u003c/a\u003e\n\u003ca name=\"trace-custom-service-methods\"\u003e\u003c/a\u003e\n\n### Trace custom service methods\n\nYou can use the SDK to trace custom service methods. A custom service method is a meaningful part of your code that you want to trace but\nthat does not fit any other tracer.\n\n```C\n    /* create tracer */\n    onesdk_tracer_handle_t const tracer = onesdk_customservicetracer_create(\n        onesdk_asciistr(\"custom service method\"),\n        onesdk_asciistr(\"logical service name\"));\n\n    /* start tracer */\n    onesdk_tracer_start(tracer);\n\n    /* ... actually execute the custom service ... */\n\n    /* set error information */\n    if (something_went_wrong)\n        onesdk_tracer_error(tracer, onesdk_asciistr(\"error type\"), onesdk_asciistr(\"error message\"));\n\n    /* end and release tracer */\n    onesdk_tracer_end(tracer);\n```\n\n\u003e 📕 [Reference documentation for custom service tracers](https://dynatrace.github.io/OneAgent-SDK-for-C/group__customservice.html)\n\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-to-add-custom-request-attributes\"\u003e\u003c/a\u003e\n\u003ca name=\"add-custom-request-attributes\"\u003e\u003c/a\u003e\n\n### Add custom request attributes\n\nYou can add custom request attributes (key value pairs) to the currently traced service. Those attributes can then be used to e.g. search/filter requests in Dynatrace.\nTo add a custom request attribute, simply call one of the `onesdk_customrequestattribute_add_{type}` functions:\n\n```C\n    /* add simple values */\n    onesdk_customrequestattribute_add_integer(onesdk_asciistr(\"account-id\"), 42);\n    onesdk_customrequestattribute_add_float(onesdk_asciistr(\"service-quality\"), 0.707106);\n    onesdk_customrequestattribute_add_string(onesdk_asciistr(\"region\"), onesdk_asciistr(\"emea\"));\n\n    /* add multiple values with the same key to create a list */\n    onesdk_customrequestattribute_add_integer(onesdk_asciistr(\"account-group\"), 1);\n    onesdk_customrequestattribute_add_integer(onesdk_asciistr(\"account-group\"), 2);\n    onesdk_customrequestattribute_add_integer(onesdk_asciistr(\"account-group\"), 3);\n```\n\nThis will add the custom request attributes to the currently traced service. If no tracer is active, the values will be discarded.\n\n\u003e 📕 [Reference documentation for custom request attributes](https://dynatrace.github.io/OneAgent-SDK-for-C/group__custom__request__attributes.html)\n\n\u003ca name=\"forking\"\u003e\u003c/a\u003e\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-with-forked-child-processes-only-available-on-linux\"\u003e\u003c/a\u003e\n\u003ca name=\"using-the-dynatrace-oneagent-sdk-with-forked-child-processes-not-available-on-windows\"\u003e\u003c/a\u003e\n\n\n\n\u003ca name=\"retrieve-a-w3c-trace-context\"\u003e\u003c/a\u003e\n\n### Retrieve a W3C trace context\n\nThis feature allows you to retrieve a W3C TraceContext trace ID and span ID referencing the current PurePath node,\nas defined in \u003chttps://www.w3.org/TR/trace-context\u003e.\n\nThis trace ID and span ID information is not intended for tagging and\ncontext-propagation scenarios and primarily designed for log-enrichment use\ncases. Use\n[`onesdk_tracer_get_outgoing_dynatrace_string_tag`][refd_tracer_get_outgoing_dynatrace_string_tag],\n[`onesdk_tracer_set_incoming_dynatrace_string_tag`][refd_tracer_set_incoming_dynatrace_string_tag],\n[`onesdk_tracer_get_outgoing_dynatrace_byte_tag`][refd_tracer_get_outgoing_dynatrace_byte_tag],\n[`onesdk_tracer_set_incoming_dynatrace_byte_tag`][refd_tracer_set_incoming_dynatrace_byte_tag]\nfor tagging traces (see the usage examples elsewhere in this document).\n\nThe following example shows how to print the current trace \u0026 span ID to stdout\nin a format that works well with Dynatrace Log Monitoring\n(see \u003chttps://www.dynatrace.com/support/help/shortlink/log-monitoring-log-enrichment\u003e for more):\n\n```c\n/* The context of the active tracer will be printed, so one should be active.\n   You can copy \u0026 paste from any other sample that starts a tracer. */\nonesdk_tracer_start(tracer);\n\nchar trace_id[ONESDK_TRACE_ID_BUFFER_SIZE];\nchar span_id[ONESDK_SPAN_ID_BUFFER_SIZE];\n\n/* A result code is returned, if and only if it is != ONESDK_SUCCESS, both IDs will consist of ASCII zeros only. */\nonesdk_tracecontext_get_current(trace_id, sizeof(trace_id), span_id, sizeof(span_id));\nfprintf(stderr, \"[!dt dt.trace_id=%s,dt.span_id=%s] Some important log info.\\n\", trace_id, span_id);\n```\n\n\n\u003e 📕 [Reference documentation for tracecontext][tcref]\n\n[tcref]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__tracecontext.html\n\n[refd_tracer_get_outgoing_dynatrace_string_tag]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__tracers.html#gad1a200fc7591163158458bb9938f4b29\n[refd_tracer_get_outgoing_dynatrace_byte_tag]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__tracers.html#ga7ae547cfdab36ab9464f82708fe9d414\n[refd_tracer_set_incoming_dynatrace_string_tag]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__tracers.html#ga332fb9c487786fb521f19d899079d0a6\n[refd_tracer_set_incoming_dynatrace_byte_tag]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__tracers.html#ga7a2c9b92ca453b575a1aa11cf5ab7ac8\n\n## Using the Dynatrace OneAgent SDK with forked child processes (only available on Linux)\n\nSome applications, especially web servers, use a concurrency model that is based on forked child processes. Typically a master process\nis started which is responsible only for creating and managing child processes by means of forking. The child processes do the real work,\nfor example handling web requests.\n\nThe recommended way to use the SDK in such a scenario is as follows: You initialize the SDK in the master using the [`onesdk_initialize_2`\nfunction][refd_initialize_2] passing the [`ONESDK_INIT_FLAG_FORKABLE` flag][refd_init_flag_forkable] in the flags argument. This way you\nwill not be able to use the SDK in the master process (attempts to do so will be ignored, if applicable with an error code), but all forked\nchild processes will share the same agent. This has a lower overhead, for example the startup of worker processes is not slowed down, and\nthe per-worker memory overhead is reduced.\n\n![Diagram color legend](img/fork-legend.png)\n\nRecommended, simple scenario:\n\n![Diagram showing how to pre-initialize the SDK in the parent/master process](img/fork-simple.png)\n\nDouble/daemon forks (i.e., a process forks a single child and then terminates) are also supported, as long as the intermediate child does\nnot use the SDK. If possible, it is better to initialize the SDK only in the intermediate child, as illustrated in the diagram below, but\ncalling `onesdk_initialize_2(ONESDK_FORKABLE)` in the master's parent process is also supported (take especial care to not use any SDK\nfunctions in the master then, not even `onesdk_agent_get_current_state`).\n\n![Diagram showing how to pre-initialize the SDK in the parent/master process and double forking](img/double-fork.png)\n\nThere are some scenarios where you may not be able to use this feature:\n\n* You have to use an older SDK or agent version which does not support the `onesdk_initialize_2` API, or\n* You have no control over the master process, i.e. are unable to ensure that `onesdk_initialize_2` is called before the first fork in the\n  master process.\n\nIn these cases, you can use the following workaround: Instead of initializing the SDK in the master process, you initialize it\n(without the `ONESDK_INIT_FLAG_FORKABLE` flag) in each worker process. This has the consequence that each process is monitored\nseparately with its own agent. This is not recommended as each per-worker agent will have to establish and maintain its own\nconnection to Dynatrace, which results in higher overhead, especially at startup.\n\n  ![Diagram showing how to initialize the SDK only in the child processes](img/init-child.png)\n\nWhen you initialize the SDK using `onesdk_initialize` or without passing `ONESDK_INIT_FLAG_FORKABLE` to `onesdk_initialize_2`,\nyou may not use the SDK in forked child processes (attempts to do so will simply do nothing and may return the `ONESDK_ERROR_FORK_CHILD`\nerror code).\n\n![Diagram showing how to pre-initialize the SDK in the parent/master process and double forking](img/fork-bad.png)\n\nExample for SDK initialization with `ONESDK_INIT_FLAG_FORKABLE`:\n\n```C\n#include \u003cstdio.h\u003e\n#include \u003cstring.h\u003e\n#include \u003cunistd.h\u003e\n\n#include \u003conesdk/onesdk.h\u003e\n\nonesdk_result_t g_onesdk_init_result = ONESDK_ERROR_NOT_INITIALIZED;\n\nint worker_main();\n\nint main(int argc, char** argv) {\n    onesdk_stub_process_cmdline_args(argc, argv, 1);  /* optional: let the SDK process command line arguments   */\n    onesdk_stub_strip_sdk_cmdline_args(\u0026argc, argv);  /* optional: remove SDK command line arguments from argv  */\n\n    /* Initialize SDK in forkable mode. */\n    g_onesdk_init_result = onesdk_initialize_2(ONESDK_INIT_FLAG_FORKABLE);\n    /* Assuming everything went well, the SDK is now in a _parent-initialized_ state. That means child processes\n       that this process forks will be able to use the SDK with very little initialization overhead.\n       (This process, the master, won't be able to use the SDK though.) */\n\n    /* This process can now proceed and fork some workers, either all at once or on demand ... */\n\n    static size_t const worker_count = 10;\n    for (size_t i = 0; i \u003c worker_count; ++i) {\n        int const worker_pid = fork();\n        if (worker_pid == -1) {\n            perror(\"fork(2) failed\");\n            return 1;\n        } else if (worker_pid == 0) {\n            return worker_main();\n        } else {\n            /* ... remember worker PID/establish communication ... */\n        }\n    }\n\n    /* ... maybe accept connections, dispatch work to the worker processes, wait(2) for them ... */\n\n    /* ... unitl eventualls it's time to shut down. */\n\n    /* Shut down SDK */\n    if (g_onesdk_init_result == ONESDK_SUCCESS)\n        onesdk_shutdown();\n\n    return 0;\n}\n\nint worker_main() {\n    /* Assuming everything went well in the parent process and `g_onesdk_init_result == ONESDK_SUCCESS`,\n       this process has inherited the SDK in a _pre-initialized_ state.\n       (The initialization state changes from _parent-initialized_ to _pre-initialized_ while forking.)\n       That means the SDK initialization will automatically be completed when this process begins to use\n       the SDK, e.g. when the first tracer is created... */\n\n    onesdk_tracer_handle_t const tracer = onesdk_sometracer_create(\n        onesdk_asciistr(\"some argument\"),\n        onesdk_asciistr(\"some other argument\"));\n\n    /* The SDK should now be fully initialized and the tracer should have been created successfully. */\n\n    onesdk_tracer_start(tracer);\n    /* ... do the actual work ... */\n    onesdk_tracer_end(tracer);\n\n    /* Since we inherited a _pre-initialized_ SDK state we have to call `onesdk_shutdown`. */\n    if (g_onesdk_init_result == ONESDK_SUCCESS)\n        onesdk_shutdown();\n    return 0;\n}\n```\n\n\u003ca name=\"fork-trouble\"\u003e\u003c/a\u003e\n\nAs the behavior of the SDK is sometimes complicated to understand with forking,\nthe [`onesdk_agent_get_fork_state`][refd_agent_get_fork_state] function is provided\nwhich can help you examine the state the SDK currently is in regarding forking.\nBasic usage is shown in sample1. You may want to call it before and after an SDK operation\nthat behaves/fails unexpectly if you use [`ONESDK_INIT_FLAG_FORKABLE`][refd_init_flag_forkable].\n\n\u003e 📕 Reference documentation for:\n\u003e * [initialization and shutdown](https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html)\n\u003e * [`onesdk_agent_get_fork_state`][refd_agent_get_fork_state]\n\n[refd_agent_get_fork_state]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__misc.html#ga77260efaf63455969962e05b6b170135\n[refd_initialize_2]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#gac0681af704ba7e6404c3f67f582ee4db\n[refd_init_flag_forkable]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#ga732bf07f0e190264baf29f3a1c22cc4a\n\n\u003ca name=\"troubleshooting\"\u003e\u003c/a\u003e\n\n## Troubleshooting\n\nThis section describes two broad categories of problems and how to debug them. The SDK has extensive\nlogging capabilites which will often point you quite directly at what the issue is.\n\n\u003ca name=\"troubleshooting-init\"\u003e\u003c/a\u003e\n\n### Problems with initializing the SDK\n\nMain symptom: [`onesdk_initialize`][refd_initialize] / [`onesdk_initalize_2`][refd_initialize_2] returning an error code.\n\nIf the SDK stub cannot load or initialize the agent module (see output of sample1), you can set the SDK stub's logging level to activate\nlogging of what happengs during initialization by either\n\n- setting the environment variable `DT_LOGLEVELSDK=FINEST`; or\n- calling [`onesdk_stub_set_logging_level(ONESDK_LOGGING_LEVEL_FINEST)`][refd_stub_set_logging_level]; or\n- if your program passes command line arguments to the SDK (see [`onesdk_stub_process_cmdline_args`][refd_process_cmdline_args]), you can\n  use the command line argument `--dt_loglevelsdk=FINEST`.\n\nWhichever method you choose (usually setting the environment variable is the easiest), make sure to apply it _before_ calling [`onesdk_initialize`][refd_initialize] / [`onesdk_initalize_2`][refd_initialize_2].\n\nOnce you have enabled logging, log output of the stub will be written to `stderr` by default. Refer to the [documentation for\n`onesdk_stub_set_logging_callback`][refd_stub_set_logging_callback] if you need to process stub log messages in another way.\n\nIf initialization fails, [`ONESDK_ERROR_LOAD_AGENT`][refd_error_load_agent] (numerical code 2952658951, -1342308345 or 0xaffe0007,\nerror message \"Could not load agent.\").\nis the most common error code. These are the two most common causes we have observed for this issue:\n\n1. The OneAgent is not installed on the host where the program runs. Install the OneAgent and restart the program.\n2. The program being run is started with a debugger.\n   The OneAgent will not inject in that case. Start the program without debugger.\n   You may still attach the debugger later, once the program is running.\n\n[refd_error_load_agent]: https://dynatrace.github.io/OneAgent-SDK-for-C/onesdk__common_8h.html#aa120990f128eb02bce1e88a489a7f398\n\n\u003ca name=\"troubleshooting-postinit\"\u003e\u003c/a\u003e\n\n### Problems occuring after initialization\n\nFor any problems you encounter after successful initialization\n(for example, no paths are shown in the UI, or you wonder why a function returns `ONESDK_INVALID_HANDLE` or another error code),\nit is best to check for messages from the agent logging callbacks: see\n[`onesdk_agent_set_warning_callback`][refd_agent_set_warning_callback] and\n[`onesdk_agent_set_verbose_callback`][refd_agent_set_verbose_callback] in the reference documentation or in sample1.\n\nYou can also check the agent log files (see the Dynatrace documentation for where to find them, e.g., on\n[Linux](https://www.dynatrace.com/support/help/shortlink/oneagent-files-linux#log-files) or\n[Windows](https://www.dynatrace.com/support/help/shortlink/oneagent-files-windows#log-files)).\nYou can increase the agent log level by setting the environment variable `DT_LOGLEVELFILE={level}` or passing the command line argument `--dt_loglevelfile={level}` to the SDK.\nThis will provide additional debug information in agent log file. (Alternatively you can use `DT_LOGLEVELCON={level}` or `--dt_loglevelcon={level}` if you want to receive agent log output via `stderr`.)\n\nLastly, in some situations, the [`onesdk_agent_get_current_state`][refd_agent_get_current_state] function may provide additional insights. See sample1 for a usage example.\n\nSpecial situations can arise when forking is involved, see [the section on forking](#forking).\n\n[refd_stub_set_logging_level]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#ga85b610bcd0d771fe641a1cd1ef03fd13\n[refd_stub_set_logging_callback]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__init.html#ga68fd905f95b1fdc05b7d45e5a419934d\n[refd_agent_set_warning_callback]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__misc.html#ga31c7f418f4b3515097434f8df6810cad\n[refd_agent_set_verbose_callback]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__misc.html#ga1324a8c95a407255e838641e8a8f03a9\n[refd_agent_get_current_state]: https://dynatrace.github.io/OneAgent-SDK-for-C/group__misc.html#gab45441c798009a1bad93480e8476a1e4\n\n\u003ca name=\"requirements\"\u003e\u003c/a\u003e\n\n## Requirements\n\n- Dynatrace OneAgent needs to be installed on the system that is to be monitored (required versions see below)\n- The supported environments are:\n    + Windows on x86\n    + Linux on x86. musl libc is currently not supported (e.g. used in Alpine Linux)\n    + Solaris on SPARC (x86 is *not* supported).\n      Support for this platform is new since version 1.3.2 of the SDK.\n\n  Refer to https://www.dynatrace.com/support/help/shortlink/supported-technologies#operating-systems for the exact versions supported by\n  OneAgent. Note that only the subset of operating systems and processor architectures explicitly listed both in this README and the link\n  are supported by the SDK.\n\n\u003ca name=\"compatibility-of-dynatrace-oneagent-sdk-for-cc-releases-with-oneagent-releases\"\u003e\u003c/a\u003e\n\u003ca name=\"version-support-and-compatibility-table\"\u003e\u003c/a\u003e\n\n### Version support and compatibility table\n\n|OneAgent SDK for C/C++|Dynatrace OneAgent|Support status or EOL date|\n|:---------------------|:-----------------|:-------------|\n|1.7.1                 |\u003e=1.251           |Supported     |\n|1.6.1                 |\u003e=1.179           |Supported     |\n|1.5.1                 |\u003e=1.179           |Deprecated with support ending 2023-07-01 |\n|1.4.1                 |\u003e=1.161           |Deprecated with support ending 2023-07-01 |\n|1.3.2                 |\u003e=1.159           |Deprecated with support ending 2023-07-01 |\n|1.3.1                 |\u003e=1.151           |Deprecated with support ending 2023-07-01 |\n|1.2.0                 |\u003e=1.147           |Deprecated with support ending 2023-07-01 |\n|1.1.0                 |\u003e=1.141           |Deprecated with support ending 2023-07-01 |\n|1.0.0                 |\u003e=1.133           |Deprecated with support ending 2023-07-01 |\n\nNote that this table only states the support status of the mentioned OneAgent SDK for C/C++ version,\nnot the OneAgent itself.\n\nYou should always try to update to the latest version if possible, as it may contain reliability or security\nimprovements (see respective release notes). This is especially true if an end of support date for your version\nis announced.\n\n\u003ca name=\"help\"\u003e\u003c/a\u003e\n\u003ca name=\"help--support\"\u003e\u003c/a\u003e\n\n## Help \u0026 Support\n\nThe Dynatrace OneAgent SDK for C/C++ is fully supported by Dynatrace. For the support status of a particular version, refer to the [version\nsupport and compatibility table](#version-support-and-compatibility-table). For detailed support policy see [Dynatrace OneAgent SDK\nhelp](https://github.com/Dynatrace/OneAgent-SDK#help).\n\n\n\u003ca name=\"read-the-manual\"\u003e\u003c/a\u003e\n\n### Read the manual\n\n* The most recent version of the reference documentation can be viewed at https://dynatrace.github.io/OneAgent-SDK-for-C/\n* A high level documentation/description of OneAgent SDK concepts is available at https://github.com/Dynatrace/OneAgent-SDK/.\n* Of course, this README also contains lots of useful information.\n\n\u003ca name=\"let-us-help-you\"\u003e\u003c/a\u003e\n\n### Let us help you\n\n**Get Help**\n* Ask a question in the [product forums](https://community.dynatrace.com/t5/Using-Dynatrace/ct-p/UsingDynatrace)\n* Read the [product documentation](https://www.dynatrace.com/support/help/)\n\n**Open a [GitHub issue](https://github.com/Dynatrace/OneAgent-SDK-for-C/issues) to:**\n* Report minor defects like typos\n* Ask any questions related to the community effort\n\nSLAs don't apply for GitHub tickets.\n\n**Customers can open a ticket on the [Dynatrace support portal](https://one.dynatrace.com/hc/) to:**\n* Get support from the Dynatrace technical support engineering team\n* Manage and resolve product related technical issues\n\nSLAs apply according to the customer's support level.\n\n\u003ca name=\"release-notes\"\u003e\u003c/a\u003e\n\n## Release Notes\n\nSee also \u003chttps://github.com/Dynatrace/OneAgent-SDK-for-C/releases\u003e.\n\n|Version|Description                                                                                                             |\n|:------|:-----------------------------------------------------------------------------------------------------------------------|\n|1.7.1  |Add W3C trace context support for log enrichment (not for tagging/linking). \u003cbr\u003e Announce deprecation of versions \u003c 1.6.1 |\n|1.6.1  |Deprecate metrics-related APIs. \u003cbr\u003e Don't look for agent module in `PATH/LD_LIBRARY_PATH/...`, disallow relative `DT_HOME` on Windows (prevent DLL hijacking)   |\n|1.5.1  |Added metrics APIs (preview feature), improved logging callback APIs, new API to query fork state                       |\n|1.4.1  |Added custom service tracers and messaging tracers                                                                      |\n|1.3.2  |Support for Solaris SPARC                                                                                               |\n|1.3.1  |Support for monitoring forked child processes, added new API to check agent version compatibility                       |\n|1.2.0  |Added in-process linking, added custom request attributes, added outgoing web request tracers                           |\n|1.1.0  |Added incoming web request tracers, added row count \u0026 round trip count for DB request tracers                           |\n|1.0.0  |Initial version                                                                                                         |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdynatrace%2Foneagent-sdk-for-c","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdynatrace%2Foneagent-sdk-for-c","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdynatrace%2Foneagent-sdk-for-c/lists"}