refactor(logs): move to core package (#4586)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { AxiosError } from "axios";
|
||||
import { createTask, validate } from "node-cron";
|
||||
|
||||
import { Stopwatch } from "@homarr/common";
|
||||
import type { MaybePromise } from "@homarr/common/types";
|
||||
import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error";
|
||||
import { db } from "@homarr/db";
|
||||
|
||||
import type { Logger } from "./logger";
|
||||
@@ -33,33 +33,39 @@ const createCallback = <TAllowedNames extends string, TName extends TAllowedName
|
||||
return (callback: () => MaybePromise<void>) => {
|
||||
const catchingCallbackAsync = async () => {
|
||||
try {
|
||||
creatorOptions.logger.logDebug(`The callback of '${name}' cron job started`);
|
||||
creatorOptions.logger.logDebug("The callback of cron job started", {
|
||||
name,
|
||||
});
|
||||
const stopwatch = new Stopwatch();
|
||||
await creatorOptions.beforeCallback?.(name);
|
||||
const beforeCallbackTook = stopwatch.getElapsedInHumanWords();
|
||||
await callback();
|
||||
const callbackTook = stopwatch.getElapsedInHumanWords();
|
||||
creatorOptions.logger.logDebug(
|
||||
`The callback of '${name}' cron job succeeded (before callback took ${beforeCallbackTook}, callback took ${callbackTook})`,
|
||||
);
|
||||
creatorOptions.logger.logDebug("The callback of cron job succeeded", {
|
||||
name,
|
||||
beforeCallbackTook,
|
||||
callbackTook,
|
||||
});
|
||||
|
||||
const durationInMillis = stopwatch.getElapsedInMilliseconds();
|
||||
if (durationInMillis > expectedMaximumDurationInMillis) {
|
||||
creatorOptions.logger.logWarning(
|
||||
`The callback of '${name}' succeeded but took ${(durationInMillis - expectedMaximumDurationInMillis).toFixed(2)}ms longer than expected (${expectedMaximumDurationInMillis}ms). This may indicate that your network performance, host performance or something else is too slow. If this happens too often, it should be looked into.`,
|
||||
);
|
||||
creatorOptions.logger.logWarning("The callback of cron job took longer than expected", {
|
||||
name,
|
||||
durationInMillis,
|
||||
expectedMaximumDurationInMillis,
|
||||
});
|
||||
}
|
||||
await creatorOptions.onCallbackSuccess?.(name);
|
||||
} catch (error) {
|
||||
// Log AxiosError in a less detailed way to prevent very long output
|
||||
if (error instanceof AxiosError) {
|
||||
creatorOptions.logger.logError(
|
||||
`Failed to run job '${name}': [AxiosError] ${error.message} ${error.response?.status} ${error.response?.config.url}\n${error.stack}`,
|
||||
);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
creatorOptions.logger.logError(`Failed to run job '${name}': ${error}`);
|
||||
}
|
||||
creatorOptions.logger.logError(
|
||||
new ErrorWithMetadata(
|
||||
"The callback of cron job failed",
|
||||
{
|
||||
name,
|
||||
},
|
||||
{ cause: error },
|
||||
),
|
||||
);
|
||||
await creatorOptions.onCallbackError?.(name, error);
|
||||
}
|
||||
};
|
||||
@@ -80,21 +86,28 @@ const createCallback = <TAllowedNames extends string, TName extends TAllowedName
|
||||
timezone: creatorOptions.timezone,
|
||||
},
|
||||
);
|
||||
creatorOptions.logger.logDebug(
|
||||
`The cron job '${name}' was created with expression ${defaultCronExpression} in timezone ${creatorOptions.timezone} and runOnStart ${options.runOnStart}`,
|
||||
);
|
||||
creatorOptions.logger.logDebug("The scheduled task for cron job was created", {
|
||||
name,
|
||||
cronExpression: defaultCronExpression,
|
||||
timezone: creatorOptions.timezone,
|
||||
runOnStart: options.runOnStart,
|
||||
});
|
||||
|
||||
return scheduledTask;
|
||||
},
|
||||
async onStartAsync() {
|
||||
if (options.beforeStart) {
|
||||
creatorOptions.logger.logDebug(`Running beforeStart for job: ${name}`);
|
||||
creatorOptions.logger.logDebug("Running beforeStart for job", {
|
||||
name,
|
||||
});
|
||||
await options.beforeStart();
|
||||
}
|
||||
|
||||
if (!options.runOnStart) return;
|
||||
|
||||
creatorOptions.logger.logDebug(`The cron job '${name}' is running because runOnStart is set to true`);
|
||||
creatorOptions.logger.logDebug("The cron job is configured to run on start, executing callback", {
|
||||
name,
|
||||
});
|
||||
await catchingCallbackAsync();
|
||||
},
|
||||
async executeAsync() {
|
||||
@@ -117,11 +130,17 @@ export const createCronJobCreator = <TAllowedNames extends string = string>(
|
||||
defaultCronExpression: TExpression,
|
||||
options: CreateCronJobOptions = { runOnStart: false },
|
||||
) => {
|
||||
creatorOptions.logger.logDebug(`Validating cron expression '${defaultCronExpression}' for job: ${name}`);
|
||||
creatorOptions.logger.logDebug("Validating cron expression for cron job", {
|
||||
name,
|
||||
cronExpression: defaultCronExpression,
|
||||
});
|
||||
if (!validate(defaultCronExpression)) {
|
||||
throw new Error(`Invalid cron expression '${defaultCronExpression}' for job '${name}'`);
|
||||
}
|
||||
creatorOptions.logger.logDebug(`Cron job expression '${defaultCronExpression}' for job ${name} is valid`);
|
||||
creatorOptions.logger.logDebug("Cron job expression for cron job is valid", {
|
||||
name,
|
||||
cronExpression: defaultCronExpression,
|
||||
});
|
||||
|
||||
const returnValue = {
|
||||
withCallback: createCallback<TAllowedNames, TName>(name, defaultCronExpression, options, creatorOptions),
|
||||
|
||||
Reference in New Issue
Block a user