Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: observe api c++ bindings / improve observe api c bindings #165

Merged
merged 6 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions observe-api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ WASICXX?=$(WASI_SDK_PATH)/bin/clang++ --sysroot=${WASI_SDK_PATH}/share/wasi-sysr
build:
@cd test/rust && cargo build --target=wasm32-wasi && cd ../..
@cp test/rust/target/wasm32-wasi/debug/rust_guest.wasm test/rust_guest.wasm
$(WASICC) -o test/c_guest.wasm test/c/main.c c/observe_api.c
$(WASICXX) -o test/cxx_guest.wasm -x c++ test/c/main.c c/observe_api.c
$(WASICC) -o test/c_guest.wasm -I c test/c/main.c
$(WASICXX) -o test/cxx_guest.wasm -I c -x c++ test/c/main.c
$(WASICXX) -o test/cxx_guest_2.wasm -fno-exceptions -I c test/c/main.cpp
$(WASICXX) -o test/cxx_guest_3.wasm -fno-exceptions -I c test/c/main2.cpp
37 changes: 35 additions & 2 deletions observe-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,41 @@ Ideally, you will not call this API layer directly but instead use language spec

We currently provide these language bindings to this API:

* [rust](rust/) -- [example](test/rust/src/main.rs)
* [c](c/) -- [example](test/c/main.c)
### [rust](rust/)

* [example](test/rust/src/main.rs)


### [c and c++](c/)

Both the C and C++ bindings are implemented as header-only libraries. To use the C bindings,
in __ONE__ source file:

```c
#define OBSERVE_API_IMPLEMENTATION
#include "observe_api.h"
```

In other source files, just `#include "observe_api.h"`

* [example](test/c/main.c)

To use the C++ bindings, instead, in __ONE__ source file:

```c++
#define OBSERVE_API_IMPLEMENTATION
#define OBSERVE_API_CPP_IMPLEMENTATION
#include "observe_api.hpp"
```

In other source files, just `#include "observe_api.hpp"`

__NOTE:__ `observe_api.hpp` `#include`s `observe_api.h`

* [functional example](test/c/main.cpp)
* [OO example](test/c/main2.cpp)

### Other

More languages will come soon as well as tools built on top of these bindings. If you are planning on building your own tooling we suggest using or contributing one of these language specific bindings.

26 changes: 0 additions & 26 deletions observe-api/c/observe_api.c

This file was deleted.

107 changes: 92 additions & 15 deletions observe-api/c/observe_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,111 @@

#define IMPORT(a, b) __attribute__((import_module(a), import_name(b)))

enum DO_LOG_LEVEL {
DO_LL_ERROR = 1,
DO_LL_WARN = 2,
DO_LL_INFO = 3,
DO_LL_DEBUG = 4,
DO_LL_TRACE = 5
};

enum DO_METRIC_FMT { DO_MF_STATSD = 1 };

IMPORT("dylibso:observe/api", "metric")
extern void _metric(uint32_t, uint32_t, uint32_t);
extern void observe_api_metric_n(enum DO_METRIC_FMT format, const char *metric,
size_t metric_length);
IMPORT("dylibso:observe/api", "log")
extern void _log(uint32_t, uint32_t, uint32_t);
extern void observe_api_log_n(enum DO_LOG_LEVEL level, const char *message,
size_t message_length);
IMPORT("dylibso:observe/api", "span-enter")
extern void _span_enter(uint32_t, uint32_t);
extern void observe_api_span_enter_n(const char *name, size_t name_length);
IMPORT("dylibso:observe/api", "span-exit")
extern void _span_exit(void);

enum DO_LOG_LEVEL {
DO_LL_ERROR = 0,
DO_LL_WARN = 1,
DO_LL_INFO = 2,
DO_LL_DEBUG = 3,
DO_LL_TRACE = 4
};
extern void observe_api_span_exit(void);
IMPORT("dylibso:observe/api", "span-tags")
extern void observe_api_span_tags_n(const char *tags, size_t tags_length);

#ifdef __cplusplus
extern "C" {
#endif

void observe_api_span_enter(const char *name);
void observe_api_span_exit(void);
void observe_api_metric(const char *metric);
void observe_api_write_log(const enum DO_LOG_LEVEL level, const char *msg);
void observe_api_metric(enum DO_METRIC_FMT format, const char *message);
void observe_api_statsd_n(const char *metric, const size_t metric_length);
void observe_api_statsd(const char *metric);
void observe_api_log(const enum DO_LOG_LEVEL level, const char *msg);
void observe_api_span_tags(const char *tags);
void observe_api_span_tags_from_array(const char *const tags[],
size_t num_tags);

#ifdef __cplusplus
}
#endif

#endif // OBSERVE_API_H

// avoid greying out the implementation section
#if defined(Q_CREATOR_RUN) || defined(__INTELLISENSE__) || \
defined(_CDT_PARSER__)
#define OBSERVE_API_IMPLEMENTATION
#endif

#ifdef OBSERVE_API_IMPLEMENTATION
G4Vi marked this conversation as resolved.
Show resolved Hide resolved
#ifndef OBSERVE_API_C
#define OBSERVE_API_C

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

void observe_api_span_enter(const char *name) {
const size_t name_length = strlen(name);
observe_api_span_enter_n(name, name_length);
}

void observe_api_metric(enum DO_METRIC_FMT format, const char *metric) {
const size_t metric_length = strlen(metric);
observe_api_metric_n(format, metric, metric_length);
}

void observe_api_statsd_n(const char *metric, const size_t metric_length) {
observe_api_metric_n(DO_MF_STATSD, metric, metric_length);
}

void observe_api_statsd(const char *metric) {
observe_api_metric(DO_MF_STATSD, metric);
}

