Giter VIP home page Giter VIP logo

dylibso / observe-sdk Goto Github PK

View Code? Open in Web Editor NEW
151.0 6.0 7.0 3.35 MB

Continuous runtime observablity SDKs to monitor WebAssembly code.

Home Page: https://dev.dylibso.com/docs/observe/overview

License: Apache License 2.0

Makefile 0.69% Rust 38.87% C 1.46% Go 19.65% JavaScript 5.38% TypeScript 32.68% HTML 0.16% Shell 0.13% Dockerfile 0.54% Just 0.44%
opentelemetry wasmtime webassembly instrumentation otel tracing

observe-sdk's Introduction

Checkout the official overview and documentation here:
https://dev.dylibso.com/docs/observe/overview


WebAssembly Observability - Observe SDK by Dylibso

CI

WebAssembly Observability Toolkit

Observe provides observability SDKs for WebAssembly, enabling continuous monitoring of WebAssembly code as it executes within a runtime.

This repository contains the Runtime SDKs and the Adapters necessary to have live profiling & tracing, and over time will include a complete observability stack for WebAssembly.

SDKs and Official Adapters

The table below tracks the supported Runtime SDKs and Adapters for the host application language that is running a WebAssembly module. The Runtime SDKs link to a particular WebAssembly runtime, and the Adapter formats the raw telemetry data to be emitted to a particular output/sink. If you need support for another Adapter, please open an issue here or email [email protected].

Note: Any supported Runtime SDK can be paired with any Adapter from the same language.

Language Runtime SDKs Adapters
Rust Wasmtime Datadog, Honeycomb, Lightstep, OpenTelemetry (stdout), Zipkin
Go Wazero Datadog, Honeycomb, Lightstep, OpenTelemetry
JavaScript Native (Browser, Node, Deno, Bun) Datadog, Honeycomb, Lightstep

More languages, SDKs, and adapters are coming soon! Reach out to help us prioritize these additional components ([email protected]).

Overview

There are two components to this process:

  1. Including a runtime/host SDK
  2. Instrumenting the Wasm code

Including a runtime SDK and an Adapter

First you should choose a Host SDK corresponding to your host application's language and Wasm runtime. The Host SDK captures raw observability events from the running Wasm module and sends them to an adapter. You must choose an adapter based on where you want your data to go. At the moment, we support a few systems out of the box. In the future we will support a lot more and will have more community driven options. If you don't see support for your favorite observability tools feel free to reach out to us at ([email protected]).

Each language includes some examples demonstrating use with different adapters. You can view these examples here:

Instrumenting Wasm Modules

There are two ways to instrument the Wasm modules: automatically and manually.

Automatically instrument your Wasm

The easiest way to instrument your code right now is to use our instrumenting compiler. This is a tool that can look at your Wasm and recompile it with instrumentation built in. The compiler is available as a service. You can generate a key to use this service for free here.

To use the key:

curl --fail -F [email protected] https://compiler-preview.dylibso.com/instrument -X POST -H 'Authorization: Bearer <your-api-key>' > code.instr.wasm

Note: The Instrumentation Service https://compiler-preview.dylibso.com/instrument only re-compiles a .wasm binary and returns the updated code. We do not log or store any information about your submitted code. The compilation also adds no telemetry or other information besides the strictly-necessary auto-instrumentation to the .wasm instructions. If you would prefer to run this service yourself, please contact [email protected] to discuss the available options.

Manually instrument your Wasm

The Host SDKs expose a series of host functions that make up our Observe API. You can code directly against this if you wish. Because we are still changing and experimenting with this API, we have not built much tooling or support for this yet. See the Observe API README to learn more about the API and the language bindings we provide.

Expect to see some documentation and alpha tools by September 2023. We will be building out a lot of the language specific layers, but we hope the community can help by building tools on top of it and integrating with existing libraries like OpenTelemetry.

Development

Building

To build the current wasmtime-based SDK, run:

