@logtail/core
Advanced tools
Comparing version 0.4.16 to 0.4.17
@@ -55,2 +55,3 @@ import { ILogLevel, ILogtailLog, ILogtailOptions, Context, Middleware, Sync } from "@logtail/types"; | ||
log<TContext extends Context>(message: Message, level?: ILogLevel, context?: TContext): Promise<ILogtailLog & TContext>; | ||
private serialize; | ||
/** | ||
@@ -57,0 +58,0 @@ * |
@@ -124,2 +124,11 @@ "use strict"; | ||
async log(message, level = types_1.LogLevel.Info, context = {}) { | ||
// Wrap context in an object, if it's not already | ||
if (typeof context !== "object") { | ||
const wrappedContext = { extra: context }; | ||
context = wrappedContext; | ||
} | ||
if (context instanceof Error) { | ||
const wrappedContext = { error: context }; | ||
context = wrappedContext; | ||
} | ||
if (this._options.sendLogsToConsoleOutput) { | ||
@@ -151,17 +160,7 @@ switch (level) { | ||
// Start building the log message | ||
let log = Object.assign({ | ||
let log = Object.assign(Object.assign({ | ||
// Implicit date timestamp | ||
dt: new Date(), | ||
// Explicit level | ||
level }, context); | ||
// Determine the type of message... | ||
// Is this an error? | ||
if (message instanceof Error) { | ||
log = Object.assign(Object.assign({}, log), (0, serialize_error_1.serializeError)(message)); | ||
} | ||
else { | ||
log = Object.assign(Object.assign({}, log), { | ||
// Add string message | ||
message }); | ||
} | ||
level }, context), (message instanceof Error ? (0, serialize_error_1.serializeError)(message) : { message })); | ||
let transformedLog = log; | ||
@@ -176,2 +175,4 @@ for (const middleware of this._middleware) { | ||
} | ||
// Manually serialize the log data | ||
transformedLog = this.serialize(transformedLog, this._options.contextObjectMaxDepth); | ||
if (!this._options.sendLogsToBetterStack) { | ||
@@ -204,2 +205,59 @@ // Return the resulting log before sending it | ||
} | ||
serialize(value, maxDepth, visitedObjects = new WeakSet()) { | ||
if (value === null || | ||
typeof value === "boolean" || | ||
typeof value === "number" || | ||
typeof value === "string") { | ||
return value; | ||
} | ||
else if (value instanceof Date) { | ||
// Date instances can be invalid & toISOString() will fail | ||
if (isNaN(value.getTime())) { | ||
return value.toString(); | ||
} | ||
return value.toISOString(); | ||
} | ||
else if (value instanceof Error) { | ||
return (0, serialize_error_1.serializeError)(value); | ||
} | ||
else if ((typeof value === "object" || Array.isArray(value)) && | ||
(maxDepth < 1 || visitedObjects.has(value))) { | ||
if (visitedObjects.has(value)) { | ||
if (this._options.contextObjectCircularRefWarn) { | ||
console.warn(`[Logtail] Found a circular reference when serializing logs. Please do not use circular references in your logs.`); | ||
} | ||
return "<omitted circular reference>"; | ||
} | ||
if (this._options.contextObjectMaxDepthWarn) { | ||
console.warn(`[Logtail] Max depth of ${this._options.contextObjectMaxDepth} reached when serializing logs. Please do not use excessive object depth in your logs.`); | ||
} | ||
return `<omitted context beyond configured max depth: ${this._options.contextObjectMaxDepth}>`; | ||
} | ||
else if (Array.isArray(value)) { | ||
visitedObjects.add(value); | ||
const serializedArray = value.map(item => this.serialize(item, maxDepth - 1, visitedObjects)); | ||
visitedObjects.delete(value); | ||
return serializedArray; | ||
} | ||
else if (typeof value === "object") { | ||
const serializedObject = {}; | ||
visitedObjects.add(value); | ||
Object.entries(value).forEach(item => { | ||
const key = item[0]; | ||
const value = item[1]; | ||
const serializedValue = this.serialize(value, maxDepth - 1, visitedObjects); | ||
if (serializedValue !== undefined) { | ||
serializedObject[key] = serializedValue; | ||
} | ||
}); | ||
visitedObjects.delete(value); | ||
return serializedObject; | ||
} | ||
else if (typeof value === "undefined") { | ||
return undefined; | ||
} | ||
else { | ||
return `<omitted unserializable ${typeof value}>`; | ||
} | ||
} | ||
/** | ||
@@ -206,0 +264,0 @@ * |
@@ -55,2 +55,3 @@ import { ILogLevel, ILogtailLog, ILogtailOptions, Context, Middleware, Sync } from "@logtail/types"; | ||
log<TContext extends Context>(message: Message, level?: ILogLevel, context?: TContext): Promise<ILogtailLog & TContext>; | ||
private serialize; | ||
/** | ||
@@ -57,0 +58,0 @@ * |
@@ -122,2 +122,11 @@ import { LogLevel, } from "@logtail/types"; | ||
async log(message, level = LogLevel.Info, context = {}) { | ||
// Wrap context in an object, if it's not already | ||
if (typeof context !== "object") { | ||
const wrappedContext = { extra: context }; | ||
context = wrappedContext; | ||
} | ||
if (context instanceof Error) { | ||
const wrappedContext = { error: context }; | ||
context = wrappedContext; | ||
} | ||
if (this._options.sendLogsToConsoleOutput) { | ||
@@ -149,17 +158,7 @@ switch (level) { | ||
// Start building the log message | ||
let log = Object.assign({ | ||
let log = Object.assign(Object.assign({ | ||
// Implicit date timestamp | ||
dt: new Date(), | ||
// Explicit level | ||
level }, context); | ||
// Determine the type of message... | ||
// Is this an error? | ||
if (message instanceof Error) { | ||
log = Object.assign(Object.assign({}, log), serializeError(message)); | ||
} | ||
else { | ||
log = Object.assign(Object.assign({}, log), { | ||
// Add string message | ||
message }); | ||
} | ||
level }, context), (message instanceof Error ? serializeError(message) : { message })); | ||
let transformedLog = log; | ||
@@ -174,2 +173,4 @@ for (const middleware of this._middleware) { | ||
} | ||
// Manually serialize the log data | ||
transformedLog = this.serialize(transformedLog, this._options.contextObjectMaxDepth); | ||
if (!this._options.sendLogsToBetterStack) { | ||
@@ -202,2 +203,59 @@ // Return the resulting log before sending it | ||
} | ||
serialize(value, maxDepth, visitedObjects = new WeakSet()) { | ||
if (value === null || | ||
typeof value === "boolean" || | ||
typeof value === "number" || | ||
typeof value === "string") { | ||
return value; | ||
} | ||
else if (value instanceof Date) { | ||
// Date instances can be invalid & toISOString() will fail | ||
if (isNaN(value.getTime())) { | ||
return value.toString(); | ||
} | ||
return value.toISOString(); | ||
} | ||
else if (value instanceof Error) { | ||
return serializeError(value); | ||
} | ||
else if ((typeof value === "object" || Array.isArray(value)) && | ||
(maxDepth < 1 || visitedObjects.has(value))) { | ||
if (visitedObjects.has(value)) { | ||
if (this._options.contextObjectCircularRefWarn) { | ||
console.warn(`[Logtail] Found a circular reference when serializing logs. Please do not use circular references in your logs.`); | ||
} | ||
return "<omitted circular reference>"; | ||
} | ||
if (this._options.contextObjectMaxDepthWarn) { | ||
console.warn(`[Logtail] Max depth of ${this._options.contextObjectMaxDepth} reached when serializing logs. Please do not use excessive object depth in your logs.`); | ||
} | ||
return `<omitted context beyond configured max depth: ${this._options.contextObjectMaxDepth}>`; | ||
} | ||
else if (Array.isArray(value)) { | ||
visitedObjects.add(value); | ||
const serializedArray = value.map(item => this.serialize(item, maxDepth - 1, visitedObjects)); | ||
visitedObjects.delete(value); | ||
return serializedArray; | ||
} | ||
else if (typeof value === "object") { | ||
const serializedObject = {}; | ||
visitedObjects.add(value); | ||
Object.entries(value).forEach(item => { | ||
const key = item[0]; | ||
const value = item[1]; | ||
const serializedValue = this.serialize(value, maxDepth - 1, visitedObjects); | ||
if (serializedValue !== undefined) { | ||
serializedObject[key] = serializedValue; | ||
} | ||
}); | ||
visitedObjects.delete(value); | ||
return serializedObject; | ||
} | ||
else if (typeof value === "undefined") { | ||
return undefined; | ||
} | ||
else { | ||
return `<omitted unserializable ${typeof value}>`; | ||
} | ||
} | ||
/** | ||
@@ -204,0 +262,0 @@ * |
{ | ||
"name": "@logtail/core", | ||
"version": "0.4.16", | ||
"version": "0.4.17", | ||
"description": "Better Stack logging core (formerly Logtail)", | ||
@@ -48,3 +48,3 @@ "keywords": [ | ||
}, | ||
"gitHead": "6937cd7195fbdb73b54033fe79c12801ebd1dca7" | ||
"gitHead": "f2026bd07c7fcea650a37d814cc2806b1514f15d" | ||
} |
116
src/base.ts
@@ -199,2 +199,12 @@ import { | ||
): Promise<ILogtailLog & TContext> { | ||
// Wrap context in an object, if it's not already | ||
if (typeof context !== "object") { | ||
const wrappedContext: unknown = { extra: context }; | ||
context = wrappedContext as TContext; | ||
} | ||
if (context instanceof Error) { | ||
const wrappedContext: unknown = { error: context }; | ||
context = wrappedContext as TContext; | ||
} | ||
if (this._options.sendLogsToConsoleOutput) { | ||
@@ -238,25 +248,7 @@ switch (level) { | ||
...context, | ||
// Add string message or serialized error | ||
...(message instanceof Error ? serializeError(message) : { message }), | ||
}; | ||
// Determine the type of message... | ||
// Is this an error? | ||
if (message instanceof Error) { | ||
log = { | ||
// Add stub | ||
...log, | ||
// Serialize the error and add to log | ||
...serializeError(message), | ||
}; | ||
} else { | ||
log = { | ||
// Add stub | ||
...log, | ||
// Add string message | ||
message, | ||
}; | ||
} | ||
let transformedLog = log as ILogtailLog | null; | ||
@@ -272,2 +264,8 @@ for (const middleware of this._middleware) { | ||
// Manually serialize the log data | ||
transformedLog = this.serialize( | ||
transformedLog, | ||
this._options.contextObjectMaxDepth, | ||
); | ||
if (!this._options.sendLogsToBetterStack) { | ||
@@ -303,2 +301,78 @@ // Return the resulting log before sending it | ||
private serialize( | ||
value: any, | ||
maxDepth: number, | ||
visitedObjects: WeakSet<any> = new WeakSet(), | ||
): any { | ||
if ( | ||
value === null || | ||
typeof value === "boolean" || | ||
typeof value === "number" || | ||
typeof value === "string" | ||
) { | ||
return value; | ||
} else if (value instanceof Date) { | ||
// Date instances can be invalid & toISOString() will fail | ||
if (isNaN(value.getTime())) { | ||
return value.toString(); | ||
} | ||
return value.toISOString(); | ||
} else if (value instanceof Error) { | ||
return serializeError(value); | ||
} else if ( | ||
(typeof value === "object" || Array.isArray(value)) && | ||
(maxDepth < 1 || visitedObjects.has(value)) | ||
) { | ||
if (visitedObjects.has(value)) { | ||
if (this._options.contextObjectCircularRefWarn) { | ||
console.warn( | ||
`[Logtail] Found a circular reference when serializing logs. Please do not use circular references in your logs.`, | ||
); | ||
} | ||
return "<omitted circular reference>"; | ||
} | ||
if (this._options.contextObjectMaxDepthWarn) { | ||
console.warn( | ||
`[Logtail] Max depth of ${this._options.contextObjectMaxDepth} reached when serializing logs. Please do not use excessive object depth in your logs.`, | ||
); | ||
} | ||
return `<omitted context beyond configured max depth: ${this._options.contextObjectMaxDepth}>`; | ||
} else if (Array.isArray(value)) { | ||
visitedObjects.add(value); | ||
const serializedArray = value.map(item => | ||
this.serialize(item, maxDepth - 1, visitedObjects), | ||
); | ||
visitedObjects.delete(value); | ||
return serializedArray; | ||
} else if (typeof value === "object") { | ||
const serializedObject: { [key: string]: any } = {}; | ||
visitedObjects.add(value); | ||
Object.entries(value).forEach(item => { | ||
const key = item[0]; | ||
const value = item[1]; | ||
const serializedValue = this.serialize( | ||
value, | ||
maxDepth - 1, | ||
visitedObjects, | ||
); | ||
if (serializedValue !== undefined) { | ||
serializedObject[key] = serializedValue; | ||
} | ||
}); | ||
visitedObjects.delete(value); | ||
return serializedObject; | ||
} else if (typeof value === "undefined") { | ||
return undefined; | ||
} else { | ||
return `<omitted unserializable ${typeof value}>`; | ||
} | ||
} | ||
/** | ||
@@ -305,0 +379,0 @@ * |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
152639
2607