void observe_api_log(const enum DO_LOG_LEVEL level, const char *msg) {
const size_t msg_length = strlen(msg);
observe_api_log_n(level, msg, msg_length);
}

void observe_api_span_tags(const char *tags) {
const size_t tags_length = strlen(tags);
observe_api_span_tags_n(tags, tags_length);
}

void observe_api_span_tags_from_array(const char *const tags[],
size_t num_tags) {
char *tags_buf = 0;
size_t tags_buf_size = 0;
for (size_t i = 0; i < num_tags; i++) {
size_t new_tag_length = strlen(tags[i]);
size_t new_tags_buf_size = tags_buf_size + new_tag_length + 1;
char *new_tags_buf = (char *)realloc(tags_buf, new_tags_buf_size);
if (!new_tags_buf) {
break;
}
memcpy(new_tags_buf + tags_buf_size, tags[i], new_tag_length);
new_tags_buf[new_tags_buf_size - 1] = ',';
tags_buf = new_tags_buf;
tags_buf_size = new_tags_buf_size;
}
if (tags_buf_size > 0) {
observe_api_span_tags_n(tags_buf, tags_buf_size - 1);
free(tags_buf);
}
}

#endif // OBSERVE_API_C
#endif // OBSERVE_API_IMPLEMENTATION
88 changes: 88 additions & 0 deletions observe-api/c/observe_api.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#ifndef OBSERVE_API_HPP
#define OBSERVE_API_HPP

#include "observe_api.h"
#include <string>
#include <string_view>
#include <vector>

namespace observe_api {
void span_enter(std::string_view name);
void span_exit();
void metric(enum DO_METRIC_FMT format, std::string_view mtc);
void log(enum DO_LOG_LEVEL level, std::string_view message);
void span_tags(std::string_view tags);
void statsd(std::string_view mtc);
void span_tags(std::vector<std::string> &tags);

class Span {
public:
Span(std::string_view name) { span_enter(name); }
~Span() { span_exit(); }
void metric(enum DO_METRIC_FMT format, std::string_view mtc) {
observe_api::metric(format, mtc);
}
void tags(std::string_view tags) { span_tags(tags); }
void statsd(std::string_view mtc) { observe_api::statsd(mtc); }
void tags(std::vector<std::string> &tags) { span_tags(tags); }
};
}; // namespace observe_api

#endif // OBSERVE_API_HPP

// avoid greying out the implementation section
#if defined(Q_CREATOR_RUN) || defined(__INTELLISENSE__) || \
defined(_CDT_PARSER__)
#define OBSERVE_API_CPP_IMPLEMENTATION
#endif

#ifdef OBSERVE_API_CPP_IMPLEMENTATION
#ifndef OBSERVE_API_CPP
#define OBSERVE_API_CPP

#include "observe_api.h"
#include <iterator>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>

namespace observe_api {

void span_enter(std::string_view name) {
observe_api_span_enter_n(name.data(), name.size());
}

void span_exit() { observe_api_span_exit(); }

void metric(enum DO_METRIC_FMT format, std::string_view mtc) {
observe_api_metric_n(format, mtc.data(), mtc.size());
}

void log(enum DO_LOG_LEVEL level, std::string_view message) {
observe_api_log_n(level, message.data(), message.size());
}

void span_tags(std::string_view tags) {
observe_api_span_tags_n(tags.data(), tags.size());
}

void statsd(std::string_view mtc) {
observe_api_statsd_n(mtc.data(), mtc.size());
}

void span_tags(std::vector<std::string> &tags) {
const char *delim = ",";
std::ostringstream imploded;
std::copy(tags.begin(), tags.end(),
std::ostream_iterator<std::string>(imploded, delim));
std::string str = imploded.str();
if (str.size() > 0) {
observe_api_span_tags_n(str.data(), str.size() - 1);
}
}

}; // namespace observe_api

#endif // OBSERVE_API_CPP
#endif // OBSERVE_API_CPP_IMPLEMENTATION
8 changes: 7 additions & 1 deletion observe-api/test/c/main.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#include "../../c/observe_api.h"
#define OBSERVE_API_IMPLEMENTATION
#include "observe_api.h"
#include <stdio.h>
#include <stdlib.h>

void run() {
observe_api_span_enter("printf");
observe_api_statsd("ok:aaaaa");
observe_api_log(DO_LL_INFO, "bbbbb");
observe_api_span_tags("abbc:def,(another:tag");
const char *const tags[] = {"taga:one", "tagb:two"};
observe_api_span_tags_from_array(tags, sizeof(tags) / sizeof(tags[0]));
printf("Hello from Wasm!\n");
observe_api_span_exit();
}
Expand Down
23 changes: 23 additions & 0 deletions observe-api/test/c/main2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#define OBSERVE_API_IMPLEMENTATION
#define OBSERVE_API_CPP_IMPLEMENTATION
#include "observe_api.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>

void run() {
auto span = observe_api::Span("printf");
span.statsd("ok:aaaaa");
observe_api::log(DO_LL_INFO, "bbbbb");
span.tags("abbc:def,(another:tag");
std::vector<std::string> tags = {"taga:one", "tagb:two"};
span.tags(tags);
printf("Hello from Wasm!\n");
}

int main(int argc, char *argv[]) {
auto span = observe_api::Span("run");
run();
return 0;
}
Binary file modified observe-api/test/c_guest.wasm
Binary file not shown.
Binary file modified observe-api/test/cxx_guest.wasm
Binary file not shown.
Binary file added observe-api/test/cxx_guest_2.wasm
Binary file not shown.
Binary file added observe-api/test/cxx_guest_3.wasm
Binary file not shown.
Loading