$ cargo build

Testing

$ make test

Compile the Test Modules

These are already checked in, but you can compile and instrument them with. Please check in any changes in the test/ directory.

make instrument WASM_INSTR_API_KEY=<your-api-key>

Running Zipkin

One of the test adapters will output to Zipkin, defaulting to one running on localhost.

docker run -d -p 9411:9411 openzipkin/zipkin

Component Support

WIT is available in wit for the (manual) observe api and (automatic) observe instrument api.

Examples

First install dependencies:

cargo install wasm-tools cargo-component

Build the wit:

just build_wit

Build and run component_demo:

just component_demo

Build and run component_demo_2:

just component_demo_2

observe-sdk's People

Contributors

bhelx avatar chrisdickinson avatar dependabot[bot] avatar g4vi avatar mhmd-azeez avatar nilslice avatar wikiwong avatar wwkeyboard avatar zshipko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

observe-sdk's Issues

Observe API C++ SDK

Currently the observe api may be used in C++, but requires using raw pointers to pass strings. It would nice to be able to use std::string to pass strings instead.

Component Model Support for Observe SDK

Enable support for the Observe SDK to execute and profile components. Since wazero does not yet support components, this issue is scoped to (in priority order):

To test, we'll have to compile a component that has been instrumented. We should be able to do this manually with the Rust Observe API

add version compat checks to JS

Similar to how we check for the min & maj version globals in the SDK for compatibility in Rust and Go (if instrumented automatically via the compiler) we should implement it in JS.

Move planktonic to the Observe-SDK repo

Move the planktonic repos to some subfolder in observe-sdk. It should get deployed when observe-sdk is deployed. It should have a readme and a little content about how it works. Maybe a short video.

Iota: Dynamic Adapter Swapping

As an Iota user, I would like to be able to dynamically swap the adapter used by Iota at request time, so that I have more flexibility when testing and demo'ing Observe Toolkit adapters

rust/tests/many_tests.rs may be flaky

On my machine many.rs never prints 250 times, usually it only print 200 times. However, it seems to work most of the time on CI.

test tests::integration_many ... FAILED

failures:

---- tests::integration_many stdout ----
thread 'tests::integration_many' panicked at 'assertion failed: `(left == right)`
  left: `200`,
 right: `250`', rust/tests/many_tests.rs:23:9
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
   1: core::panicking::panic_fmt
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:228:5
   4: many_tests::tests::integration_many
             at ./tests/many_tests.rs:23:9
   5: many_tests::tests::integration_many::{{closure}}
             at ./tests/many_tests.rs:12:30
   6: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
   7: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.


failures:
    tests::integration_many

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.65s

error: test failed, to rerun pass `--test many_tests`

Observe API single header libraries for C and C++

The simplicity of the Observe API bindings makes it an ideal library candidate to implement as a single header library. A script can make it easy to still provide the traditional src file + header setup for users that prefer that setup.

Support Span Errors

We should add errors on a span as a concept to the core Event data-structure. It should be mapped to sink equivalent concepts in the adapters.

take options by reference wherever possible

In the updated adapter.start calls or wherever we're passing in options, we should take the value by reference vs. expecting to own it. particularly in Rust, currently each trace context must make its own new Options, or if cloneable, copy it from elsewhere.

e.g.

- let trace_ctx = adapter.start(_, _, options);
+ let trace_ctx = adapter.start(_, _, &options);

It could also be done in Go so the value isn't copied around, but that's more of a performance/resource optimization than a pesky DX as it is in Rust.

Better testing

The testing situation is currently grim, mostly done by hand. A first start is to unit test the individual modules. We also need to simplistic and well understood modules that we can run and verify that the captured events match what we expected from the module.
This will involve building at least one of those modules, and making a list of others we'll need. Then well need a way to test that the modules are events are being generated correctly, however we should not let changes to the adapters break these tests.

Shutdown methods should wait on the channels to shutdown

