refactor(logs): move to core package (#4586)

This commit is contained in:
Meier Lukas
2025-12-16 23:37:44 +01:00
committed by GitHub
parent d86af072bf
commit d348abfe4a
145 changed files with 971 additions and 708 deletions

View File

@@ -1,9 +1,11 @@
import dayjs from "dayjs";
import type { Duration } from "dayjs/plugin/duration";
import { logger } from "@homarr/log";
import { createLogger } from "@homarr/core/infrastructure/logs";
import type { createChannelWithLatestAndEvents } from "@homarr/redis";
const logger = createLogger({ module: "cachedRequestHandler" });
interface Options<TData, TInput extends Record<string, unknown>> {
// Unique key for this request handler
queryKey: string;
@@ -34,9 +36,10 @@ export const createCachedRequestHandler = <TData, TInput extends Record<string,
};
if (forceUpdate) {
logger.debug(
`Cached request handler forced update for channel='${channel.name}' queryKey='${options.queryKey}'`,
);
logger.debug("Cached request handler forced update", {
channel: channel.name,
queryKey: options.queryKey,
});
return await requestNewDataAsync();
}
@@ -47,22 +50,27 @@ export const createCachedRequestHandler = <TData, TInput extends Record<string,
dayjs().diff(channelData.timestamp, "milliseconds") > options.cacheDuration.asMilliseconds();
if (shouldRequestNewData) {
logger.debug(
`Cached request handler cache miss for channel='${channel.name}' queryKey='${options.queryKey}' reason='${!channelData ? "no data" : "cache expired"}'`,
);
logger.debug("Cached request handler cache miss", {
channel: channel.name,
queryKey: options.queryKey,
reason: !channelData ? "no data" : "cache expired",
});
return await requestNewDataAsync();
}
logger.debug(
`Cached request handler cache hit for channel='${channel.name}' queryKey='${options.queryKey}' expiresAt='${dayjs(channelData.timestamp).add(options.cacheDuration).toISOString()}'`,
);
logger.debug("Cached request handler cache hit", {
channel: channel.name,
queryKey: options.queryKey,
expiresAt: dayjs(channelData.timestamp).add(options.cacheDuration).toISOString(),
});
return channelData;
},
async invalidateAsync() {
logger.debug(
`Cached request handler invalidating cache channel='${channel.name}' queryKey='${options.queryKey}'`,
);
logger.debug("Cached request handler invalidating cache", {
channel: channel.name,
queryKey: options.queryKey,
});
await this.getCachedOrUpdatedDataAsync({ forceUpdate: true });
},
subscribe(callback: (data: TData) => void) {

View File

@@ -3,10 +3,11 @@ import SuperJSON from "superjson";
import { hashObjectBase64, Stopwatch } from "@homarr/common";
import { decryptSecret } from "@homarr/common/server";
import type { MaybeArray } from "@homarr/common/types";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error";
import { db } from "@homarr/db";
import { getItemsWithIntegrationsAsync, getServerSettingsAsync } from "@homarr/db/queries";
import type { WidgetKind } from "@homarr/definitions";
import { logger } from "@homarr/log";
// This imports are done that way to avoid circular dependencies.
import type { inferSupportedIntegrationsStrict } from "../../../widgets/src";
@@ -14,6 +15,8 @@ import { reduceWidgetOptionsWithDefaultValues } from "../../../widgets/src";
import type { WidgetComponentProps } from "../../../widgets/src/definition";
import type { createCachedIntegrationRequestHandler } from "./cached-integration-request-handler";
const logger = createLogger({ module: "cachedRequestIntegrationJobHandler" });
export const createRequestIntegrationJobHandler = <
TWidgetKind extends WidgetKind,
TIntegrationKind extends inferSupportedIntegrationsStrict<TWidgetKind>,
@@ -37,9 +40,10 @@ export const createRequestIntegrationJobHandler = <
kinds: widgetKinds,
});
logger.debug(
`Found items for integration widgetKinds='${widgetKinds.join(",")}' count=${itemsForIntegration.length}`,
);
logger.debug("Found items for integration", {
widgetKinds: widgetKinds.join(","),
count: itemsForIntegration.length,
});
const distinctIntegrations: {
integrationId: string;
@@ -102,14 +106,14 @@ export const createRequestIntegrationJobHandler = <
);
const stopWatch = new Stopwatch();
await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true });
logger.debug(
`Ran integration job integration=${integrationId} inputHash='${inputHash}' elapsed=${stopWatch.getElapsedInHumanWords()}`,
);
logger.debug("Ran integration job", {
integration: integrationId,
inputHash,
elapsed: stopWatch.getElapsedInHumanWords(),
});
} catch (error) {
logger.error(
new Error(`Failed to run integration job integration=${integrationId} inputHash='${inputHash}'`, {
cause: error,
}),
new ErrorWithMetadata("Failed to run integration job", { integrationId, inputHash }, { cause: error }),
);
}
}

View File

@@ -4,10 +4,12 @@ import dayjs from "dayjs";
import { z } from "zod/v4";
import type { Modify } from "@homarr/common/types";
import { logger } from "@homarr/log";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler";
const logger = createLogger({ module: "rssFeedsRequestHandler" });
export const rssFeedsRequestHandler = createCachedWidgetRequestHandler({
queryKey: "rssFeedList",
widgetKind: "rssFeed",

View File

@@ -4,12 +4,14 @@ import { compareSemVer, isValidSemVer } from "semver-parser";
import { fetchWithTimeout } from "@homarr/common";
import { env } from "@homarr/common/env";
import { logger } from "@homarr/log";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { createChannelWithLatestAndEvents } from "@homarr/redis";
import { createCachedRequestHandler } from "@homarr/request-handler/lib/cached-request-handler";
import packageJson from "../../../package.json";
const logger = createLogger({ module: "updateCheckerRequestHandler" });
export const updateCheckerRequestHandler = createCachedRequestHandler({
queryKey: "homarr-update-checker",
cacheDuration: dayjs.duration(1, "hour"),
@@ -34,7 +36,7 @@ export const updateCheckerRequestHandler = createCachedRequestHandler({
for (const release of releases.data) {
if (!isValidSemVer(release.tag_name)) {
logger.warn(`Unable to parse semantic tag '${release.tag_name}'. Update check might not work.`);
logger.warn("Unable to parse semantic tag. Update check might not work.", { tagName: release.tag_name });
continue;
}
@@ -46,11 +48,12 @@ export const updateCheckerRequestHandler = createCachedRequestHandler({
.sort((releaseA, releaseB) => compareSemVer(releaseB.tag_name, releaseA.tag_name));
if (availableNewerReleases.length > 0) {
logger.info(
"Update checker found a new available version",
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
`Update checker found a new available version: ${availableReleases[0]!.tag_name}. Current version is ${currentVersion}`,
{ version: availableReleases[0]!.tag_name, currentVersion },
);
} else {
logger.debug(`Update checker did not find any available updates. Current version is ${currentVersion}`);
logger.debug("Update checker did not find any available updates", { currentVersion });
}
return {