breaking change. it works better.

This commit is contained in:
2026-01-04 19:28:56 -05:00
parent 6a7c6eb40b
commit df31d60af9
15 changed files with 635 additions and 823 deletions

109
README.md
View File

@@ -1,5 +1,5 @@
# Undead Logging
Logging for stupid idiots like me
Opinionated logging
* Pluggable event listeners
* Per-source hushing, global log type hushing
@@ -39,10 +39,10 @@ log.n("Something happened");
Disable a type of message globally:
```ts
import Logging, { MessageTypeVisibility } from "@proxnet/undead-logging";
import Logging, { LoggingConfiguration } from "@proxnet/undead-logging";
// .. logging source "Main" is in the scope
MessageTypeVisibility.Error = false;
LoggingConfiguration.MessageTypeVisibility.Error = false;
// somewhere else, could be a different script
log.i("I am visible");
@@ -87,6 +87,8 @@ LoggingListeners.offmsg('basic', cb);
## Time display modes
You can display four different formats for time:
* No time display
- Can be useful when running a service that already logs time and date, such as systemd services
* UTC
* Unix time (in milliseconds)
* Local [process] time (in milliseconds, from the `performance` API)
@@ -99,6 +101,8 @@ import { LoggingConfiguration, TimeFormat } from "@proxnet/undead-logging";
LoggingConfiguration.timeFormat = TimeFormat.Local;
// or
LoggingConfiguration.timeFormat = TimeFormat.Utc;
// or even
LoggingConfiguration.timeFormat = TimeFormat.None; // removes the time and date section of the log line entirely
```
## (advanced) Logging timing
@@ -118,10 +122,10 @@ You might also prefer to reset all sources to synchronous logging during app shu
This can help debug issues with how your app closes. (see example below)
## Global resets
Every source is tracked by this module in a `Set`.
Every source is tracked by `LoggingConfiguration` in a `Set`.
You can reset every source's log timing or time format with `LoggingConfiguration.reset(something)`.<br>
The corresponding property will be updated on `LoggingConfiguration`:
You can reset every source's log timing or time format with `LoggingConfiguration.resetX`.<br>
The corresponding property will be updated on all instances of `Logging`:
```ts
import Logging, { LoggingConfiguration, LogTiming } from "@proxnet/undead-logging";
@@ -149,7 +153,98 @@ Deno.addSignalListener('SIGINT', () => {
});
```
## [Benchmarks](./BENCH.md)
## Class/Object Conversion
Any type of object can be given to a logging function. "[object Object]" may not always be desirable.
You can automatically convert any object to a string of any format using a `Conversion<T>`:
```ts
class CustomClass {
foo: string;
bar: number;
constructor(foo: string, bar: number) {
this.foo = foo;
this.bar = bar;
}
}
LoggingConfiguration.addConversion<CustomClass>({
condition: arg => arg instanceof CustomClass,
converter: arg => `CustomClass; foo:${arg.foo}; bar:${arg.bar};`
});
/*
log an instance of `CustomClass`:
2026-01-04T23:56:49.156Z ConvertTest [DEBUG] CustomClass; foo:baz; bar:39;
*/
```
Promises are honored when using them in the `condition` and/or the `converter`.
<br>As such, you can use your own async in the conversion should you ever want to.
Some classes and objects are converted by default, such as `Response` and `Request` standard APIs.
<br>They are demonstrated in `tests/convert.ts`, though they appear as:
```
2026-01-04T23:56:48.965Z Web [INFO] GET http://example.com/?hello=world
key1: value1
key2: value2
2026-01-04T23:56:49.156Z Web [INFO] 200 OK https://example.com/
age: 8217
...
server: cloudflare
vary: Accept-Encoding
```
You can remove these default conversions using `LoggingConfiguration.clearConversions()` before your program starts.
### Converter priority
In semi-rare cases, you may want to prefer using some converters over others,<br>such as converting custom `Error`s rather than the base `Error` class.
You can configure converter *priority* using `Conversion.priority`:
```ts
class CustomError extends Error {
someProperty: string
constructor(someProp: string) {
super("Something went wrong.");
this.someProperty = someProp;
}
}
LoggingConfiguration.clearConversions();
LoggingConfiguration.addConversion<CustomError>({
condition: arg => arg instanceof CustomError,
converter: arg => `CustomError: someProperty:${arg.someProperty}; ${arg.stack || arg.message}`,
priority: -1
});
LoggingConfiguration.addConversion<Error>({
condition: arg => arg instanceof Error,
converter: arg => `${arg.stack || arg.message}`,
priority: 1
});
/*
CustomError at 1, Error at -1:
2026-01-05T00:09:18.176Z PriorityTest [INFO] CustomError: someProperty:'Hello World!'; Error: Something went wrong.
at file:///C:/Users/zombieb/undead-logging/tests/priority.ts:28:7
*/
/*
CustomError at -1, Error at 1:
2026-01-05T00:09:34.040Z PriorityTest [INFO] Error: Something went wrong.
at file:///C:/Users/zombieb/undead-logging/tests/priority.ts:28:7
*/
```
Converters with numbers closer to `Infinity` have a higher priority. As such, you can choose your numerical layout for converter priority.
## Contributing
create an account on gitea.proxnet.dev, fork, then PR