Skip to content

Commit

Permalink
An attempt at an http rust wasm logger (#24)
Browse files Browse the repository at this point in the history
* An attempt at an http rust wasm logger, fundamentally not possible right now with the state of rust's opentelemetry ecosystem, js one improved to feasibly be included in the HEAD, probably should make separate repo for it though to keep size small

* Feature fixes

* Wasm fixes

* Small fixes

* Fixing timing test
  • Loading branch information
zakstucke authored Feb 20, 2024
1 parent b62ef35 commit 0733a6d
Show file tree
Hide file tree
Showing 21 changed files with 806 additions and 181 deletions.
7 changes: 5 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ repos:
# Toml formatting,
# same as vscode extension: https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml
# Configure from ./taplo.toml
- repo: https://github.com/ComPWA/mirrors-taplo
rev: v0.8.1
# NOTE: temporary source whilst taplo sort out their internal packaging, should switch to proper in the end, see:
# https://github.com/tamasfe/taplo/pull/549
# https://github.com/tamasfe/taplo/issues/535
- repo: https://github.com/redeboer/taplo-pre-commit
rev: v0.9.1rc1
hooks:
- id: taplo
args: ["format", "--config", "./taplo.toml"]
Expand Down
27 changes: 14 additions & 13 deletions .zetch.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions js/bitbazaar/log/log.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,22 @@ describe("Logging/Tracing", () => {
service_version: "1.0.0",
},
});

LOG.debug("DEBUG");
LOG.info("INFO");
LOG.warn("WARN");
LOG.error("ERROR");
expect(logs).toEqual(expected_enabled);

// Empty:
logs.length = 0;

