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

test/examples: various improvements #157

Merged
merged 12 commits into from
Mar 4, 2024
Merged
28 changes: 19 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,19 @@ jobs:
with:
version: "23.4"

- name: Install Component CLI Deps
uses: actions-rs/cargo@v1
with:
command: install
args: wasm-tools@^1.0.57 [email protected]

- name: Install Just
uses: extractions/setup-just@v1

# building wit is necessary for cargo test
- name: Build wit
run: just build_wit

- name: Run cargo test
uses: actions-rs/cargo@v1
with:
Expand All @@ -106,20 +119,17 @@ jobs:
| jq '.resourceSpans[].scopeSpans[].spans[0].attributes[0]' \
| jq '.key == "function_name", .value.stringValue == "_start"'

- name: Install Component CLI Deps
- name: Run Reactor example
uses: actions-rs/cargo@v1
with:
command: install
args: wasm-tools cargo-component

- name: Install Just
uses: extractions/setup-just@v1

- name: Build wit
run: just build_wit
command: run
args: --example=reactor-hello test/reactor-hello.c.instr.wasm

- name: Component Demo
run: just component_demo

- name: Component Demo 2
run: just component_demo_2

- name: Component Demo 3
run: just component_demo_3
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ target
build.js
node_modules
dist
corpus/01-component-instr-component/wit/deps/observe/observe.wit
34 changes: 23 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
WASICC?=$(WASI_SDK_PATH)/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot
WASM_INSTR_API_KEY=?

WASM_INSTR_API_KEY?=
.NOTINTERMEDIATE:
.PHONY: test
test:
cargo run --example=basic test/test.c.instr.wasm "Test"
cargo run --example=many test/test.c.instr.wasm "Test"

