SDK: IO Logging now respects the job and client logLevel, and only outputs locally when ioLogLocalEnabled is true

This commit is contained in:
Eric Allam
2023-07-03 16:00:11 +01:00
parent 807b9d4c45
commit 486d6818ba
8 changed files with 103 additions and 31 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---
IO Logging now respects the job and client logLevel, and only outputs locally when ioLogLocalEnabled is true
@@ -0,0 +1,19 @@
import { client } from "@/trigger";
import { Job, eventTrigger } from "@trigger.dev/sdk";
new Job(client, {
id: "test-logging",
name: "Test logging",
version: "0.0.1",
logLevel: "debug",
trigger: eventTrigger({
name: "test.logging",
}),
run: async (payload, io, ctx) => {
await io.logger.log("Hello log level", { payload });
await io.logger.error("Hello error level", { payload });
await io.logger.warn("Hello warn level", { payload });
await io.logger.info("Hello info level", { payload });
await io.logger.debug("Hello debug level", { payload });
},
});
@@ -4,6 +4,7 @@ import "@/jobs/openai";
import "@/jobs/resend";
import "@/jobs/general";
import "@/jobs/slack";
import "@/jobs/logging";
import { createPagesRoute } from "@trigger.dev/nextjs";
const { handler, config } = createPagesRoute(client);
+2 -1
View File
@@ -16,7 +16,8 @@ export const client = new TriggerClient({
id: "nextjs-example",
apiKey: process.env.TRIGGER_API_KEY,
apiUrl: process.env.TRIGGER_API_URL,
logLevel: "debug",
verbose: false,
ioLogLocalEnabled: true,
});
export const openai = new OpenAI({
+4
View File
@@ -35,6 +35,10 @@ export class Logger {
);
}
static satisfiesLogLevel(logLevel: LogLevel, setLevel: LogLevel) {
return logLevels.indexOf(logLevel) <= logLevels.indexOf(setLevel);
}
log(...args: any[]) {
if (this.#level < 0) return;
+40 -18
View File
@@ -43,6 +43,8 @@ export type IOOptions = {
context: TriggerContext;
logger?: Logger;
logLevel?: LogLevel;
jobLogger?: Logger;
jobLogLevel: LogLevel;
cachedTasks?: Array<CachedTask>;
};
@@ -51,6 +53,8 @@ export class IO {
private _apiClient: ApiClient;
private _triggerClient: TriggerClient;
private _logger: Logger;
private _jobLogger?: Logger;
private _jobLogLevel: LogLevel;
private _cachedTasks: Map<string, CachedTask>;
private _taskStorage: AsyncLocalStorage<{ taskId: string }>;
private _context: TriggerContext;
@@ -62,6 +66,8 @@ export class IO {
this._logger =
options.logger ?? new Logger("trigger.dev", options.logLevel);
this._cachedTasks = new Map();
this._jobLogger = options.jobLogger;
this._jobLogLevel = options.jobLogLevel;
if (options.cachedTasks) {
options.cachedTasks.forEach((task) => {
@@ -75,38 +81,51 @@ export class IO {
get logger() {
return new IOLogger(async (level, message, data) => {
let logLevel: LogLevel = "info";
switch (level) {
case "LOG": {
this._jobLogger?.log(message, data);
logLevel = "log";
break;
}
case "DEBUG": {
this._logger.debug(message, data);
this._jobLogger?.debug(message, data);
logLevel = "debug";
break;
}
case "INFO": {
this._logger.info(message, data);
this._jobLogger?.info(message, data);
logLevel = "info";
break;
}
case "WARN": {
this._logger.warn(message, data);
this._jobLogger?.warn(message, data);
logLevel = "warn";
break;
}
case "ERROR": {
this._logger.error(message, data);
this._jobLogger?.error(message, data);
logLevel = "error";
break;
}
}
await this.runTask(
[message, level],
{
name: "log",
icon: "log",
description: message,
params: data,
properties: [{ label: "Level", text: level }],
style: { style: "minimal", variant: level.toLowerCase() },
noop: true,
},
async (task) => {}
);
if (Logger.satisfiesLogLevel(logLevel, this._jobLogLevel)) {
await this.runTask(
[message, level],
{
name: "log",
icon: "log",
description: message,
params: data,
properties: [{ label: "Level", text: level }],
style: { style: "minimal", variant: level.toLowerCase() },
noop: true,
},
async (task) => {}
);
}
});
}
@@ -595,7 +614,7 @@ function stableStringify(obj: any): string {
}
type CallbackFunction = (
level: "DEBUG" | "INFO" | "WARN" | "ERROR",
level: "DEBUG" | "INFO" | "WARN" | "ERROR" | "LOG",
message: string,
properties?: Record<string, any>
) => Promise<void>;
@@ -603,6 +622,9 @@ type CallbackFunction = (
export class IOLogger implements TaskLogger {
constructor(private callback: CallbackFunction) {}
log(message: string, properties?: Record<string, any>): Promise<void> {
return this.callback("LOG", message, properties);
}
debug(message: string, properties?: Record<string, any>): Promise<void> {
return this.callback("DEBUG", message, properties);
}
+5
View File
@@ -12,6 +12,7 @@ import {
import { TriggerClient } from "./triggerClient";
import type {
EventSpecification,
Logger,
Trigger,
TriggerContext,
TriggerEventType,
@@ -103,6 +104,10 @@ export class Job<
);
}
get logLevel() {
return this.options.logLevel;
}
toJSON(): JobMetadata {
// @ts-ignore
const internal = this.options.__internal as JobMetadata["internal"];
+27 -12
View File
@@ -57,6 +57,8 @@ export type TriggerClientOptions = {
running your own Trigger.dev instance. */
apiUrl?: string;
logLevel?: LogLevel;
verbose?: boolean;
ioLogLocalEnabled?: boolean;
};
/** A [TriggerClient](https://trigger.dev/docs/documentation/concepts/client-adaptors) is used to connect to a specific [Project](https://trigger.dev/docs/documentation/concepts/projects) by using an [API Key](https://trigger.dev/docs/documentation/concepts/environments-apikeys). */
@@ -87,18 +89,21 @@ export class TriggerClient {
{};
#client: ApiClient;
#logger: Logger;
#internalLogger: Logger;
id: string;
constructor(options: Prettify<TriggerClientOptions>) {
this.id = options.id;
this.#options = options;
this.#client = new ApiClient(this.#options);
this.#logger = new Logger("trigger.dev", this.#options.logLevel);
this.#internalLogger = new Logger(
"trigger.dev",
this.#options.verbose ? "debug" : "log"
);
}
async handleRequest(request: Request): Promise<NormalizedResponse> {
this.#logger.debug("handling request", {
this.#internalLogger.debug("handling request", {
url: request.url,
headers: Object.fromEntries(request.headers.entries()),
method: request.method,
@@ -455,7 +460,7 @@ export class TriggerClient {
params: any;
}): void {
this.#registeredHttpSourceHandlers[options.key] = async (s, r) => {
return await options.source.handle(s, r, this.#logger);
return await options.source.handle(s, r, this.#internalLogger);
};
let registeredSource = this.#registeredSources[options.key];
@@ -593,7 +598,10 @@ export class TriggerClient {
body: RunJobBody,
job: Job<Trigger<any>, any>
): Promise<RunJobResponse> {
this.#logger.debug("executing job", { execution: body, job: job.toJSON() });
this.#internalLogger.debug("executing job", {
execution: body,
job: job.toJSON(),
});
const context = this.#createRunContext(body);
@@ -601,9 +609,13 @@ export class TriggerClient {
id: body.run.id,
cachedTasks: body.tasks,
apiClient: this.#client,
logger: this.#logger,
logger: this.#internalLogger,
client: this,
context,
jobLogLevel: job.logLevel ?? this.#options.logLevel ?? "info",
jobLogger: this.#options.ioLogLocalEnabled
? new Logger(job.id, job.logLevel ?? this.#options.logLevel ?? "info")
: undefined,
});
const ioWithConnections = createIOWithIntegrations(
@@ -714,7 +726,7 @@ export class TriggerClient {
},
sourceRequest: Request
): Promise<{ response: NormalizedResponse; events: SendEvent[] }> {
this.#logger.debug("Handling HTTP source request", {
this.#internalLogger.debug("Handling HTTP source request", {
source,
});
@@ -722,9 +734,12 @@ export class TriggerClient {
const dynamicTrigger = this.#registeredDynamicTriggers[source.dynamicId];
if (!dynamicTrigger) {
this.#logger.debug("No dynamic trigger registered for HTTP source", {
source,
});
this.#internalLogger.debug(
"No dynamic trigger registered for HTTP source",
{
source,
}
);
return {
response: {
@@ -740,7 +755,7 @@ export class TriggerClient {
const results = await dynamicTrigger.source.handle(
source,
sourceRequest,
this.#logger
this.#internalLogger
);
if (!results) {
@@ -769,7 +784,7 @@ export class TriggerClient {
const handler = this.#registeredHttpSourceHandlers[source.key];
if (!handler) {
this.#logger.debug("No handler registered for HTTP source", {
this.#internalLogger.debug("No handler registered for HTTP source", {
source,
});