SDK: IO Logging now respects the job and client logLevel, and only outputs locally when ioLogLocalEnabled is true
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user