C_MODULES := $(wildcard test/*.c)
RS_MODULES := $(wildcard test/*.rs)
instrument:
@for file in $(C_MODULES); do \
$(WASICC) -o $$file.wasm $$file; \
curl -F wasm=@$$file.wasm https://compiler-preview.dylibso.com/instrument -X POST -H "Authorization: Bearer $(WASM_INSTR_API_KEY)" > $$file.instr.wasm; \
done
@for file in $(RS_MODULES); do \
rustc $$file --target=wasm32-wasi -C opt-level=3 -C debuginfo=0 -o $$file.wasm; \
curl -F wasm=@$$file.wasm https://compiler-preview.dylibso.com/instrument -X POST -H "Authorization: Bearer $(WASM_INSTR_API_KEY)" > $$file.instr.wasm; \
done
ALL_MODULES := $(C_MODULES) $(RS_MODULES)
ALL_MODULES_INSTR_WASM := $(addsuffix .instr.wasm, $(ALL_MODULES))

test/reactor-%.c.wasm: test/reactor-%.c
$(WASICC) -mexec-model=reactor -o $@ $^

test/%.c.wasm: test/%.c
$(WASICC) -o $@ $^

test/%.rs.wasm: test/%.rs
rustc $^ --target=wasm32-wasi -C opt-level=3 -C debuginfo=0 -o $@

test/%.instr.wasm: test/%.wasm
curl -F wasm=@$^ https://compiler-preview.dylibso.com/instrument -X POST -H "Authorization: Bearer $(WASM_INSTR_API_KEY)" > $@

.PHONY: instrument
instrument: $(ALL_MODULES_INSTR_WASM)

.PHONY: clean
clean:
rm -f test/*.wasm
8 changes: 8 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ _edit:

build_wit:
wasm-tools component wit wit/observe.wit -w -o wit/observe.wasm
mkdir -p corpus/01-component-instr-component/wit/deps/observe
cp wit/observe.wit corpus/01-component-instr-component/wit/deps/observe/

component_demo:
#!/bin/bash
Expand All @@ -24,5 +26,11 @@ component_demo_2:
)
(cd rust/; cargo run -F component-model --example otel-stdout-components ../corpus/02-component-instr-combined/target/wasm32-wasi/debug/final.wasm)

component_demo_3:
#!/bin/bash
set -eou pipefail
(cd corpus/01-component-instr-component; cargo component build)
(cd rust/; cargo run -F component-model --example reactor-hello-world-otel-stdout-components ../corpus/01-component-instr-component/target/wasm32-wasi/debug/component_instr_component.wasm)

local_instr instr_path="../wasm-instr/wasm-instr":
for i in test/*.c.wasm; do o=${i%.wasm}; {{ instr_path }} $i > $o.instr.wasm; done
88 changes: 88 additions & 0 deletions rust/examples/reactor-hello-world-otel-stdout-components.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use dylibso_observe_sdk::{
adapter::otelstdout::OtelStdoutAdapter,
context::component::{ObserveSdk, ObserveSdkView},
};

use wasmtime_wasi::preview2::{ResourceTable, WasiCtx, WasiView};

struct State {
table: ResourceTable,
wasi_ctx: WasiCtx,
observe_sdk: ObserveSdk,
}

impl WasiView for State {
fn table(&self) -> &ResourceTable {
&self.table
}

fn table_mut(&mut self) -> &mut ResourceTable {
&mut self.table
}

fn ctx(&self) -> &WasiCtx {
&self.wasi_ctx
}

fn ctx_mut(&mut self) -> &mut WasiCtx {
&mut self.wasi_ctx
}
}

impl ObserveSdkView for State {
fn sdk_mut(&mut self) -> &mut ObserveSdk {
&mut self.observe_sdk
}
}

wasmtime::component::bindgen!({path: "../corpus/01-component-instr-component/wit", async: true});

#[tokio::main]
pub async fn main() -> anyhow::Result<()> {
let args: Vec<_> = std::env::args().skip(1).collect();
let data = std::fs::read(&args[0])?;
let mut config = wasmtime::Config::new();

config.async_support(true);
config.wasm_component_model(true);

// Create instance
let engine = wasmtime::Engine::new(&config)?;
let component = wasmtime::component::Component::new(&engine, &data)?;

let table = ResourceTable::new();

// Setup WASI
let wasi_ctx = wasmtime_wasi::preview2::WasiCtxBuilder::new()
.inherit_stdio()
.args(&args.clone())
.build();

let mut linker = wasmtime::component::Linker::new(&engine);

let adapter = OtelStdoutAdapter::create();
let observe_sdk = adapter.build_observe_sdk(&data, Default::default())?;

let state = State {
table,
wasi_ctx,
observe_sdk,
};
let mut store = wasmtime::Store::new(&engine, state);
wasmtime_wasi::preview2::command::add_to_linker(&mut linker)?;

dylibso_observe_sdk::context::component::add_to_linker(&mut linker)?;

let (component_instr_component, _instance) =
Example::instantiate_async(&mut store, &component, &linker).await?;

match component_instr_component.call_hello_world(&mut store).await {
Ok(result) => println!("hello_world: {:?}", result),
_ => println!("encountered error"),
};

let state = store.into_data();
state.observe_sdk.shutdown().await?;

Ok(())
}
64 changes: 64 additions & 0 deletions rust/examples/reactor-hello.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use dylibso_observe_sdk::adapter::stdout::StdoutAdapter;

#[tokio::main]
pub async fn main() -> anyhow::Result<()> {
env_logger::init_from_env(
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "warn"),
);
let args: Vec<_> = std::env::args().skip(1).collect();
let data = std::fs::read(&args[0])?;
let function_name = "hello";
let config = wasmtime::Config::new();

// Create instance
let engine = wasmtime::Engine::new(&config)?;
let module = wasmtime::Module::new(&engine, &data)?;

let adapter = StdoutAdapter::create();

// Setup WASI
let wasi_ctx = wasmtime_wasi::WasiCtxBuilder::new()
.inherit_env()?
.inherit_stdio()
.args(&args.clone())?
.build();

let mut store = wasmtime::Store::new(&engine, wasi_ctx);
let mut linker = wasmtime::Linker::new(&engine);
wasmtime_wasi::add_to_linker(&mut linker, |wasi| wasi)?;

// Provide the observability functions to the `Linker` to be made available
// to the instrumented guest code. These are safe to add and are a no-op
// if guest code is uninstrumented.
let trace_ctx = adapter.start(&mut linker, &data, Default::default())?;

let instance = linker.instantiate(&mut store, &module)?;

// call _initialize"
{
let f = instance
.get_func(&mut store, "_initialize")
.expect("function exists");
f.call(&mut store, &[], &mut []).unwrap();
}

// call hello
let f = instance
.get_func(&mut store, function_name)
.expect("function exists 2");
f.call(&mut store, &[], &mut []).unwrap();
trace_ctx.shutdown().await;

// call __wasm_call_dtors
// Normally reactors don't emit __wasm_call_dtors, but
// reactor-hello.c.instr.wasm includes it as an example of specifying
// a cleanup function in a reactor.
{
let f = instance
.get_func(&mut store, "__wasm_call_dtors")
.expect("function exists");
f.call(&mut store, &[], &mut []).unwrap();
}

Ok(())
}
2 changes: 2 additions & 0 deletions test/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BasedOnStyle: LLVM
IndentWidth: 2
11 changes: 11 additions & 0 deletions test/constructor-destructor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <stdio.h>

__attribute__((constructor)) static void constructor(void) {
printf("constructor\n");
}

int main(void) {}

__attribute__((destructor)) static void destructor(void) {
printf("destructor\n");
}
Binary file added test/constructor-destructor.c.instr.wasm
Binary file not shown.
Binary file added test/constructor-destructor.c.wasm
Binary file not shown.
38 changes: 19 additions & 19 deletions test/kitchensink.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,45 @@
#define IMPORT(a, b) __attribute__((import_module(a), import_name(b)))

IMPORT("dylibso:observe/api", "metric")
extern void metric(uint32_t, uint64_t, uint32_t);
extern void metric(uint32_t, uint32_t, uint32_t);
IMPORT("dylibso:observe/api", "log")
extern void log_write(uint32_t, uint64_t, uint32_t);
extern void log_write(uint32_t, uint32_t, uint32_t);
IMPORT("dylibso:observe/api", "span-enter")
extern void span_enter(uint64_t, uint32_t);
extern void span_enter(uint32_t, uint32_t);
IMPORT("dylibso:observe/api", "span-exit") extern void span_exit();

void custom_span_enter(char name[]) {
uintptr_t ptr = (uintptr_t)name;
uint64_t uint64_ptr = (uint64_t)ptr;
uint32_t uint32_length = (uint32_t)(strlen(name));
void custom_span_enter(const char name[]) {
const uintptr_t ptr = (uintptr_t)name;
const uint32_t uint32_ptr = ptr;
const uint32_t uint32_length = strlen(name);

span_enter(uint64_ptr, uint32_length);
span_enter(uint32_ptr, uint32_length);
}

void custom_span_exit() { span_exit(); }

void write_stat() {
char stat[] = "vowels.count:1|c";
static const char stat[] = "vowels.count:1|c";

uintptr_t ptr = (uintptr_t)stat;
uint64_t uint64_ptr = (uint64_t)ptr;
uint32_t uint32_length = (uint32_t)(strlen(stat));
const uintptr_t ptr = (uintptr_t)stat;
const uint32_t uint32_ptr = ptr;
const uint32_t uint32_length = strlen(stat);

custom_span_enter("statsd");
metric((uint64_t)1, uint64_ptr, uint32_length);
metric(1, uint32_ptr, uint32_length);
custom_span_exit();
}

void write_log() {
char stat[] = "Vowels Counted: 3\n";
static const char stat[] = "Vowels Counted: 3\n";

uintptr_t ptr = (uintptr_t)stat;
uint64_t uint64_ptr = (uint64_t)ptr;
uint32_t uint32_length = (uint32_t)(strlen(stat));
uint32_t uint32_level = (uint32_t)1;
const uintptr_t ptr = (uintptr_t)stat;
const uint32_t uint32_ptr = ptr;
const uint32_t uint32_length = strlen(stat);
const uint32_t uint32_level = 1;

custom_span_enter("log_write");
log_write(uint32_level, uint64_ptr, uint32_length);
log_write(uint32_level, uint32_ptr, uint32_length);
custom_span_exit();
}

Expand Down
Binary file modified test/kitchensink.c.instr.wasm
Binary file not shown.
Binary file modified test/kitchensink.c.wasm
Binary file not shown.
12 changes: 12 additions & 0 deletions test/reactor-hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdio.h>
#define EXPORT_AS(name) __attribute__((export_name(name)))

__attribute__((constructor)) static void constructor(void) {
printf("constructor\n");
}

EXPORT_AS("hello") void hello(void) { printf("hello world\n"); }

EXPORT_AS("__wasm_call_dtors") void __wasm_call_dtors(void) {
printf("real destructor\n");
}
Binary file added test/reactor-hello.c.instr.wasm
Binary file not shown.
Binary file added test/reactor-hello.c.wasm
Binary file not shown.
Loading