Skip to content
This repository was archived by the owner on Dec 16, 2020. It is now read-only.

wasm: API to add tags to active span from wasm filter #384

Closed
wants to merge 14 commits into from
Closed
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
8 changes: 8 additions & 0 deletions api/wasm/cpp/doc/wasm_filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,14 @@ method is effective when calling from
Returns [WasmData](#wasmdata) pointer which
holds the response body data.

### activeSpanSetTag

``` {.sourceCode .cpp}
void activeSpanSetTag(StringView key, StringView value)
```
Sets a tag key and value in the active span of the request being
processed by the filte.

Metadata API
------------

Expand Down
6 changes: 6 additions & 0 deletions api/wasm/cpp/proxy_wasm_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct Tuple3Hash {
};

using HeaderStringPairs = std::vector<std::pair<std::string, std::string>>;
using SpanTagPairs = std::vector<std::pair<std::string, std::string>>;

class GrpcCallHandlerBase {
public:
Expand Down Expand Up @@ -785,6 +786,11 @@ inline WasmResult makeHttpCall(StringView uri, const HeaderStringPairs& request_
return result;
}

// Tracing
inline WasmResult activeSpanSetTag(StringView key, StringView value) {
return proxy_set_active_span_tag(key.data(), key.size(), value.data(), value.size());
}

// Low level metrics interface.

inline WasmResult defineMetric(MetricType type, StringView name, uint32_t* metric_id) {
Expand Down
4 changes: 4 additions & 0 deletions api/wasm/cpp/proxy_wasm_externs.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ extern "C" WasmResult proxy_remove_header_map_value(HeaderMapType type, const ch
size_t key_size);
extern "C" WasmResult proxy_get_header_map_size(HeaderMapType type, size_t* size);

// Tracing
extern "C" WasmResult proxy_set_active_span_tag(const char* key_ptr, size_t key_size, const char* value_ptr,
size_t value_size);

// Buffer
extern "C" WasmResult proxy_get_buffer_bytes(BufferType type, uint32_t start, uint32_t length,
const char** ptr, size_t* size);
Expand Down
1 change: 1 addition & 0 deletions api/wasm/cpp/proxy_wasm_intrinsics.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ mergeInto(LibraryManager.library, {
proxy_set_effective_context : function () {},
proxy_done: function () {},
proxy_call_foreign_function: function () {},
proxy_set_active_span_tag: function () {},
});
Binary file modified examples/wasm/envoy_filter_http_wasm_example.wasm
Binary file not shown.
9 changes: 9 additions & 0 deletions source/extensions/common/wasm/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,15 @@ void Context::scriptLog(spdlog::level::level_enum level, absl::string_view messa
// Connection
bool Context::isSsl() { return decoder_callbacks_->connection()->ssl() != nullptr; }

// Tracing
void Context::activeSpanSetTag(absl::string_view key, absl::string_view value) {
if (!decoder_callbacks_) {
return;
}
Tracing::Span& span = decoder_callbacks_->activeSpan();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered a version of this function that uses encoder_callbacks_, maybe as a backup? I ask because I don't know if decoder_callbacks_ is valid in the context of the HTTP encoder. Do you have.an example of this working within the onResponseBody() of a Context subclass?

span.setTag(key, value);
}

//
// Calls into the WASM code.
//
Expand Down
3 changes: 3 additions & 0 deletions source/extensions/common/wasm/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ class Context : public Logger::Loggable<Logger::Id::wasm>,
// Connection
virtual bool isSsl();

// Tracing
virtual void activeSpanSetTag(absl::string_view key, absl::string_view value);

void addAfterVmCallAction(std::function<void()> f);

protected:
Expand Down
14 changes: 14 additions & 0 deletions source/extensions/common/wasm/exports.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <iostream>

#include "extensions/common/wasm/wasm.h"

namespace Envoy {
Expand Down Expand Up @@ -846,6 +848,18 @@ Word log(void* raw_context, Word level, Word address, Word size) {
return wasmResultToWord(WasmResult::Ok);
}

Word set_active_span_tag(void* raw_context, Word key_ptr, Word key_size, Word value_ptr,
Word value_size) {
auto context = WASM_CONTEXT(raw_context);
auto key = context->wasmVm()->getMemory(key_ptr.u64_, key_size.u64_);
auto value = context->wasmVm()->getMemory(value_ptr.u64_, value_size.u64_);
if (!key || !value) {
return wasmResultToWord(WasmResult::InvalidMemoryAccess);
}
context->activeSpanSetTag(key.value(), value.value());
return wasmResultToWord(WasmResult::Ok);
}

} // namespace Exports
} // namespace Wasm
} // namespace Common
Expand Down
2 changes: 2 additions & 0 deletions source/extensions/common/wasm/exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ Word set_effective_context(void* raw_context, Word context_id);
Word done(void* raw_context);
Word call_foreign_function(void* raw_context, Word function_name, Word function_name_size,
Word arguments, Word warguments_size, Word results, Word results_size);
Word set_active_span_tag(void* raw_context, Word key_ptr, Word key_size, Word value_ptr,
Word value_size);

// Runtime environment functions exported from envoy to wasm.

Expand Down
9 changes: 8 additions & 1 deletion source/extensions/common/wasm/null/wasm_api_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ inline WasmResult proxy_set_shared_data(const char* key_ptr, size_t key_size, co
}

// SharedQueue
// Note: Registering the same queue_name will overwrite the old registration while preseving any
// Note: Registering the same queue_name will overwrite the old registration while preserving any
// pending data. Consequently it should typically be followed by a call to
// proxy_dequeue_shared_queue. Returns unique token for the queue.
inline WasmResult proxy_register_shared_queue(const char* queue_name_ptr, size_t queue_name_size,
Expand Down Expand Up @@ -225,6 +225,13 @@ inline WasmResult proxy_grpc_send(uint64_t token, const char* message_ptr, size_
WS(message_size), WS(end_stream)));
}

// Tracing
inline WasmResult proxy_set_active_span_tag(const char* key_ptr, size_t key_size,
const char* value_ptr, size_t value_size) {
return wordToWasmResult(Exports::set_active_span_tag(current_context_, WR(key_ptr), WS(key_size),
WR(value_ptr), WS(value_size)));
}

// Metrics
// Returns a metric_id which can be used to report a metric. On error returns 0.
inline WasmResult proxy_define_metric(MetricType type, const char* name_ptr, size_t name_size,
Expand Down
1 change: 1 addition & 0 deletions source/extensions/common/wasm/wasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ void Wasm::registerCallbacks() {
_REGISTER_PROXY(set_effective_context);
_REGISTER_PROXY(done);
_REGISTER_PROXY(call_foreign_function);
_REGISTER_PROXY(set_active_span_tag);
#undef _REGISTER_PROXY
}

Expand Down
Binary file modified test/extensions/access_loggers/wasm/test_data/logging.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion test/extensions/filters/http/wasm/test_data/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
all: headers_cpp.wasm async_call_cpp.wasm metadata_cpp.wasm grpc_call_cpp.wasm shared_cpp.wasm queue_cpp.wasm root_id_cpp.wasm body_cpp.wasm
all: headers_cpp.wasm async_call_cpp.wasm metadata_cpp.wasm grpc_call_cpp.wasm shared_cpp.wasm queue_cpp.wasm root_id_cpp.wasm body_cpp.wasm tracing_cpp.wasm

include ../../../../../../api/wasm/cpp/Makefile.base_lite
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
DOCKER_SDK=/external_sdk

all: headers_cpp.wasm async_call_cpp.wasm metadata_cpp.wasm grpc_call_cpp.wasm shared_cpp.wasm queue_cpp.wasm http_callout_cpp.wasm grpc_callout_cpp.wasm
all: headers_cpp.wasm async_call_cpp.wasm metadata_cpp.wasm grpc_call_cpp.wasm shared_cpp.wasm queue_cpp.wasm http_callout_cpp.wasm grpc_callout_cpp.wasm tracing_cpp.wasm
chown ${uid}.${gid} *.wasm

include ${DOCKER_SDK}/Makefile.base_lite
Binary file modified test/extensions/filters/http/wasm/test_data/async_call_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/grpc_call_cpp.wasm
Binary file not shown.
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/headers_cpp.wasm
Binary file not shown.
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/metadata_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/queue_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/shared_cpp.wasm
Binary file not shown.
18 changes: 18 additions & 0 deletions test/extensions/filters/http/wasm/test_data/tracing_cpp.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// NOLINT(namespace-envoy)
#include <string>
#include <unordered_map>

#include "proxy_wasm_intrinsics.h"

class ExampleContext : public Context {
public:
explicit ExampleContext(uint32_t id, RootContext* root) : Context(id, root) {}

FilterHeadersStatus onRequestHeaders(uint32_t) override;
};
static RegisterContextFactory register_ExampleContext(CONTEXT_FACTORY(ExampleContext));

FilterHeadersStatus ExampleContext::onRequestHeaders(uint32_t) {
activeSpanSetTag("tag_1", "tag_value_1");
return FilterHeadersStatus::Continue;
}
Binary file not shown.
14 changes: 14 additions & 0 deletions test/extensions/filters/http/wasm/wasm_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "test/mocks/ssl/mocks.h"
#include "test/mocks/stream_info/mocks.h"
#include "test/mocks/thread_local/mocks.h"
#include "test/mocks/tracing/mocks.h"
#include "test/mocks/upstream/mocks.h"
#include "test/test_common/environment.h"
#include "test/test_common/printers.h"
Expand Down Expand Up @@ -149,6 +150,7 @@ class WasmHttpFilterTest : public testing::TestWithParam<std::string> {
NiceMock<Http::MockStreamEncoderFilterCallbacks> encoder_callbacks_;
NiceMock<Envoy::StreamInfo::MockStreamInfo> request_stream_info_;
NiceMock<LocalInfo::MockLocalInfo> local_info_;
NiceMock<Tracing::MockSpan> active_span_;
envoy::config::core::v3::Metadata listener_metadata_;
TestRoot* root_context_ = nullptr;
Config::DataSource::RemoteAsyncDataProviderPtr remote_data_provider_;
Expand Down Expand Up @@ -759,6 +761,18 @@ TEST_P(WasmHttpFilterTest, SharedQueue) {
wasm_->wasm()->queueReady(root_context_->id(), token);
}

// Verifies if the tags have been added correctly.
TEST_P(WasmHttpFilterTest, AddTagToActiveSpans) {
setupConfig(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(
"{{ test_rundir }}/test/extensions/filters/http/wasm/test_data/tracing_cpp.wasm")));
setupFilter();
EXPECT_CALL(decoder_callbacks_, activeSpan).WillRepeatedly(ReturnRef(active_span_));
EXPECT_CALL(active_span_, setTag(Eq("tag_1"), Eq("tag_value_1")));
Http::TestRequestHeaderMapImpl request_headers{{":path", "/"}};
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true));
filter_->onDestroy();
}

// Script using a root_id which is not registered.
TEST_P(WasmHttpFilterTest, RootIdNotRegistered) {
setupConfig(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(
Expand Down
Loading