diff --git a/.changeset/logger-with-child-loggers.md b/.changeset/logger-with-child-loggers.md new file mode 100644 index 0000000000..b4f1e46bdd --- /dev/null +++ b/.changeset/logger-with-child-loggers.md @@ -0,0 +1,8 @@ +--- +"@prosopo/database": patch +"@prosopo/env": patch +"@prosopo/redis-client": patch +"@prosopo/provider": patch +--- + +Bind repeated log context once with `Logger.with` instead of re-attaching the same data on every log call (mongo `mongoUrl`, redis `url`/`name`, provider startup-cleanup `failedFuncName`, and IP validation `challengeIp`/`providedIp`). diff --git a/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.bin b/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.bin index 3bce0826de..dd7e4c03e1 100644 Binary files a/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.bin and b/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.bin differ diff --git a/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.lock b/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.lock index ae4ac8b7bd..f277520c10 100644 Binary files a/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.lock and b/demos/android-webview/.gradle/8.7/fileHashes/fileHashes.lock differ diff --git a/demos/android-webview/.gradle/file-system.probe b/demos/android-webview/.gradle/file-system.probe index a64bc332e7..bc0da9252c 100644 Binary files a/demos/android-webview/.gradle/file-system.probe and b/demos/android-webview/.gradle/file-system.probe differ diff --git a/packages/database/src/base/mongo.ts b/packages/database/src/base/mongo.ts index 8f28d77f98..03a22c33ee 100644 --- a/packages/database/src/base/mongo.ts +++ b/packages/database/src/base/mongo.ts @@ -55,7 +55,9 @@ export class MongoDatabase implements IDatabase { this._url = parsedUrl.toString(); this.safeURL = this.url.replace(/\w+:\w+/, ""); this.dbname = dbname || parsedUrl.pathname.replace("/", ""); - this.logger = logger || getLogger("info", "database:mongo"); + this.logger = (logger || getLogger("info", "database:mongo")).with({ + mongoUrl: this.safeURL, + }); } get url(): string { @@ -77,14 +79,12 @@ export class MongoDatabase implements IDatabase { */ async connect(): Promise { this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Connecting to database", })); try { // Already connected if (this.connected) { this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database connection already open", })); return; @@ -93,7 +93,6 @@ export class MongoDatabase implements IDatabase { // If a connection is in progress, await it if (this.connecting) { this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database connection in progress, waiting for it to finish", })); return this.connecting; @@ -116,7 +115,6 @@ export class MongoDatabase implements IDatabase { const onConnected = () => { this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database connection opened", })); this.connected = true; @@ -128,7 +126,6 @@ export class MongoDatabase implements IDatabase { const onError = (err: unknown) => { this.logger.error(() => ({ err, - data: { mongoUrl: this.safeURL }, msg: "Database error", })); this.connected = false; @@ -143,7 +140,6 @@ export class MongoDatabase implements IDatabase { connection.on("disconnected", () => { this.connected = false; this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database disconnected", })); }); @@ -151,7 +147,6 @@ export class MongoDatabase implements IDatabase { connection.on("reconnected", () => { this.connected = true; this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database reconnected", })); }); @@ -159,7 +154,6 @@ export class MongoDatabase implements IDatabase { connection.on("close", () => { this.connected = false; this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database connection closed", })); }); @@ -167,7 +161,6 @@ export class MongoDatabase implements IDatabase { connection.on("fullsetup", () => { this.connected = true; this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Database connection is fully setup", })); }); @@ -177,7 +170,6 @@ export class MongoDatabase implements IDatabase { } catch (e) { this.logger.error(() => ({ err: e, - data: { mongoUrl: this.safeURL }, msg: "Database connection error", })); throw e; @@ -187,7 +179,6 @@ export class MongoDatabase implements IDatabase { /** Close connection to the database */ async close(): Promise { this.logger.debug(() => ({ - data: { mongoUrl: this.safeURL }, msg: "Closing connection", })); await this.connection?.close(); diff --git a/packages/env/src/provider.ts b/packages/env/src/provider.ts index e64274bc1d..6df8b195af 100644 --- a/packages/env/src/provider.ts +++ b/packages/env/src/provider.ts @@ -31,13 +31,14 @@ export class ProviderEnvironment extends Environment { return; } + const errorLog = this.logger.with({ failedFuncName: this.cleanup.name }); + this.db ?.cleanupScheduledTaskStatus(ScheduledTaskStatus.Running) .catch((err) => { - this.logger.error(() => ({ + errorLog.error(() => ({ msg: "Failed to cleanup running scheduled tasks", err, - data: { failedFuncName: this.cleanup.name }, })); }); @@ -49,10 +50,9 @@ export class ProviderEnvironment extends Environment { const redisConnection = this.getDb().getRedisConnection(); const writeQueue = new RedisWriteQueue(redisConnection, this.logger); writeQueue.clearAllSessionRecords().catch((err) => { - this.logger.error(() => ({ + errorLog.error(() => ({ msg: "Failed to clear Redis session records at startup", err, - data: { failedFuncName: this.cleanup.name }, })); }); } catch (err) { diff --git a/packages/provider/src/util.ts b/packages/provider/src/util.ts index a738d27ebd..b292e7e70e 100644 --- a/packages/provider/src/util.ts +++ b/packages/provider/src/util.ts @@ -374,6 +374,10 @@ export const deepValidateIpAddress = async ( distanceKm?: number; shouldFlag?: boolean; }> => { + const log = logger.with({ + challengeIp: challengeIpAddress.address, + providedIp: ip, + }); if ( ipValidationRules?.forceConsistentIp === true && dnsPeerIp && @@ -398,12 +402,8 @@ export const deepValidateIpAddress = async ( } // IP mismatch - continue to distance checking if not forcing consistent IPs if (ipValidationRules?.forceConsistentIp === true) { - logger.info(() => ({ + log.info(() => ({ msg: "IP validation failed - forceConsistentIp is true", - data: { - challengeIp: challengeIpAddress.address, - providedIp: ip, - }, })); return { isValid: false, @@ -421,12 +421,10 @@ export const deepValidateIpAddress = async ( const comparison = await compareIPs(challengeIpString, ip, ipInfoService); if ("error" in comparison) { - logger.error(() => ({ + log.error(() => ({ msg: "Failed to get IP distance comparison", data: { error: comparison.error, - challengeIp: challengeIpString, - providedIp: ip, }, })); // If we can't do distance comparison and IPs don't match exactly, be strict @@ -444,22 +442,18 @@ export const deepValidateIpAddress = async ( // If no validation rules provided, use legacy logic (1000km threshold) if (!ipValidationRules) { - logger.info(() => ({ + log.info(() => ({ msg: "No IP validation rules provided, using legacy logic", data: { - challengeIp: challengeIpString, - providedIp: ip, distanceKm: distanceKm, }, })); // Legacy distance > 1000km -> fail and log if (distanceKm !== undefined && distanceKm > 1000) { const errorMessage = `IP addresses are too far apart: ${distanceKm.toFixed(2)}km (>1000km limit)`; - logger.info(() => ({ + log.info(() => ({ msg: "IP validation failed - distance too great", data: { - challengeIp: challengeIpString, - providedIp: ip, distanceKm: distanceKm, comparison: comparison.comparison, }, @@ -472,11 +466,9 @@ export const deepValidateIpAddress = async ( } // Legacy distance <= 1000km -> allow flag - logger.info(() => ({ + log.info(() => ({ msg: "IP addresses differ but within acceptable distance", data: { - challengeIp: challengeIpString, - providedIp: ip, distanceKm: distanceKm, comparison: comparison.comparison, }, @@ -517,10 +509,9 @@ export const deepValidateIpAddress = async ( }; } } catch (error) { - logger.error(() => ({ + log.error(() => ({ msg: "Error during IP distance validation", err: error, - data: { challengeIp: challengeIpAddress.address, providedIp: ip }, })); // Something weird going on -> allow but flag return { diff --git a/packages/redis-client/src/redisClient.ts b/packages/redis-client/src/redisClient.ts index 9418404344..a8a92368f1 100644 --- a/packages/redis-client/src/redisClient.ts +++ b/packages/redis-client/src/redisClient.ts @@ -54,21 +54,19 @@ export const connectToRedis = (options: RedisOptions): RedisConnection => { } }); - options.logger.info(() => ({ + const log = options.logger.with({ url: options.url }); + + log.info(() => ({ msg: "Connecting to Redis", - data: { - url: options.url, - }, })); const clientPromise = masterClient.connect().then(async (connectedClient) => { isReady = true; timestamps.connectedAt = Date.now(); - options.logger.info(() => ({ + log.info(() => ({ msg: "Redis connected", data: { - url: options.url, awaitingTimeMs: timestamps.connectedAt - timestamps.initializedAt, }, })); @@ -98,14 +96,13 @@ export const setupRedisIndex = ( let isReady = false; + const log = logger.with({ name: index.name }); + const clientPromise = connection.getClient().then(async (client) => { timestamps.initializedAt = Date.now(); - logger.info(() => ({ + log.info(() => ({ msg: "Setting up Redis index", - data: { - name: index.name, - }, })); await createRedisIndex(client, index); @@ -113,10 +110,9 @@ export const setupRedisIndex = ( isReady = true; timestamps.setupAt = Date.now(); - logger.info(() => ({ + log.info(() => ({ msg: "Index setup", data: { - name: index.name, awaitingTimeMs: timestamps.setupAt - timestamps.initializedAt, }, }));