feat: add initial event logging implementation

old-agentic-v1^2
Philipp Burckhardt 2023-05-26 14:28:27 -04:00
rodzic f8bd19bdda
commit 29207be8a7
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: A2C3BCA4F31D1DDD
3 zmienionych plików z 174 dodań i 2 usunięć

Wyświetl plik

@ -42,6 +42,7 @@
"@inquirer/checkbox": "^1.3.0",
"@inquirer/editor": "^1.1.0",
"@inquirer/select": "^1.2.0",
"debug": "^4.3.4",
"handlebars": "^4.7.7",
"js-tiktoken": "^1.0.6",
"jsonrepair": "^3.1.0",
@ -52,6 +53,7 @@
"p-timeout": "^6.1.1",
"quick-lru": "^6.1.1",
"ts-dedent": "^2.2.0",
"uuid": "^9.0.0",
"zod": "^3.21.4",
"zod-to-ts": "^1.1.4",
"zod-validation-error": "^1.3.0"
@ -59,8 +61,10 @@
"devDependencies": {
"@keyv/redis": "^2.5.8",
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@types/debug": "^4.1.8",
"@types/node": "^20.2.5",
"@types/sinon": "^10.0.15",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"ava": "^5.3.0",

Wyświetl plik

@ -17,6 +17,9 @@ dependencies:
'@inquirer/select':
specifier: ^1.2.0
version: 1.2.0
debug:
specifier: ^4.3.4
version: 4.3.4
handlebars:
specifier: ^4.7.7
version: 4.7.7
@ -47,6 +50,9 @@ dependencies:
ts-dedent:
specifier: ^2.2.0
version: 2.2.0
uuid:
specifier: ^9.0.0
version: 9.0.0
zod:
specifier: ^3.21.4
version: 3.21.4
@ -64,12 +70,18 @@ devDependencies:
'@trivago/prettier-plugin-sort-imports':
specifier: ^4.1.1
version: 4.1.1(prettier@2.8.8)
'@types/debug':
specifier: ^4.1.8
version: 4.1.8
'@types/node':
specifier: ^20.2.5
version: 20.2.5
'@types/sinon':
specifier: ^10.0.15
version: 10.0.15
'@types/uuid':
specifier: ^9.0.1
version: 9.0.1
'@typescript-eslint/eslint-plugin':
specifier: ^5.59.8
version: 5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4)
@ -715,6 +727,12 @@ packages:
- supports-color
dev: true
/@types/debug@4.1.8:
resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
dependencies:
'@types/ms': 0.7.31
dev: true
/@types/json-schema@7.0.12:
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
dev: true
@ -723,6 +741,10 @@ packages:
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
dev: true
/@types/ms@0.7.31:
resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
dev: true
/@types/node@20.2.5:
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
dev: true
@ -749,6 +771,10 @@ packages:
resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==}
dev: true
/@types/uuid@9.0.1:
resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==}
dev: true
/@typescript-eslint/eslint-plugin@5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4):
resolution: {integrity: sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -1409,7 +1435,6 @@ packages:
optional: true
dependencies:
ms: 2.1.2
dev: true
/decamelize-keys@1.1.1:
resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
@ -2762,7 +2787,6 @@ packages:
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
/ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -3927,6 +3951,11 @@ packages:
punycode: 2.3.0
dev: true
/uuid@9.0.0:
resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
hasBin: true
dev: false
/validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:

139
src/logging.ts 100644
Wyświetl plik

@ -0,0 +1,139 @@
import logger from 'debug'
import { v4 as uuidv4 } from 'uuid'
/**
* Type of events that can occur within the library.
*/
export enum EventType {
LLM_CALL = 'LLM_CALL',
LLM_COMPLETION = 'LLM_COMPLETION'
}
/**
* Severity levels of an event.
*/
export enum EventSeverity {
DEBUG,
INFO,
WARNING,
ERROR,
CRITICAL
}
/*
* Define minimum LOG_LEVEL, defaulting to EventSeverity.INFO if not provided or if an invalid value is provided. Any events below that level won't be logged to the console.
*/
let LOG_LEVEL: EventSeverity = EventSeverity.INFO
if (
process.env.DEBUG_LOG_LEVEL &&
EventSeverity[process.env.DEBUG_LOG_LEVEL.toUpperCase()] !== undefined
) {
LOG_LEVEL = EventSeverity[process.env.DEBUG_LOG_LEVEL.toUpperCase()]
} else if (process.env.DEBUG_LOG_LEVEL) {
throw new Error(`Invalid value for LOG_LEVEL: ${process.env.DEBUG_LOG_LEVEL}`)
}
/**
* Define loggers for each severity level such that logs can be filtered by severity.
*/
const LOGGERS: Record<EventSeverity, ReturnType<typeof logger>> = {
[EventSeverity.CRITICAL]: logger('agentic:events:critical'),
[EventSeverity.ERROR]: logger('agentic:events:error'),
[EventSeverity.WARNING]: logger('agentic:events:warning'),
[EventSeverity.INFO]: logger('agentic:events:info'),
[EventSeverity.DEBUG]: logger('agentic:events:debug')
}
/**
* Payload of an event.
*/
interface EventPayload {
[key: string]: unknown
}
/**
* Data required to create a new Event object.
*/
interface EventData {
parentId?: string
id?: string
timestamp?: Date
payload?: EventPayload
severity?: EventSeverity
version?: number
}
/**
* Events that occur within the library (should be treated as immutable).
*/
export class Event {
public readonly type: EventType
public readonly parentId?: string
public readonly id: string
public readonly timestamp: Date
public readonly payload?: EventPayload
public readonly severity?: EventSeverity
public readonly version: number
constructor(type: EventType, data: EventData = {}) {
this.type = type
this.parentId = data.parentId ?? null
this.id = data.id ?? uuidv4()
this.timestamp = data.timestamp ?? new Date()
this.payload = data.payload ? { ...data.payload } : {} // Only doing a shallow instead of a deep copy for performance reasons..
this.severity = data.severity ?? EventSeverity.INFO
this.version = data.version ?? 1 // Default to version 1 if not provided...
}
/**
* Converts a JSON string representation of an event back into an Event object.
*/
static fromJSON(json: string): Event {
const { type, ...data } = JSON.parse(json)
// Convert the timestamp back into a Date object, since `JSON.parse()` will have turned it into a string:
data.timestamp = new Date(data.timestamp)
const event = new Event(type, data)
return event
}
/**
* Converts the event to a JSON string representation.
*
* @returns JSON representation
*/
toJSON(): string {
return JSON.stringify({
type: this.type,
parentId: this.parentId,
id: this.id,
timestamp: this.timestamp.toISOString(),
payload: this.payload,
severity: this.severity,
version: this.version
})
}
/**
* Converts the event to a human-readable string representation suitable for logging.
*
* @returns string representation
*/
toString(): string {
return `Event { type: ${this.type}, parentId: ${this.parentId}, id: ${
this.id
}, timestamp: ${this.timestamp.toISOString()}, payload: ${JSON.stringify(
this.payload
)}, severity: ${this.severity} }`
}
/**
* Logs the event to the console.
*/
log(): void {
if (this.severity >= LOG_LEVEL) {
const logger = LOGGERS[this.severity]
logger(this.toString())
}
}
}