@arcjet/logger
Advanced tools
Comparing version 1.0.0-alpha.13 to 1.0.0-alpha.14
@@ -1,13 +0,18 @@ | ||
export type LogLevel = "DEBUG" | "LOG" | "WARN" | "ERROR"; | ||
export type LogLevel = "debug" | "info" | "warn" | "error"; | ||
export interface LoggerOptions { | ||
level: LogLevel; | ||
} | ||
export declare class Logger { | ||
#private; | ||
constructor(); | ||
constructor(opts: LoggerOptions); | ||
time(label: string): void; | ||
timeEnd(label: string): void; | ||
debug(msg: string, ...details: unknown[]): void; | ||
log(msg: string, ...details: unknown[]): void; | ||
warn(msg: string, ...details: unknown[]): void; | ||
error(msg: string, ...details: unknown[]): void; | ||
debug(msg: string, ...args: unknown[]): void; | ||
debug(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
info(msg: string, ...args: unknown[]): void; | ||
info(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
warn(msg: string, ...args: unknown[]): void; | ||
warn(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
error(msg: string, ...args: unknown[]): void; | ||
error(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
} | ||
declare const logger: Logger; | ||
export default logger; |
109
index.js
@@ -1,38 +0,73 @@ | ||
import { format } from 'util'; | ||
import format from '@arcjet/sprintf'; | ||
// TODO(#180): Implement our own format utility | ||
function getEnvLogLevel() { | ||
const level = process.env["ARCJET_LOG_LEVEL"]; | ||
switch (level) { | ||
case "DEBUG": | ||
case "LOG": | ||
case "WARN": | ||
case "ERROR": | ||
return level; | ||
default: | ||
return undefined; | ||
function bigintReplacer(key, value) { | ||
if (typeof value === "bigint") { | ||
return "[BigInt]"; | ||
} | ||
return value; | ||
} | ||
// TODO: Deduplicate this and sprintf implementation | ||
function tryStringify(o) { | ||
try { | ||
return JSON.stringify(o, bigintReplacer); | ||
} | ||
catch (e) { | ||
return "[Circular]"; | ||
} | ||
} | ||
const PREFIX = "✦Aj"; | ||
function getTimeLabel(label) { | ||
return `✦Aj Latency ${label}`; | ||
return `${PREFIX} LATENCY ${label}`; | ||
} | ||
function getMessage(obj, msg, args) { | ||
// The first argument was the message so juggle the args | ||
if (typeof obj === "string") { | ||
args = [msg, ...args]; | ||
msg = obj; | ||
} | ||
// Prefer a string message over `obj.msg`, as per Pino: | ||
// https://github.com/pinojs/pino/blob/8db130eba0439e61c802448d31eb1998cebfbc98/docs/api.md#message-string | ||
if (typeof msg === "string") { | ||
return format(msg, ...args); | ||
} | ||
if (typeof obj === "object" && | ||
obj !== null && | ||
"msg" in obj && | ||
typeof obj.msg === "string") { | ||
return format(obj.msg, [msg, ...args]); | ||
} | ||
} | ||
function getOutput(obj, msg, args) { | ||
let output = getMessage(obj, msg, args); | ||
if (typeof output !== "string") { | ||
return; | ||
} | ||
if (typeof obj === "object" && obj !== null) { | ||
for (const [key, value] of Object.entries(obj)) { | ||
output += `\n ${key}: ${tryStringify(value)}`; | ||
} | ||
} | ||
return output; | ||
} | ||
class Logger { | ||
#logLevel; | ||
constructor() { | ||
const levelStr = getEnvLogLevel() ?? "WARN"; | ||
switch (levelStr) { | ||
case "DEBUG": | ||
constructor(opts) { | ||
if (typeof opts.level !== "string") { | ||
throw new Error(`Invalid log level`); | ||
} | ||
switch (opts.level) { | ||
case "debug": | ||
this.#logLevel = 0; | ||
break; | ||
case "LOG": | ||
case "info": | ||
this.#logLevel = 1; | ||
break; | ||
case "WARN": | ||
case "warn": | ||
this.#logLevel = 2; | ||
break; | ||
case "ERROR": | ||
case "error": | ||
this.#logLevel = 3; | ||
break; | ||
default: { | ||
throw new Error(`Unknown log level: ${levelStr}`); | ||
throw new Error(`Unknown log level: ${opts.level}`); | ||
} | ||
@@ -51,26 +86,36 @@ } | ||
} | ||
debug(msg, ...details) { | ||
debug(obj, msg, ...args) { | ||
if (this.#logLevel <= 0) { | ||
console.debug("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.debug(`${PREFIX} DEBUG ${output}`); | ||
} | ||
} | ||
} | ||
log(msg, ...details) { | ||
info(obj, msg, ...args) { | ||
if (this.#logLevel <= 1) { | ||
console.log("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.info(`${PREFIX} INFO ${output}`); | ||
} | ||
} | ||
} | ||
warn(msg, ...details) { | ||
warn(obj, msg, ...args) { | ||
if (this.#logLevel <= 2) { | ||
console.warn("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.warn(`${PREFIX} WARN ${output}`); | ||
} | ||
} | ||
} | ||
error(msg, ...details) { | ||
error(obj, msg, ...args) { | ||
if (this.#logLevel <= 3) { | ||
console.error("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.error(`${PREFIX} ERROR ${output}`); | ||
} | ||
} | ||
} | ||
} | ||
// Singleton logger that only accounts for `process.env["ARCJET_LOG_LEVEL"]` at module-load time | ||
const logger = new Logger(); | ||
export { Logger, logger as default }; | ||
export { Logger }; |
135
index.ts
@@ -1,44 +0,93 @@ | ||
// TODO(#180): Implement our own format utility | ||
import { format } from "util"; | ||
import format from "@arcjet/sprintf"; | ||
export type LogLevel = "DEBUG" | "LOG" | "WARN" | "ERROR"; | ||
function bigintReplacer(key: string, value: unknown) { | ||
if (typeof value === "bigint") { | ||
return "[BigInt]"; | ||
} | ||
function getEnvLogLevel(): LogLevel | undefined { | ||
const level = process.env["ARCJET_LOG_LEVEL"]; | ||
switch (level) { | ||
case "DEBUG": | ||
case "LOG": | ||
case "WARN": | ||
case "ERROR": | ||
return level; | ||
default: | ||
return undefined; | ||
return value; | ||
} | ||
// TODO: Deduplicate this and sprintf implementation | ||
function tryStringify(o: unknown) { | ||
try { | ||
return JSON.stringify(o, bigintReplacer); | ||
} catch (e) { | ||
return "[Circular]"; | ||
} | ||
} | ||
export type LogLevel = "debug" | "info" | "warn" | "error"; | ||
export interface LoggerOptions { | ||
level: LogLevel; | ||
} | ||
const PREFIX = "✦Aj"; | ||
function getTimeLabel(label: string) { | ||
return `✦Aj Latency ${label}`; | ||
return `${PREFIX} LATENCY ${label}`; | ||
} | ||
function getMessage(obj: unknown, msg: unknown, args: unknown[]) { | ||
// The first argument was the message so juggle the args | ||
if (typeof obj === "string") { | ||
args = [msg, ...args]; | ||
msg = obj; | ||
} | ||
// Prefer a string message over `obj.msg`, as per Pino: | ||
// https://github.com/pinojs/pino/blob/8db130eba0439e61c802448d31eb1998cebfbc98/docs/api.md#message-string | ||
if (typeof msg === "string") { | ||
return format(msg, ...args); | ||
} | ||
if ( | ||
typeof obj === "object" && | ||
obj !== null && | ||
"msg" in obj && | ||
typeof obj.msg === "string" | ||
) { | ||
return format(obj.msg, [msg, ...args]); | ||
} | ||
} | ||
function getOutput(obj: unknown, msg: unknown, args: unknown[]) { | ||
let output = getMessage(obj, msg, args); | ||
if (typeof output !== "string") { | ||
return; | ||
} | ||
if (typeof obj === "object" && obj !== null) { | ||
for (const [key, value] of Object.entries(obj)) { | ||
output += `\n ${key}: ${tryStringify(value)}`; | ||
} | ||
} | ||
return output; | ||
} | ||
export class Logger { | ||
#logLevel: number; | ||
constructor() { | ||
const levelStr = getEnvLogLevel() ?? "WARN"; | ||
switch (levelStr) { | ||
case "DEBUG": | ||
constructor(opts: LoggerOptions) { | ||
if (typeof opts.level !== "string") { | ||
throw new Error(`Invalid log level`); | ||
} | ||
switch (opts.level) { | ||
case "debug": | ||
this.#logLevel = 0; | ||
break; | ||
case "LOG": | ||
case "info": | ||
this.#logLevel = 1; | ||
break; | ||
case "WARN": | ||
case "warn": | ||
this.#logLevel = 2; | ||
break; | ||
case "ERROR": | ||
case "error": | ||
this.#logLevel = 3; | ||
break; | ||
default: { | ||
const _exhaustiveCheck: never = levelStr; | ||
throw new Error(`Unknown log level: ${levelStr}`); | ||
throw new Error(`Unknown log level: ${opts.level}`); | ||
} | ||
@@ -60,29 +109,45 @@ } | ||
debug(msg: string, ...details: unknown[]) { | ||
debug(msg: string, ...args: unknown[]): void; | ||
debug(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
debug(obj: unknown, msg?: unknown, ...args: unknown[]): void { | ||
if (this.#logLevel <= 0) { | ||
console.debug("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.debug(`${PREFIX} DEBUG ${output}`); | ||
} | ||
} | ||
} | ||
log(msg: string, ...details: unknown[]) { | ||
info(msg: string, ...args: unknown[]): void; | ||
info(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
info(obj: unknown, msg?: unknown, ...args: unknown[]): void { | ||
if (this.#logLevel <= 1) { | ||
console.log("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.info(`${PREFIX} INFO ${output}`); | ||
} | ||
} | ||
} | ||
warn(msg: string, ...details: unknown[]) { | ||
warn(msg: string, ...args: unknown[]): void; | ||
warn(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
warn(obj: unknown, msg?: unknown, ...args: unknown[]): void { | ||
if (this.#logLevel <= 2) { | ||
console.warn("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.warn(`${PREFIX} WARN ${output}`); | ||
} | ||
} | ||
} | ||
error(msg: string, ...details: unknown[]) { | ||
error(msg: string, ...args: unknown[]): void; | ||
error(obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void; | ||
error(obj: unknown, msg?: unknown, ...args: unknown[]): void { | ||
if (this.#logLevel <= 3) { | ||
console.error("✦Aj %s", format(msg, ...details)); | ||
const output = getOutput(obj, msg, args); | ||
if (typeof output !== "undefined") { | ||
console.error(`${PREFIX} ERROR ${output}`); | ||
} | ||
} | ||
} | ||
} | ||
// Singleton logger that only accounts for `process.env["ARCJET_LOG_LEVEL"]` at module-load time | ||
const logger = new Logger(); | ||
export default logger; |
{ | ||
"name": "@arcjet/logger", | ||
"version": "1.0.0-alpha.13", | ||
"description": "Arcjet logging interface which mirrors the console interface but allows log levels", | ||
"version": "1.0.0-alpha.14", | ||
"description": "Arcjet lightweight logger which mirrors the Pino structured logger interface", | ||
"license": "Apache-2.0", | ||
@@ -42,9 +42,11 @@ "homepage": "https://arcjet.com", | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"@arcjet/sprintf": "1.0.0-alpha.14" | ||
}, | ||
"devDependencies": { | ||
"@arcjet/eslint-config": "1.0.0-alpha.13", | ||
"@arcjet/rollup-config": "1.0.0-alpha.13", | ||
"@arcjet/tsconfig": "1.0.0-alpha.13", | ||
"@arcjet/eslint-config": "1.0.0-alpha.14", | ||
"@arcjet/rollup-config": "1.0.0-alpha.14", | ||
"@arcjet/tsconfig": "1.0.0-alpha.14", | ||
"@jest/globals": "29.7.0", | ||
"@rollup/wasm-node": "4.17.2", | ||
"@rollup/wasm-node": "4.18.0", | ||
"@types/node": "18.18.0", | ||
@@ -51,0 +53,0 @@ "jest": "29.7.0", |
<a href="https://arcjet.com" target="_arcjet-home"> | ||
<picture> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://arcjet.com/arcjet-logo-dark-planet-arrival.svg"> | ||
<img src="https://arcjet.com/arcjet-logo-light-planet-arrival.svg" alt="Arcjet Logo" height="144" width="auto"> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://arcjet.com/logo/arcjet-dark-lockup-voyage-horizontal.svg"> | ||
<img src="https://arcjet.com/logo/arcjet-light-lockup-voyage-horizontal.svg" alt="Arcjet Logo" height="128" width="auto"> | ||
</picture> | ||
@@ -19,4 +19,4 @@ </a> | ||
[Arcjet][arcjet] logging interface which mirrors the `console` interface but | ||
allows log levels. | ||
[Arcjet][arcjet] lightweight logger which mirrors the [Pino][pino-api] | ||
structured logger interface. | ||
@@ -51,2 +51,3 @@ ## Installation | ||
[arcjet]: https://arcjet.com | ||
[pino-api]: https://github.com/pinojs/pino/blob/8db130eba0439e61c802448d31eb1998cebfbc98/docs/api.md#logger | ||
[apache-license]: http://www.apache.org/licenses/LICENSE-2.0 |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
22469
266
52
0
1
1
+ Added@arcjet/sprintf@1.0.0-alpha.14(transitive)