Skip to content

Commit

Permalink
Add implementation for new ABI proxy_log_destination
Browse files Browse the repository at this point in the history
Signed-off-by: Vikas Choudhary <[email protected]>
  • Loading branch information
vikaschoudhary16 committed Mar 27, 2023
1 parent 609960c commit 4c28647
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 22 deletions.
26 changes: 14 additions & 12 deletions include/proxy-wasm/exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ namespace exports {
Word get_configuration(Word value_ptr_ptr, Word value_size_ptr);
Word get_status(Word code_ptr, Word value_ptr_ptr, Word value_size_ptr);
Word log(Word level, Word address, Word size);
Word log_destination(Word dest, Word dest_size, Word level, Word address, Word size);
Word get_log_level(Word result_level_uint32_ptr);
Word get_property(Word path_ptr, Word path_size, Word value_ptr_ptr, Word value_size_ptr);
Word set_property(Word key_ptr, Word key_size, Word value_ptr, Word value_size);
Expand Down Expand Up @@ -152,18 +153,19 @@ void emscripten_notify_memory_growth(Word);
// Support for embedders, not exported to Wasm.

#define FOR_ALL_HOST_FUNCTIONS(_f) \
_f(log) _f(get_status) _f(set_property) _f(get_property) _f(send_local_response) \
_f(get_shared_data) _f(set_shared_data) _f(register_shared_queue) _f(resolve_shared_queue) \
_f(dequeue_shared_queue) _f(enqueue_shared_queue) _f(get_header_map_value) \
_f(add_header_map_value) _f(replace_header_map_value) _f(remove_header_map_value) \
_f(get_header_map_pairs) _f(set_header_map_pairs) _f(get_header_map_size) \
_f(get_buffer_status) _f(get_buffer_bytes) _f(set_buffer_bytes) \
_f(http_call) _f(grpc_call) _f(grpc_stream) _f(grpc_close) \
_f(grpc_cancel) _f(grpc_send) _f(set_tick_period_milliseconds) \
_f(get_current_time_nanoseconds) _f(define_metric) \
_f(increment_metric) _f(record_metric) _f(get_metric) \
_f(set_effective_context) _f(done) \
_f(call_foreign_function)
_f(log) _f(log_destination) _f(get_status) _f(set_property) _f(get_property) \
_f(send_local_response) _f(get_shared_data) _f(set_shared_data) _f(register_shared_queue) \
_f(resolve_shared_queue) _f(dequeue_shared_queue) _f(enqueue_shared_queue) \
_f(get_header_map_value) _f(add_header_map_value) _f(replace_header_map_value) \
_f(remove_header_map_value) _f(get_header_map_pairs) _f(set_header_map_pairs) \
_f(get_header_map_size) _f(get_buffer_status) _f(get_buffer_bytes) \
_f(set_buffer_bytes) _f(http_call) _f(grpc_call) _f(grpc_stream) \
_f(grpc_close) _f(grpc_cancel) _f(grpc_send) \
_f(set_tick_period_milliseconds) \
_f(get_current_time_nanoseconds) _f(define_metric) \
_f(increment_metric) _f(record_metric) _f(get_metric) \
_f(set_effective_context) _f(done) \
_f(call_foreign_function)

#define FOR_ALL_HOST_FUNCTIONS_ABI_SPECIFIC(_f) \
_f(get_configuration) _f(continue_request) _f(continue_response) _f(clear_route_cache) \
Expand Down
8 changes: 6 additions & 2 deletions include/proxy-wasm/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
WasmBase(std::unique_ptr<WasmVm> wasm_vm, std::string_view vm_id,
std::string_view vm_configuration, std::string_view vm_key,
std::unordered_map<std::string, std::string> envs,
std::unordered_map<std::string, std::string> log_dest,
AllowedCapabilitiesMap allowed_capabilities);
WasmBase(const std::shared_ptr<WasmHandleBase> &base_wasm_handle, const WasmVmFactory &factory);
virtual ~WasmBase();
Expand Down Expand Up @@ -136,6 +137,9 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
AbiVersion abiVersion() const { return abi_version_; }

const std::unordered_map<std::string, std::string> &envs() { return envs_; }
const std::unordered_map<std::string, std::string> &log_destinations() {
return log_destinations_;
}

// Called to raise the flag which indicates that the context should stop iteration regardless of
// returned filter status from Proxy-Wasm extensions. For example, we ignore
Expand Down Expand Up @@ -222,7 +226,7 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
std::unique_ptr<ShutdownHandle> shutdown_handle_;
std::unordered_map<std::string, std::string>
envs_; // environment variables passed through wasi.environ_get

std::unordered_map<std::string, std::string> log_destinations_;
WasmCallVoid<0> _initialize_; /* WASI reactor (Emscripten v1.39.17+, Rust nightly) */
WasmCallVoid<0> _start_; /* WASI command (Emscripten v1.39.0+, TinyGo) */

Expand Down Expand Up @@ -394,7 +398,7 @@ inline void *WasmBase::allocMemory(uint64_t size, uint64_t *address) {
}
wasm_vm_->setRestrictedCallback(
true, {// logging (Proxy-Wasm)
"env.proxy_log",
"env.proxy_log", "env.proxy_log_destination",
// logging (stdout/stderr)
"wasi_unstable.fd_write", "wasi_snapshot_preview1.fd_write",
// time
Expand Down
37 changes: 37 additions & 0 deletions src/exports.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include <openssl/rand.h>

#include <fstream>
#include <iostream>
#include <utility>

namespace proxy_wasm {
Expand Down Expand Up @@ -916,6 +918,41 @@ Word log(Word level, Word address, Word size) {
return context->log(level, message.value());
}

Word log_destination(Word destination, Word dest_size, Word level, Word address, Word size) {
if (level > static_cast<uint64_t>(LogLevel::Max)) {
return WasmResult::BadArgument;
}
auto *context = contextOrEffectiveContext();
const auto &log_destinations = context->wasm()->log_destinations();

auto message = context->wasmVm()->getMemory(address, size);
if (!message) {
return WasmResult::InvalidMemoryAccess;
}
auto dest = context->wasmVm()->getMemory(destination, dest_size);
if (!dest) {
return WasmResult::InvalidMemoryAccess;
}
context->log(level, dest.value());
// iterate over log_destinations map to check if dest
// destination requested by plugin exists
for (const auto &e : log_destinations) {
if (e.first == dest.value()) {
// write message to the file which is the value of the key if it exists
std::ofstream log_file;
log_file.open(e.second, std::ios::out | std::ios_base::app);
if (!log_file) {
return WasmResult::InvalidMemoryAccess;
}
log_file << message.value() << std::endl;
log_file.close();
return WasmResult::Ok;
}
}
// As a fallback, write to the default log destination.
return context->log(level, message.value());
}

Word get_log_level(Word result_level_uint32_ptr) {
auto *context = contextOrEffectiveContext();
uint32_t level = context->getLogLevel();
Expand Down
7 changes: 5 additions & 2 deletions src/wasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ WasmBase::WasmBase(const std::shared_ptr<WasmHandleBase> &base_wasm_handle,
vm_id_(base_wasm_handle->wasm()->vm_id_), vm_key_(base_wasm_handle->wasm()->vm_key_),
started_from_(base_wasm_handle->wasm()->wasm_vm()->cloneable()),
envs_(base_wasm_handle->wasm()->envs()),
log_destinations_(base_wasm_handle->wasm()->log_destinations()),
allowed_capabilities_(base_wasm_handle->wasm()->allowed_capabilities_),
base_wasm_handle_(base_wasm_handle) {
if (started_from_ != Cloneable::NotCloneable) {
Expand All @@ -207,9 +208,11 @@ WasmBase::WasmBase(const std::shared_ptr<WasmHandleBase> &base_wasm_handle,
WasmBase::WasmBase(std::unique_ptr<WasmVm> wasm_vm, std::string_view vm_id,
std::string_view vm_configuration, std::string_view vm_key,
std::unordered_map<std::string, std::string> envs,
std::unordered_map<std::string, std::string> log_dest,
AllowedCapabilitiesMap allowed_capabilities)
: vm_id_(std::string(vm_id)), vm_key_(std::string(vm_key)), wasm_vm_(std::move(wasm_vm)),
envs_(std::move(envs)), allowed_capabilities_(std::move(allowed_capabilities)),
envs_(std::move(envs)), log_destinations_(std::move(log_dest)),
allowed_capabilities_(std::move(allowed_capabilities)),
vm_configuration_(std::string(vm_configuration)), vm_id_handle_(getVmIdHandle(vm_id)) {
if (!wasm_vm_) {
failed_ = FailState::UnableToCreateVm;
Expand Down Expand Up @@ -358,7 +361,7 @@ void WasmBase::startVm(ContextBase *root_context) {
// wasi_snapshot_preview1.clock_time_get
wasm_vm_->setRestrictedCallback(
true, {// logging (Proxy-Wasm)
"env.proxy_log",
"env.proxy_log", "env.proxy_log_destination",
// logging (stdout/stderr)
"wasi_unstable.fd_write", "wasi_snapshot_preview1.fd_write",
// args
Expand Down
2 changes: 1 addition & 1 deletion test/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class TestWasm : public WasmBase {
TestWasm(std::unique_ptr<WasmVm> wasm_vm, std::unordered_map<std::string, std::string> envs = {},
std::string_view vm_id = "", std::string_view vm_configuration = "",
std::string_view vm_key = "")
: WasmBase(std::move(wasm_vm), vm_id, vm_configuration, vm_key, std::move(envs), {}) {}
: WasmBase(std::move(wasm_vm), vm_id, vm_configuration, vm_key, std::move(envs), {}, {}) {}

TestWasm(const std::shared_ptr<WasmHandleBase> &base_wasm_handle, const WasmVmFactory &factory)
: WasmBase(base_wasm_handle, factory) {}
Expand Down
9 changes: 4 additions & 5 deletions test/wasm_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "include/proxy-wasm/wasm.h"

#include <iostream>
#include <unordered_set>

#include "gtest/gtest.h"
Expand Down Expand Up @@ -43,9 +44,9 @@ TEST_P(TestVm, GetOrCreateThreadLocalWasmFailCallbacks) {
// Define callbacks.
WasmHandleFactory wasm_handle_factory =
[this, vm_id, vm_config](std::string_view vm_key) -> std::shared_ptr<WasmHandleBase> {
auto base_wasm = std::make_shared<WasmBase>(newVm(), vm_id, vm_config, vm_key,
std::unordered_map<std::string, std::string>{},
AllowedCapabilitiesMap{});
auto base_wasm = std::make_shared<WasmBase>(
newVm(), vm_id, vm_config, vm_key, std::unordered_map<std::string, std::string>{},
std::unordered_map<std::string, std::string>{}, AllowedCapabilitiesMap{});
return std::make_shared<WasmHandleBase>(base_wasm);
};

Expand Down Expand Up @@ -171,7 +172,6 @@ TEST_P(TestVm, AlwaysApplyCanary) {
// For each create Wasm, canary should be done.
EXPECT_EQ(canary_count, 1);

std::unordered_set<std::shared_ptr<WasmHandleBase>> reference_holder;

for (const auto &root_id : root_ids) {
for (const auto &vm_id : vm_ids) {
Expand Down Expand Up @@ -209,7 +209,6 @@ TEST_P(TestVm, AlwaysApplyCanary) {
// Keep the reference of wasm_handle_comp in order to utilize the WasmHandleBase
// cache of createWasm. If we don't keep the reference, WasmHandleBase and VM will be
// destroyed for each iteration.
reference_holder.insert(wasm_handle_comp);

EXPECT_TRUE(TestContext::isGlobalLogged("onConfigure: " + root_id));

Expand Down

0 comments on commit 4c28647

Please sign in to comment.