// All console logs should have been overridden to also use the global logger:
console.debug("DEBUG");
console.info("INFO");
console.warn("WARN");
console.error("ERROR");
expect(logs).toEqual(expected_enabled);
},
);
it("Logs: oltp", async () => {
Expand Down
33 changes: 29 additions & 4 deletions js/bitbazaar/log/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ interface OltpArgs {
service_version: string; // E.g. "1.0.0"
}

type ConsoleFns = Record<
"log" | "debug" | "info" | "warn" | "error",
(message: string, ...optionalParams: any[]) => void
>;

class GlobalLog {
loggerProvider: LoggerProvider;
logger: Logger;
Expand All @@ -55,6 +60,9 @@ class GlobalLog {
console: ConsoleArgs | null;
oltp: OltpArgs;

/// We override global console functions to do filtering and emit to oltp, need to keep access to the inner ones:
orig_console_fns: ConsoleFns;

/**
* Get a new Meter instance to record metrics with.
*
Expand Down Expand Up @@ -131,22 +139,22 @@ class GlobalLog {
switch (this.console.level_from) {
case "DEBUG": {
emit = true;
emitter = console.debug;
emitter = this.orig_console_fns.debug;
break;
}
case "INFO": {
emit = severityText !== "DEBUG";
emitter = console.info;
emitter = this.orig_console_fns.info;
break;
}
case "WARN": {
emit = severityText === "WARN" || severityText === "ERROR";
emitter = console.warn;
emitter = this.orig_console_fns.warn;
break;
}
case "ERROR": {
emit = severityText === "ERROR";
emitter = console.error;
emitter = this.orig_console_fns.error;
break;
}
}
Expand Down Expand Up @@ -188,6 +196,21 @@ class GlobalLog {
}
}

_set_console_fns() {
this.orig_console_fns = {
log: console.log,
debug: console.debug,
info: console.info,
warn: console.warn,
error: console.error,
};
console.log = (msg, ...attrs) => this.info(msg, ...attrs);
console.debug = (msg, ...attrs) => this.debug(msg, ...attrs);
console.info = (msg, ...attrs) => this.info(msg, ...attrs);
console.warn = (msg, ...attrs) => this.warn(msg, ...attrs);
console.error = (msg, ...attrs) => this.error(msg, ...attrs);
}

/** Create the global logger, must setup oltp (http), console can be optionally setup and will just print logs. */
constructor({
otlp,
Expand All @@ -198,6 +221,8 @@ class GlobalLog {
}) {
this.console = console ? console : null;
this.oltp = otlp;
// Store original console fns and override with those in this global logger:
this._set_console_fns();

const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: otlp.service_name,
Expand Down
2 changes: 1 addition & 1 deletion js/bunfig.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ telemetry = false
preload = ["./tests/happydom.ts", "./tests/setupTests.ts"]
coverage = true
coverageSkipTestFiles = true
coverageThreshold = 0.95
coverageThreshold = 0.94
7 changes: 6 additions & 1 deletion opencollector.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ receivers:
protocols:
grpc:
endpoint: localhost:4317
http:
endpoint: localhost:4318
cors:
allowed_origins:
- "*"

processors:
# Prevent memory usage from exceeding 40% of the total available RAM,
Expand All @@ -27,7 +32,7 @@ exporters:
stream-name: default
# Writes all opentelemetry logs, traces, metrics to a file, useful for testing:
file/debug_file_writing:
path: /home/runner/work/bitbazaar/bitbazaar/logs/otlp_telemetry_out.log
path: /Users/zak/z/code/bitbazaar/logs/otlp_telemetry_out.log
rotation:
max_megabytes: 10
max_days: 3
Expand Down
5 changes: 5 additions & 0 deletions opencollector.yaml.zetch
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ receivers:
protocols:
grpc:
endpoint: localhost:4317
http:
endpoint: localhost:4318
cors:
allowed_origins:
- "*"

processors:
# Prevent memory usage from exceeding 40% of the total available RAM,
Expand Down
1 change: 0 additions & 1 deletion py_rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion py_rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ path = "src/lib.rs"

# Add your dependencies here
[dependencies]
colored = '2'
tracing = "0.1"
error-stack = "0.4"
bitbazaar = { version = '0.0.31', features = ["opentelemetry"] }
Expand Down
3 changes: 1 addition & 2 deletions py_rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#![warn(clippy::disallowed_types)]

use colored::Colorize;
use pyo3::prelude::*;

mod utils;

#[pyfunction]
pub fn hello() -> String {
"Hello, World!".cyan().to_string()
"Hello, World!".to_string()
}

/// A Python module implemented in Rust. The name of this function must match
Expand Down
120 changes: 120 additions & 0 deletions rust/.config/nextest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
[test-groups]
serial = { max-threads = 1 }

# A lot of the log tests use static variables or read from files for tests, causing conflicts if run in parallel:
[[profile.default.overrides]]
filter = 'test(log::)'
test-group = 'serial'

# <--- DEFAULTS --->

[store]
# The directory under the workspace root at which nextest-related files are
# written. Profile-specific storage is currently written to dir/<profile-name>.
dir = "target/nextest"

# This section defines the default nextest profile. Custom profiles are layered
# on top of the default profile.
[profile.default]
# "retries" defines the number of times a test should be retried. If set to a
# non-zero value, tests that succeed on a subsequent attempt will be marked as
# flaky. Can be overridden through the `--retries` option.
# Examples
# * retries = 3
# * retries = { backoff = "fixed", count = 2, delay = "1s" }
# * retries = { backoff = "exponential", count = 10, delay = "1s", jitter = true, max-delay = "10s" }
retries = 0

# The number of threads to run tests with. Supported values are either an integer or
# the string "num-cpus". Can be overridden through the `--test-threads` option.
test-threads = "num-cpus"

# The number of threads required for each test. This is generally used in overrides to
# mark certain tests as heavier than others. However, it can also be set as a global parameter.
threads-required = 1

# Show these test statuses in the output.
#
# The possible values this can take are:
# * none: no output
# * fail: show failed (including exec-failed) tests
# * retry: show flaky and retried tests
# * slow: show slow tests
# * pass: show passed tests
# * skip: show skipped tests (most useful for CI)
# * all: all of the above
#
# Each value includes all the values above it; for example, "slow" includes
# failed and retried tests.
#
# Can be overridden through the `--status-level` flag.
status-level = "pass"

# Similar to status-level, show these test statuses at the end of the run.
final-status-level = "flaky"

# "failure-output" defines when standard output and standard error for failing tests are produced.
# Accepted values are
# * "immediate": output failures as soon as they happen
# * "final": output failures at the end of the test run
# * "immediate-final": output failures as soon as they happen and at the end of
# the test run; combination of "immediate" and "final"
# * "never": don't output failures at all
#
# For large test suites and CI it is generally useful to use "immediate-final".
#
# Can be overridden through the `--failure-output` option.
failure-output = "immediate"

# "success-output" controls production of standard output and standard error on success. This should
# generally be set to "never".
success-output = "never"

# Cancel the test run on the first failure. For CI runs, consider setting this
# to false.
fail-fast = true

# Treat a test that takes longer than the configured 'period' as slow, and print a message.
# See <https://nexte.st/book/slow-tests> for more information.
#
# Optional: specify the parameter 'terminate-after' with a non-zero integer,
# which will cause slow tests to be terminated after the specified number of
# periods have passed.
# Example: slow-timeout = { period = "60s", terminate-after = 2 }
slow-timeout = { period = "60s" }

# Treat a test as leaky if after the process is shut down, standard output and standard error
# aren't closed within this duration.
#
# This usually happens in case of a test that creates a child process and lets it inherit those
# handles, but doesn't clean the child process up (especially when it fails).
#
# See <https://nexte.st/book/leaky-tests> for more information.
leak-timeout = "100ms"

[profile.default.junit]
# Output a JUnit report into the given file inside 'store.dir/<profile-name>'.
# If unspecified, JUnit is not written out.

# path = "junit.xml"

# The name of the top-level "report" element in JUnit report. If aggregating
# reports across different test runs, it may be useful to provide separate names
# for each report.
report-name = "nextest-run"

# Whether standard output and standard error for passing tests should be stored in the JUnit report.
# Output is stored in the <system-out> and <system-err> elements of the <testcase> element.
store-success-output = false

# Whether standard output and standard error for failing tests should be stored in the JUnit report.
# Output is stored in the <system-out> and <system-err> elements of the <testcase> element.
#
# Note that if a description can be extracted from the output, it is always stored in the
# <description> element.
store-failure-output = true

# This profile is activated if MIRI_SYSROOT is set.
[profile.default-miri]
# Miri tests take up a lot of memory, so only run 1 test at a time by default.
test-threads = 1
Loading

0 comments on commit 0733a6d

Please sign in to comment.