Skip to content

Commit

Permalink
examples: otlp: refactor and add instructions to run
Browse files Browse the repository at this point in the history
Signed-off-by: Aditya Prajapati <[email protected]>
  • Loading branch information
Aditya Prajapati authored and edsiper committed Oct 5, 2022
1 parent 0257e0a commit 7dff94f
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 1 deletion.
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ configure_file(sample_trace.bin sample_trace.bin COPYONLY)

# example: opentelemetry encoder
set(src
otlp-encoder.c
otlp-encoder/otlp-encoder.c
)

add_executable(ctraces-otlp-encoder ${src})
Expand Down
25 changes: 25 additions & 0 deletions examples/otlp-encoder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Instructions to run

After building the project with `-CTR_DEV=on`, the example can be found at `build/examples/ctraces-otlp-encoder`

The example encodes a ctraces context to a buffer and sends it to a locally running instance of the [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/). After setting up the collector locally by [following the instructions from their docs](https://opentelemetry.io/docs/collector/getting-started/), you can start the collector with the following config file:

```yaml
receivers:
otlp:
protocols:
http:
endpoint: "0.0.0.0:4318"

exporters:
logging:
loglevel: debug

service:
pipelines:
traces:
receivers: [otlp]
exporters: [logging]
```
Now you can run the example and see the trace data logged by the collector instance.
213 changes: 213 additions & 0 deletions examples/otlp-encoder/otlp-encoder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#include <ctraces/ctraces.h>
#include <unistd.h>
#include <curl/curl.h>

#define OTEL_SPAN_ID_LENGTH 8

struct ctrace_id *create_random_span_id()
{
char *buf;
ssize_t ret;
struct ctrace_id *cid;

buf = calloc(1, OTEL_SPAN_ID_LENGTH);
if (!buf) {
ctr_errno();
return NULL;
}

ret = ctr_random_get(buf, OTEL_SPAN_ID_LENGTH);
if (ret < 0) {
free(buf);
return NULL;
}

cid = ctr_id_create(buf, OTEL_SPAN_ID_LENGTH);
free(buf);

return cid;

}

int main()
{
cfl_sds_t buf;
struct ctrace *ctx;
struct ctrace_opts opts;
struct ctrace_span *span_root;
struct ctrace_span *span_child;
struct ctrace_span_event *event;
struct ctrace_resource_span *resource_span;
struct ctrace_resource *resource;
struct ctrace_scope_span *scope_span;
struct ctrace_instrumentation_scope *instrumentation_scope;
struct ctrace_link *link;
struct ctrace_id *span_id;
struct ctrace_id *trace_id;
struct cfl_array *array;
struct cfl_array *sub_array;
struct cfl_kvlist *kv;

struct curl_slist *headers;
CURL *curl;
CURLcode res;

/*
* create an options context: this is used to initialize a CTrace context only,
* it's not mandatory and you can pass a NULL instead on context creation.
*
* note: not used.
*/
ctr_opts_init(&opts);

/* ctrace context */
ctx = ctr_create(&opts);
if (!ctx) {
ctr_opts_exit(&opts);
exit(EXIT_FAILURE);
}

/* resource span */
resource_span = ctr_resource_span_create(ctx);
ctr_resource_span_set_schema_url(resource_span, "https://ctraces/resource_span_schema_url");

/* create a 'resource' for the 'resource span' in question */
resource = ctr_resource_span_get_resource(resource_span);
ctr_resource_set_dropped_attr_count(resource, 5);

/* scope span */
scope_span = ctr_scope_span_create(resource_span);
ctr_scope_span_set_schema_url(scope_span, "https://ctraces/scope_span_schema_url");

/* create an optional instrumentation scope */
instrumentation_scope = ctr_instrumentation_scope_create("ctrace", "a.b.c", 3, NULL);
ctr_scope_span_set_instrumentation_scope(scope_span, instrumentation_scope);

/* generate a random trace_id */
trace_id = ctr_id_create_random();

/* generate a random ID for the new span */
span_id = create_random_span_id();

/* Create a root span */
span_root = ctr_span_create(ctx, scope_span, "main", NULL);
if (!span_root) {
ctr_destroy(ctx);
ctr_opts_exit(&opts);
exit(EXIT_FAILURE);
}

/* assign the random ID */
ctr_span_set_span_id_with_cid(span_root, span_id);

/* set random trace_id */
ctr_span_set_trace_id_with_cid(span_root, trace_id);

/* add some attributes to the span */
ctr_span_set_attribute_string(span_root, "agent", "Fluent Bit");
ctr_span_set_attribute_int64(span_root, "year", 2022);
ctr_span_set_attribute_bool(span_root, "open_source", CTR_TRUE);
ctr_span_set_attribute_double(span_root, "temperature", 25.5);

/* pack an array: create an array context by using the CFL api */
array = cfl_array_create(4);
cfl_array_append_string(array, "first");
cfl_array_append_double(array, 2.0);
cfl_array_append_bool(array, CFL_FALSE);

sub_array = cfl_array_create(3);
cfl_array_append_double(sub_array, 3.1);
cfl_array_append_double(sub_array, 5.2);
cfl_array_append_double(sub_array, 6.3);
cfl_array_append_array(array, sub_array);

/* add array to the attribute list */
ctr_span_set_attribute_array(span_root, "my_array", array);

/* event: add one event and set attributes to it */
event = ctr_span_event_add(span_root, "connect to remote server");

ctr_span_event_set_attribute_string(event, "syscall 1", "open()");
ctr_span_event_set_attribute_string(event, "syscall 2", "connect()");
ctr_span_event_set_attribute_string(event, "syscall 3", "write()");

/* add a key/value pair list */
kv = cfl_kvlist_create(1);
cfl_kvlist_insert_string(kv, "language", "c");

ctr_span_set_attribute_kvlist(span_root, "my-list", kv);

/* create a child span */
span_child = ctr_span_create(ctx, scope_span, "do-work", span_root);
if (!span_child) {
ctr_destroy(ctx);
ctr_opts_exit(&opts);
exit(EXIT_FAILURE);
}

/* set trace_id */
ctr_span_set_trace_id_with_cid(span_child, trace_id);

/* use span_root ID as parent_span_id */
ctr_span_set_parent_span_id_with_cid(span_child, span_id);

/* delete old span id and generate a new one */
ctr_id_destroy(span_id);
span_id = create_random_span_id();
ctr_span_set_span_id_with_cid(span_child, span_id);

/* destroy the IDs since is not longer needed */
ctr_id_destroy(span_id);
ctr_id_destroy(trace_id);

/* change span kind to client */
ctr_span_kind_set(span_child, CTRACE_SPAN_CLIENT);

/* create a Link (no valid IDs of course) */
trace_id = ctr_id_create_random();
span_id = create_random_span_id();

link = ctr_link_create_with_cid(span_child, trace_id, span_id);
ctr_link_set_trace_state(link, "aaabbbccc");
ctr_link_set_dropped_attr_count(link, 2);

/* delete IDs */
ctr_id_destroy(span_id);
ctr_id_destroy(trace_id);

/* Encode Trace as otlp buffer */
buf = ctr_encode_opentelemetry_create(ctx);
if (!buf) {
ctr_destroy(ctx);
ctr_encode_opentelemetry_destroy(buf);
ctr_opts_exit(&opts);
exit(EXIT_FAILURE);
}

curl = curl_easy_init();

if (curl){
headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/x-protobuf");
curl_easy_setopt(curl, CURLOPT_URL, "0.0.0.0:4318/v1/traces");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, cfl_sds_len(buf));
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
curl_global_cleanup();

/* destroy the context */
ctr_destroy(ctx);
ctr_encode_opentelemetry_destroy(buf);

/* exit options (it release resources allocated) */
ctr_opts_exit(&opts);

return 0;
}

0 comments on commit 7dff94f

Please sign in to comment.