implement LogTiming.Microtask, better test timings, breaking options API

This commit is contained in:
2025-07-19 19:47:07 -04:00
parent 5db910ca14
commit 6a7c6eb40b
6 changed files with 82 additions and 48 deletions

View File

@@ -145,14 +145,11 @@ const log = new Logging("Main");
Deno.addSignalListener('SIGINT', () => { Deno.addSignalListener('SIGINT', () => {
LoggingConfiguration.resetLogTiming = LogTiming.Sync; LoggingConfiguration.resetLogTiming = LogTiming.Sync;
// shut down I/O here
}); });
``` ```
See [`tests/shutdown.ts`.](./tests/shutdown.ts)
## [Benchmarks](./BENCH.md) ## [Benchmarks](./BENCH.md)
## Contributing ## Contributing
Are you crazy? This ol' thing is just.. "meh" at most. You're sure? create an account on gitea.proxnet.dev, fork, then PR
... anyway, create an account on gitea.proxnet.dev, fork, then PR.

View File

@@ -4,7 +4,7 @@
"cpu": "unknown", "cpu": "unknown",
"benches": [ "benches": [
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-sync", "group": "timing-sync",
"name": "1 Log", "name": "1 Log",
"baseline": false, "baseline": false,
@@ -26,7 +26,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-sync", "group": "timing-sync",
"name": "100 Logs", "name": "100 Logs",
"baseline": false, "baseline": false,
@@ -48,7 +48,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-sync", "group": "timing-sync",
"name": "1k Logs", "name": "1k Logs",
"baseline": false, "baseline": false,
@@ -70,7 +70,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-sync", "group": "timing-sync",
"name": "10k Logs", "name": "10k Logs",
"baseline": false, "baseline": false,
@@ -92,7 +92,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-sync", "group": "timing-sync",
"name": "100k Logs", "name": "100k Logs",
"baseline": false, "baseline": false,
@@ -114,7 +114,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-deferred", "group": "timing-deferred",
"name": "1 Log", "name": "1 Log",
"baseline": false, "baseline": false,
@@ -136,7 +136,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-deferred", "group": "timing-deferred",
"name": "100 Logs", "name": "100 Logs",
"baseline": false, "baseline": false,
@@ -158,7 +158,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-deferred", "group": "timing-deferred",
"name": "1k Logs", "name": "1k Logs",
"baseline": false, "baseline": false,
@@ -180,7 +180,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-deferred", "group": "timing-deferred",
"name": "10k Logs", "name": "10k Logs",
"baseline": false, "baseline": false,
@@ -202,7 +202,7 @@
] ]
}, },
{ {
"origin": "file:///C:/Users/Keagan/undead-logging/benchmark/deno.ts", "origin": "file:///path/to/undead-logging/benchmark/deno.ts",
"group": "timing-deferred", "group": "timing-deferred",
"name": "100k Logs", "name": "100k Logs",
"baseline": false, "baseline": false,

View File

@@ -2,7 +2,7 @@
"tasks": { "tasks": {
"test-conversion": "deno run -A tests/convert.ts", "test-conversion": "deno run -A tests/convert.ts",
"test-global": "deno run -A tests/global.ts", "test-global": "deno run -A tests/global.ts",
"test-shutdown": "deno run -A tests/shutdown.ts", "test-timing": "deno run -A tests/timing.ts",
"bench": "deno bench -A" "bench": "deno bench -A"
}, },
"imports": { "imports": {
@@ -10,7 +10,7 @@
"chalk": "npm:chalk@^5.3.0" "chalk": "npm:chalk@^5.3.0"
}, },
"exports": "./mod.ts", "exports": "./mod.ts",
"version": "1.4.1", "version": "1.5.0",
"name": "@proxnet/undead-logging", "name": "@proxnet/undead-logging",
"license": "MIT", "license": "MIT",
"bench": { "bench": {

58
mod.ts
View File

@@ -11,6 +11,14 @@ interface UnknownConversion<T> {
converter: (arg: T) => string; converter: (arg: T) => string;
} }
/** How would you like your logs served? */
interface LoggingOptions {
logTiming?: LogTiming,
timeFormat?: TimeFormat,
bright?: boolean,
silent?: boolean
}
/** Control all log sources from this module */ /** Control all log sources from this module */
const sources: Set<Logging> = new Set(); const sources: Set<Logging> = new Set();
@@ -45,12 +53,16 @@ class Logging {
* @param silent Set to false to log a message when the logger instantiates. May be useful when debugging. * @param silent Set to false to log a message when the logger instantiates. May be useful when debugging.
* @returns A source for logging messages to the console (stdout). Functions for info, warnings, errors, debug statements, and network events are provided and have shorthands. * @returns A source for logging messages to the console (stdout). Functions for info, warnings, errors, debug statements, and network events are provided and have shorthands.
*/ */
constructor(source: string, silent?: boolean, bright?: boolean) { constructor(source: string, options?: LoggingOptions) {
this.visible = true; this.visible = true;
this.source = source; this.source = source;
if (typeof bright == 'boolean') this.bright = bright;
if (options) {
if (typeof silent == 'boolean' && !silent) this.info(`Instantiated logging for ${this.source}`); if (options.bright) this.bright = options.bright;
if (typeof options.silent == 'boolean' && !options.silent) this.info(`Instantiated logging for ${this.source}`);
if (options.logTiming) this.logTiming = options.logTiming;
if (options.timeFormat) this.timeFormat = options.timeFormat;
}
sources.add(this); sources.add(this);
} }
@@ -178,8 +190,23 @@ class Logging {
} }
} }
if (this.logTiming == LogTiming.Sync) func(); switch (this.logTiming) {
else setImmediate(func); case LogTiming.Sync:
func();
break;
case LogTiming.Deferred:
setImmediate(func);
break;
case LogTiming.Microtask:
if (typeof queueMicrotask == 'function')
queueMicrotask(func);
else
setTimeout(func, 0); // fallback
break;
default:
func();
break;
}
} }
/** /**
@@ -316,7 +343,8 @@ const LoggingListeners: ListenersBase = new ListenersBase();
*/ */
enum LogTiming { enum LogTiming {
Sync, Sync,
Deferred Deferred,
Microtask
} }
/** /**
* Specify the format that loggers use to display time * Specify the format that loggers use to display time
@@ -330,18 +358,18 @@ enum TimeFormat {
class LoggingConfigurationBase { class LoggingConfigurationBase {
#timing: LogTiming = LogTiming.Sync; #logTiming: LogTiming = LogTiming.Sync;
#timeType: TimeFormat = TimeFormat.Utc; #timeFormat: TimeFormat = TimeFormat.Utc;
get timeFormat(): TimeFormat { return this.#timeType } get timeFormat(): TimeFormat { return this.#timeFormat }
set timeFormat(data: TimeFormat) { this.#timeType = data } set timeFormat(data: TimeFormat) { this.#timeFormat = data }
get logTiming(): LogTiming { return this.#timing; } get logTiming(): LogTiming { return this.#logTiming; }
set logTiming(data: LogTiming) { this.#timing = data } set logTiming(data: LogTiming) { this.#logTiming = data }
set resetTimeFormat(data: TimeFormat) { for (const source of sources.values()) source.timeFormat = data; this.#timeType = data; } set resetTimeFormat(data: TimeFormat) { for (const source of sources.values()) source.timeFormat = data; this.#timeFormat = data; }
set resetLogTiming(data: LogTiming) { for (const source of sources.values()) source.logTiming = data; this.#timing = data; } set resetLogTiming(data: LogTiming) { for (const source of sources.values()) source.logTiming = data; this.#logTiming = data; }
} }
/** /**

View File

@@ -1,16 +0,0 @@
import Logging, { LoggingConfiguration, LogTiming } from "@proxnet/undead-logging";
//LoggingConfiguration.logTiming = LogTiming.Deferred;
const log = new Logging("Main");
log.i(`Deferred! - LogTiming.${LogTiming[log.logTiming]}`);
const timeout = setTimeout(() => { log.d(`Interval!`) }, 2000);
Deno.addSignalListener('SIGINT', () => {
clearTimeout(timeout);
LoggingConfiguration.resetLogTiming = LogTiming.Sync;
log.i(`Sync! - LogTiming.${LogTiming[LoggingConfiguration.logTiming]}`);
});

25
tests/timing.ts Normal file
View File

@@ -0,0 +1,25 @@
import Logging, {
LoggingConfiguration,
LogTiming,
} from "../mod.ts";
LoggingConfiguration.logTiming = LogTiming.Microtask;
// high-priority logs
const log = new Logging("HTTP", { silent: false });
Deno.serve({ port: 8080, onListen: addr => {
log.n(`Listen information: ${JSON.stringify(addr)}`);
} }, async (req: Request) => {
const url = new URL(req.url);
if (url.pathname.includes('favicon.ico')) return new Response("Not Found", { status: 404 });
log.i("Received request:", url.pathname);
log.d("I/O start");
const res = await fetch("https://httpbin.org/delay/1");
log.d("I/O end");
return new Response(JSON.stringify(await res.json()), { status: 200 });
});