Skip to content

Commit

Permalink
add agent console interface
Browse files Browse the repository at this point in the history
  • Loading branch information
maddsua committed Jan 21, 2025
1 parent 161711e commit 502604c
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 11 deletions.
113 changes: 104 additions & 9 deletions client/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface LogEntry {
date: number;
level: LogLevel;
message: string;
meta: Metadata | null;
meta?: Metadata | null;
};

type LoggerPushFn = (message: string, meta?: MetadataInit) => void;
Expand All @@ -45,6 +45,14 @@ export interface Logger {
error: LoggerPushFn;
};

export interface LogpushConsole {
info: (...args: any[]) => void;
log: (...args: any[]) => void;
warn: (...args: any[]) => void;
error: (...args: any[]) => void;
debug: (...args: any[]) => void;
};

export class Agent {

readonly url: string;
Expand All @@ -68,18 +76,51 @@ export class Agent {
this.entries = [];
}

private push = (level: LogLevel, message: string, meta?: MetadataInit) => {
private m_loggerPush = (level: LogLevel, message: string, meta?: MetadataInit) => {

const date = new Date();
console.log(`${slogDate(date)} ${level.toUpperCase()} ${message}`);
this.entries.push({ date: date.getTime(), level, message, meta: unwrapMetadata(meta) });

this.entries.push({
date: date.getTime(),
level,
message,
meta: unwrapMetadata(meta),
});

const logFn = console.debug || console.log;
if (typeof logFn === 'function') {
logFn(`${slogDate(date)} ${level.toUpperCase()} ${message}`);
}
};

readonly logger: Logger = {
log: (message: string, meta?: MetadataInit) => this.push('log', message, meta),
info: (message: string, meta?: MetadataInit) => this.push('info', message, meta),
debug: (message: string, meta?: MetadataInit) => this.push('debug', message, meta),
warn: (message: string, meta?: MetadataInit) => this.push('warn', message, meta),
error: (message: string, meta?: MetadataInit) => this.push('error', message, meta),
log: (message: string, meta?: MetadataInit) => this.m_loggerPush('log', message, meta),
info: (message: string, meta?: MetadataInit) => this.m_loggerPush('info', message, meta),
debug: (message: string, meta?: MetadataInit) => this.m_loggerPush('debug', message, meta),
warn: (message: string, meta?: MetadataInit) => this.m_loggerPush('warn', message, meta),
error: (message: string, meta?: MetadataInit) => this.m_loggerPush('error', message, meta),
};

private m_consolePush = (level: keyof LogpushConsole, args: any[]) => {

this.entries.push({
date: new Date().getTime(),
level,
message: args.map(item => stringifyArg(item)).join(' '),
});

const logFn = console[level];
if (typeof logFn === 'function') {
logFn(...args);
}
};

readonly console: LogpushConsole = {
info: (...args: any[]) => this.m_consolePush('info', args),
log: (...args: any[]) => this.m_consolePush('log', args),
warn: (...args: any[]) => this.m_consolePush('warn', args),
error: (...args: any[]) => this.m_consolePush('error', args),
debug: (...args: any[]) => this.m_consolePush('debug', args),
};

flush = async () => {
Expand Down Expand Up @@ -114,3 +155,57 @@ const slogDate = (date: Date): string => {

return `${year}/${month}/${day} ${hour}:${min}:${sec}`;
};

const stringifyArg = (item: any): string => {
switch (typeof item) {
case 'string': return item;
case 'number': return item.toString();
case 'bigint': return item.toString();
case 'boolean': return `${item}`;
case 'object': return stringifyObjectArg(item);
case 'function': return '[fn()]';
case 'symbol': return item.toString();
default: return '[undefined]';
}
};

const stringifyObjectArg = (item: object): string => {
try {
return JSON.stringify(item, objectArgReplacerFn);
} catch (_) {
return '{}';
}
};

const objectArgReplacerFn = (_: string, value: any): any => {

if (typeof value !== 'object') {
return value;
}

if (value instanceof Error) {
return { message: value.message };
}

if (value instanceof FormData) {
return Object.fromEntries(value);
}

if (value instanceof Date) {
return value.toUTCString();
}

if (value instanceof RegExp) {
return value.source;
}

if (value instanceof Set) {
return Array.from(value.keys());
}

if (value instanceof Map) {
return Object.fromEntries(value);
}

return value;
};
3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@maddsua/logpush-client",
"version": "0.1.3",
"version": "0.2.0",
"author": "maddsua",
"license": "MIT",
"type": "module",
Expand All @@ -15,6 +15,7 @@
},
"scripts": {
"test": "esbuild --format=esm --bundle --outfile=tests/run/test.mjs tests/main.test.ts && node tests/run/test.mjs",
"test:console": "esbuild --format=esm --bundle --outfile=tests/run/console.test.mjs tests/console.test.ts && node tests/run/console.test.mjs",
"check": "tsc"
}
}
18 changes: 18 additions & 0 deletions client/tests/console.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Agent } from "../lib/client";
import { testAgentUrl } from "./test.config";

const agent = new Agent(testAgentUrl, {
api: 'console-test',
agent: 'node',
env: 'dev',
});

const formData = new FormData();
formData.set('name', 'John Doe');
formData.set('phone', '+100000000000');

agent.console.debug('Dumping form data:', formData);
agent.console.debug('Dumping trpc:', { name: 'Jane Doe', ig_username: 42 });
agent.console.log('Just writing multiple values', true, 42, new Date(), /heeey/ig, new Map([['uhm', 'secret']]), new Error('Task failed successfullly'));

await agent.flush();
3 changes: 2 additions & 1 deletion client/tests/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Agent, type Logger } from "../lib/client";
import { testAgentUrl } from "./test.config";

const fakeHandler = async (request: Request, waitUntil: (task: Promise<any>) => void): Promise<Response> => {

const agent = new Agent('http://localhost:8000/push/stream/0d460d8a-f497-4027-9384-c45378a5a63d', {
const agent = new Agent(testAgentUrl, {
client_ip: request.headers.get('x-forwarded-for'),
agent: request.headers.get('user-agent'),
method: request.method.toLowerCase(),
Expand Down
2 changes: 2 additions & 0 deletions client/tests/test.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const testStreamId = '0d460d8a-f497-4027-9384-c45378a5a63d';
export const testAgentUrl = `http://localhost:8000/push/stream/${testStreamId}`;

0 comments on commit 502604c

Please sign in to comment.