Skip to content

Commit 67ba335

Browse files
committed
feat: add C language binding
1 parent 32898b5 commit 67ba335

6 files changed

Lines changed: 1247 additions & 1 deletion

File tree

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ project(
1818

1919
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
2020
option(BUILD_STATIC_LIBS "Build static libraries" ON)
21+
option(BUILD_C_BINDING "Build C binding" OFF)
2122

2223
if (WIN32)
2324
option(DD_TRACE_STATIC_CRT "Build dd-trace-cpp with static CRT with MSVC" OFF)
@@ -376,3 +377,7 @@ install(
376377
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
377378
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
378379
)
380+
381+
if (BUILD_C_BINDING)
382+
add_subdirectory(binding/c)
383+
endif ()

bin/format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ formatter=clang-format-$version
1818
formatter_options="--style=file -i $*"
1919

2020
find_sources() {
21-
find include/ src/ examples/ test/ fuzz/ -type f \( -name '*.h' -o -name '*.cpp' \) "$@"
21+
find include/ src/ examples/ test/ fuzz/ binding/ -type f \( -name '*.h' -o -name '*.cpp' \) "$@"
2222
}
2323

2424
# If the correct version of clang-format is installed, then use it and quit.

binding/c/CMakeLists.txt

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
add_library(dd_trace_c SHARED)
2+
add_library(dd-trace-cpp::c_binding ALIAS dd_trace_c)
3+
4+
add_dependencies(dd_trace_c dd-trace-cpp::obj)
5+
6+
target_compile_definitions(dd_trace_c PRIVATE DDOG_TRACE_C_BUILDING)
7+
8+
target_sources(dd_trace_c
9+
PRIVATE
10+
$<TARGET_OBJECTS:dd-trace-cpp::obj>
11+
src/tracer.cpp
12+
)
13+
14+
if(DD_TRACE_TRANSPORT STREQUAL "curl")
15+
add_dependencies(dd_trace_c CURL::libcurl_shared)
16+
17+
target_sources(dd_trace_c
18+
PRIVATE
19+
${CMAKE_SOURCE_DIR}/src/datadog/curl.cpp
20+
${CMAKE_SOURCE_DIR}/src/datadog/default_http_client_curl.cpp
21+
)
22+
23+
target_link_libraries(dd_trace_c
24+
PRIVATE
25+
CURL::libcurl_shared
26+
)
27+
else()
28+
target_sources(dd_trace_c
29+
PRIVATE
30+
${CMAKE_SOURCE_DIR}/src/datadog/default_http_client_null.cpp
31+
)
32+
endif()
33+
34+
target_include_directories(dd_trace_c
35+
PUBLIC
36+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
37+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
38+
PRIVATE
39+
${CMAKE_SOURCE_DIR}/src
40+
)
41+
42+
target_link_libraries(dd_trace_c
43+
PUBLIC
44+
dd-trace-cpp::obj
45+
PRIVATE
46+
dd-trace-cpp::specs
47+
)
48+
49+
install(TARGETS dd_trace_c
50+
EXPORT dd-trace-cpp-targets
51+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
52+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
53+
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
54+
)
55+
56+
install(
57+
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/datadog
58+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
59+
)
60+
61+
if (DD_TRACE_BUILD_TESTING)
62+
add_executable(test_c_binding
63+
test/test_c_binding.cpp
64+
${CMAKE_SOURCE_DIR}/test/test.cpp
65+
${CMAKE_SOURCE_DIR}/test/mocks/collectors.cpp
66+
${CMAKE_SOURCE_DIR}/test/mocks/loggers.cpp
67+
)
68+
69+
target_include_directories(test_c_binding
70+
PRIVATE
71+
${CMAKE_SOURCE_DIR}/test
72+
${CMAKE_SOURCE_DIR}/src
73+
${CMAKE_SOURCE_DIR}/src/datadog
74+
${CMAKE_SOURCE_DIR}/include
75+
${CMAKE_SOURCE_DIR}/include/datadog
76+
${CMAKE_CURRENT_SOURCE_DIR}/include
77+
)
78+
79+
target_compile_definitions(test_c_binding
80+
PUBLIC
81+
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
82+
)
83+
84+
target_link_libraries(test_c_binding
85+
PRIVATE
86+
dd_trace_c
87+
dd-trace-cpp::static
88+
dd-trace-cpp::specs
89+
)
90+
91+
catch_discover_tests(test_c_binding)
92+
endif()
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#ifndef DDOG_TRACE_C_TRACER_H
2+
#define DDOG_TRACE_C_TRACER_H
3+
4+
#if defined(_WIN32)
5+
#if defined(DDOG_TRACE_C_BUILDING)
6+
#define DDOG_TRACE_C_API __declspec(dllexport)
7+
#else
8+
#define DDOG_TRACE_C_API __declspec(dllimport)
9+
#endif
10+
#elif defined(__GNUC__) || defined(__clang__)
11+
#define DDOG_TRACE_C_API __attribute__((visibility("default")))
12+
#else
13+
#define DDOG_TRACE_C_API
14+
#endif
15+
16+
#if defined(__cplusplus)
17+
extern "C" {
18+
#endif
19+
20+
// Callback used during trace context extraction. The tracer calls this
21+
// function for each propagation header it needs to read (e.g. "x-datadog-*").
22+
//
23+
// @param key Header name to look up
24+
// @return Header value, or NULL if the header is not present.
25+
// The returned pointer must remain valid until
26+
// ddog_trace_tracer_extract_or_create_span returns.
27+
typedef const char* (*ddog_trace_context_read_callback)(const char* key);
28+
29+
// Callback used during trace context injection. The tracer calls this
30+
// function for each propagation header it needs to write.
31+
//
32+
// @param key Header name to set
33+
// @param value Header value to set
34+
typedef void (*ddog_trace_context_write_callback)(const char* key,
35+
const char* value);
36+
37+
enum ddog_trace_tracer_option {
38+
DDOG_TRACE_OPT_SERVICE_NAME = 0,
39+
DDOG_TRACE_OPT_ENV = 1,
40+
DDOG_TRACE_OPT_VERSION = 2,
41+
DDOG_TRACE_OPT_AGENT_URL = 3,
42+
DDOG_TRACE_OPT_INTEGRATION_NAME = 4,
43+
DDOG_TRACE_OPT_INTEGRATION_VERSION = 5
44+
};
45+
46+
typedef void ddog_trace_conf_t;
47+
typedef void ddog_trace_tracer_t;
48+
typedef void ddog_trace_span_t;
49+
50+
// Creates a tracer configuration instance.
51+
//
52+
// @return Configuration handle, or NULL on allocation failure
53+
DDOG_TRACE_C_API ddog_trace_conf_t* ddog_trace_tracer_conf_new();
54+
55+
// Release a tracer configuration. Safe to call with NULL.
56+
//
57+
// @param handle Configuration handle to release
58+
DDOG_TRACE_C_API void ddog_trace_tracer_conf_free(ddog_trace_conf_t* handle);
59+
60+
// Set or update a configuration field. No-op if handle or value is NULL.
61+
//
62+
// @param handle Configuration handle
63+
// @param option Configuration option
64+
// @param value Configuration value
65+
DDOG_TRACE_C_API void ddog_trace_tracer_conf_set(
66+
ddog_trace_conf_t* handle, enum ddog_trace_tracer_option option,
67+
const char* value);
68+
69+
// Creates a tracer instance.
70+
//
71+
// @param conf_handle Configuration handle
72+
//
73+
// @return Tracer handle, or NULL on error (e.g. invalid config)
74+
DDOG_TRACE_C_API ddog_trace_tracer_t* ddog_trace_tracer_new(
75+
ddog_trace_conf_t* conf_handle);
76+
77+
// Release a tracer instance. Safe to call with NULL.
78+
//
79+
// @param tracer_handle Tracer handle to release
80+
DDOG_TRACE_C_API void ddog_trace_tracer_free(
81+
ddog_trace_tracer_t* tracer_handle);
82+
83+
// Create a span using a Tracer.
84+
//
85+
// @param tracer_handle Tracer handle
86+
// @param name Name of the span
87+
//
88+
// @return Span handle, or NULL on error
89+
DDOG_TRACE_C_API ddog_trace_span_t* ddog_trace_tracer_create_span(
90+
ddog_trace_tracer_t* tracer_handle, const char* name);
91+
92+
// Extract trace context from incoming headers, or create a new root span
93+
// if extraction fails. Never returns an error span; on extraction failure
94+
// a fresh root span is created.
95+
//
96+
// @param tracer_handle Tracer handle
97+
// @param on_context_read Callback invoked to read propagation headers
98+
// @param name Span name
99+
// @param resource Resource name (may be NULL)
100+
//
101+
// @return Span handle, or NULL if arguments are invalid
102+
DDOG_TRACE_C_API ddog_trace_span_t* ddog_trace_tracer_extract_or_create_span(
103+
ddog_trace_tracer_t* tracer_handle,
104+
ddog_trace_context_read_callback on_context_read, const char* name,
105+
const char* resource);
106+
107+
// Release a span instance. Safe to call with NULL.
108+
//
109+
// @param span_handle Span handle
110+
DDOG_TRACE_C_API void ddog_trace_span_free(ddog_trace_span_t* span_handle);
111+
112+
// Set a tag (key-value pair) on a span. No-op if any argument is NULL.
113+
//
114+
// @param span_handle Span handle
115+
// @param key Tag key
116+
// @param value Tag value
117+
DDOG_TRACE_C_API void ddog_trace_span_set_tag(ddog_trace_span_t* span_handle,
118+
const char* key,
119+
const char* value);
120+
121+
// Mark a span as erroneous. No-op if span_handle is NULL.
122+
//
123+
// @param span_handle Span handle
124+
// @param error_value Non-zero to mark as error, zero to clear
125+
DDOG_TRACE_C_API void ddog_trace_span_set_error(ddog_trace_span_t* span_handle,
126+
int error_value);
127+
128+
// Set an error message on a span. No-op if any argument is NULL.
129+
//
130+
// @param span_handle Span handle
131+
// @param error_message Error message string
132+
DDOG_TRACE_C_API void ddog_trace_span_set_error_message(
133+
ddog_trace_span_t* span_handle, const char* error_message);
134+
135+
// Inject trace context into outgoing headers via callback.
136+
// No-op if any argument is NULL.
137+
//
138+
// @param span_handle Span handle
139+
// @param on_context_write Callback invoked per propagation header
140+
DDOG_TRACE_C_API void ddog_trace_span_inject(
141+
ddog_trace_span_t* span_handle,
142+
ddog_trace_context_write_callback on_context_write);
143+
144+
// Create a child span. Returns NULL if any required argument is NULL.
145+
//
146+
// @param span_handle Parent span handle
147+
// @param name Name of the child span
148+
//
149+
// @return Child span handle, or NULL
150+
DDOG_TRACE_C_API ddog_trace_span_t* ddog_trace_span_create_child(
151+
ddog_trace_span_t* span_handle, const char* name);
152+
153+
// Finish a span by recording its end time. No-op if span_handle is NULL.
154+
// After finishing, the span should be freed with ddog_trace_span_free.
155+
//
156+
// @param span_handle Span handle
157+
DDOG_TRACE_C_API void ddog_trace_span_finish(ddog_trace_span_t* span_handle);
158+
159+
// Get the trace ID as a zero-padded hex string.
160+
//
161+
// @param span_handle Span handle
162+
// @param buffer Output buffer (at least 33 bytes for 128-bit IDs)
163+
// @param buffer_size Size of the buffer
164+
// @return Number of characters written, or -1 on error
165+
DDOG_TRACE_C_API int ddog_trace_span_get_trace_id(
166+
ddog_trace_span_t* span_handle, char* buffer, int buffer_size);
167+
168+
// Get the span ID as a zero-padded hex string.
169+
//
170+
// @param span_handle Span handle
171+
// @param buffer Output buffer (at least 17 bytes)
172+
// @param buffer_size Size of the buffer
173+
// @return Number of characters written (16), or -1 on error
174+
DDOG_TRACE_C_API int ddog_trace_span_get_span_id(ddog_trace_span_t* span_handle,
175+
char* buffer, int buffer_size);
176+
177+
// Set the resource name on a span. No-op if any argument is NULL.
178+
//
179+
// @param span_handle Span handle
180+
// @param resource Resource name
181+
DDOG_TRACE_C_API void ddog_trace_span_set_resource(
182+
ddog_trace_span_t* span_handle, const char* resource);
183+
184+
// Set the service name on a span. No-op if any argument is NULL.
185+
//
186+
// @param span_handle Span handle
187+
// @param service Service name
188+
DDOG_TRACE_C_API void ddog_trace_span_set_service(
189+
ddog_trace_span_t* span_handle, const char* service);
190+
191+
// Set multiple tags at once. No-op if any required argument is NULL or
192+
// count <= 0. Individual entries where key or value is NULL are skipped.
193+
//
194+
// @param span_handle Span handle
195+
// @param keys Array of tag keys
196+
// @param values Array of tag values
197+
// @param count Number of tags
198+
DDOG_TRACE_C_API void ddog_trace_span_set_tags(ddog_trace_span_t* span_handle,
199+
const char** keys,
200+
const char** values, int count);
201+
202+
// Get the sampling priority for the trace this span belongs to.
203+
//
204+
// @param span_handle Span handle
205+
// @param priority Output: sampling priority value
206+
// @return 1 if a priority was written, 0 if no decision yet,
207+
// -1 on error (NULL arguments)
208+
DDOG_TRACE_C_API int ddog_trace_span_get_sampling_priority(
209+
ddog_trace_span_t* span_handle, int* priority);
210+
211+
// Override the sampling priority for the trace this span belongs to.
212+
// No-op if span_handle is NULL.
213+
//
214+
// @param span_handle Span handle
215+
// @param priority Sampling priority value
216+
DDOG_TRACE_C_API void ddog_trace_span_set_sampling_priority(
217+
ddog_trace_span_t* span_handle, int priority);
218+
219+
// Create a child span with explicit service and resource names.
220+
// Returns NULL if span_handle or name is NULL. service and resource may
221+
// be NULL (inherits from parent).
222+
//
223+
// @param span_handle Parent span handle
224+
// @param name Span name (required)
225+
// @param service Service name (may be NULL)
226+
// @param resource Resource name (may be NULL)
227+
//
228+
// @return Child span handle, or NULL
229+
DDOG_TRACE_C_API ddog_trace_span_t* ddog_trace_span_create_child_with_options(
230+
ddog_trace_span_t* span_handle, const char* name, const char* service,
231+
const char* resource);
232+
233+
#if defined(__cplusplus)
234+
}
235+
#endif
236+
237+
#endif

0 commit comments

Comments
 (0)