The shutdown methods (e.g. https://github.com/dylibso/observe-sdk/blob/main/rust/src/adapter/otelstdout.rs#L97 ) should wait on the runtime instance to close it's side of the event channel. This does get tricky because we don't have a way to tell the runtime instance it needs to stop sending events. So the parts of this issue will be:

  1. the Collector needs to signal the InstrumentationContext that we're shutting down even collection
  2. A way for the InstrumentationContext to know that we are no longer collecting events, all future calls from the module should be noops (e.g. https://github.com/dylibso/observe-sdk/blob/main/rust/src/lib.rs#L135 )
  3. The InstrumentationContext needs to close events_tx
  4. When the Collector sees the channel is closed it needs to call shutdown on the adapter ( https://github.com/dylibso/observe-sdk/blob/main/rust/src/adapter/mod.rs#LL30C37-L30C48 )

go: Allow trace ID to be configured

For integration with existing traces, we should figure out how to allow the caller to provide a trace ID that can be used instead of generating one. This is primarily for the go otel adapter, but a more generic solution would be nice.

Rust Component Model Support for Observe SDK / Observe API

PR: #128

Updated Versioning

  • Remove checks on wasm-instr globals
    • Rust
    • Go
  • Support pre-namespace change instr api with deprecation warning
    • Rust
    • Go
    • JS
  • Error out pre-linking when observe api with old namespace is used
    • Rust
    • Go
    • JS
      [ ] Add advisory check on version in wasm-instr producers section, Moved out to own issue (#146) as it isn't essential for updated versioning/component support.
  • Document api versioning plan so changes can be implemented smoothly.
    -[ ] Glibc is the gold standard on c api versioning https://developers.redhat.com/blog/2019/08/01/how-the-gnu-c-library-handles-backward-compatibility#change_your_abi_with_compatibility . See what works with wasm. Linking model is different decided doing it all by hand is easiest for now.

Version Observe API

Similar to the Wasm Instr API we should version the observe api so we can detect if a module is compatible with the observe sdk before linking.

Unfortunately adding exported globals for major and minor version numbers may not be doable from source in guest languages as they don't really have an in-language equivalent. We could create a tool to append version numbers to a Wasm module, but we should consider alternative methods that don't require custom tooling.

Observe SDK: limit spans sent to sink

  • Go SDK
  • Rust SDK
  • JS SDK

The default should be applied similarly to each SDK, but have a method for configuring this at the SDK level.

For example, a possible approach is:

let mut trace_ctx = adapter.start(&mut linker, &data)?;
trace_ctx.set_trace_depth(4);

// OR.. avoiding mutability and any additional method surface area:

let config = TraceConfig {
   trace_depth: 4,
   ..default::Default(),
};
let trace_ctx = adapter.start(&mut linker, &data, &config)?;

Add native support of Observe-SDK in wasmtime runtime

As discussed over a mail thread, if someone wants to monitor their wasmplugins running inside Envoy proxy which uses Wasmtime runtime, atm observe-sdk can't be used because the runtime is the default one and we can't modify it to have the observe-sdk embedded into it.
Similar scenario happens when we use spin, since spin also uses wasmtime as wasm runtime.

One thing we can do that came out of a discussion with @nilslice is that, we can integrate observe-sdk in wasmtime and create/maintain a fork of wasmtime with builtin observe-sdk.

This issue is to track the discussion/work around this.

Race conditions with Go SDK

Running the stdout adapter on ../test/nested.instr.wasm can yield varying results. No triage has been done to determine if it occurs with the other adapters.

One run:

gavin@teleporter:~/dev/observe-sdk/go$ go run bin/stdout/main.go ../test/nested.c.instr.wasm
Hello from Wasm!
2023/11/17 14:59:47  Call to _start took 279.05µs
2023/11/17 14:59:47    Call to __main_void took 227.212µs
2023/11/17 14:59:47      Call to malloc took 20.93µs
2023/11/17 14:59:47      Call to main took 149.579µs
2023/11/17 14:59:47        Call to one took 144.082µs
2023/11/17 14:59:47          Call to two took 138.563µs
2023/11/17 14:59:47            Call to three took 132.061µs
2023/11/17 14:59:47              Call to printf took 125.978µs
2023/11/17 14:59:47                Call to vfprintf took 119.754µs
2023/11/17 14:59:47                  Call to printf_core took 94.882µs
2023/11/17 14:59:47                    Call to __fwritex took 87.077µs
2023/11/17 14:59:47                      Call to __stdio_write took 39.71µs
2023/11/17 14:59:47                        Call to writev took 33.156µs
2023/11/17 14:59:47                          Call to __wasi_fd_write took 21.692µs
2023/11/17 14:59:47    Call to __wasm_call_dtors took 21.599µs

Another run:

gavin@teleporter:~/dev/observe-sdk/go$ go run bin/stdout/main.go ../test/nested.c.instr.wasm
Hello from Wasm!
2023/11/17 14:59:50  Call to _start took 268.672µs
2023/11/17 14:59:50    Call to __main_void took 225.266µs
2023/11/17 14:59:50      Call to main took 158.609µs
2023/11/17 14:59:50        Call to one took 153.519µs
2023/11/17 14:59:50          Call to two took 146.536µs
2023/11/17 14:59:50            Call to three took 138.794µs
2023/11/17 14:59:50              Call to printf took 133.646µs
2023/11/17 14:59:50                Call to vfprintf took 127.749µs
2023/11/17 14:59:50                  Call to printf_core took 105.449µs
2023/11/17 14:59:50                    Call to __fwritex took 98.354µs
2023/11/17 14:59:50                      Call to __stdio_write took 48.64µs
2023/11/17 14:59:50                        Call to writev took 41.878µs
2023/11/17 14:59:50                          Call to __wasi_fd_write took 32.052µs
2023/11/17 14:59:50                            Call to __imported_wasi_snapshot_preview1_fd_write took 26.243µs`

In the second trace __imported_wasi_snapshot_preview1_fd_write shows up which wasn't in the first. However, then __wasm_call_dtors doesn't show up which was in the first trace.

Loosen crate dependency version requirements

wasmtime, serde, etc could all probably use less strict versions to increase compatibility across variety of end-user codebases. We should look at the "oldest" versions of these that support our needs and make those then minimum requirements. serde being set to "1" is probably safe.

wazero observe SDK otel json formatter

Just as we have a re-usable OTel JSON formatter in Rust, we should support it in Go. This will act as the basis for other adapters to wrap the formatter.

Logging in dev/debug modes

Related to #48, when we encounter situations that don't really make sense we should have a pattern in place to log some information and if in some operational mode for debug/dev then potentially panic/blow up in a way that informs us or end users of an issue.

This should be consistently disabled by default as to never block user code from executing even if the telemetry is impacted.

Benchmarking

We need repeatable benchmarks around the latency this introduces into executing the module. The benchmarks should focus on initially on anything that's run in line with the module as that's the most important place not to introduce latency. After we are confident in that code path we can concentrate on the collector and the adapters.

Observe Go SDK Arch Refinement

Refactor Go library to match the Rust concurrency architecture: #37

  • We should have a generic collector struct / func per module
  • it should capture the events
  • when it gets a shutdown it should send a new object, a tracevent payload, to the singleton adapter func

Warning messaging

Working on Updated Versioning. I added deprecation warnings for the old namespace dylibso_observe. However, I'm not sure they are going the right place or actually making it to the observe-sdk user across the languages and adapters. We should decide on a consistently policy for this and apply it everywhere.

Currently, the rust sdk outputs with log::warn! and the basic example is setup to by default log with warnings.

The go-sdk outputs to the standard logger with log.Println.

The js-sdk outputs with console.warn.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.