diff --git a/api/so/sprk/actor/getPreferences.ts b/api/so/sprk/actor/getPreferences.ts index a27a3c1..e7d3284 100644 --- a/api/so/sprk/actor/getPreferences.ts +++ b/api/so/sprk/actor/getPreferences.ts @@ -127,7 +127,7 @@ export default function (server: Server, ctx: AppContext) { }, }; } catch (error) { - ctx.logger.error("Failed to get preferences", { error, userDid }); + console.error("Failed to get preferences", { error, userDid }); throw error; } }, diff --git a/api/so/sprk/actor/putPreferences.ts b/api/so/sprk/actor/putPreferences.ts index 8acd11a..dd089c7 100644 --- a/api/so/sprk/actor/putPreferences.ts +++ b/api/so/sprk/actor/putPreferences.ts @@ -131,7 +131,7 @@ export default function (server: Server, ctx: AppContext) { return; } catch (error) { - ctx.logger.error("Failed to put preferences", { error, userDid }); + console.error("Failed to put preferences", { error, userDid }); throw error; } }, diff --git a/api/so/sprk/notification/updateSeen.ts b/api/so/sprk/notification/updateSeen.ts index 75ed3be..19aeb3f 100644 --- a/api/so/sprk/notification/updateSeen.ts +++ b/api/so/sprk/notification/updateSeen.ts @@ -25,7 +25,7 @@ export default function (server: Server, ctx: AppContext) { // Reset badge count on iOS devices // Fire and forget - don't block the response ctx.pushService.sendBadgeReset(viewer).catch((err) => { - ctx.logger.error("Failed to send badge reset", { err, viewer }); + console.error("Failed to send badge reset", { err, viewer }); }); }, }); diff --git a/context.ts b/context.ts index bb02518..5099929 100644 --- a/context.ts +++ b/context.ts @@ -1,4 +1,3 @@ -import { Logger } from "@logtape/logtape"; import { Database } from "./data-plane/db/index.ts"; import { DataPlane } from "./data-plane/index.ts"; import { Hydrator } from "./hydration/index.ts"; @@ -14,7 +13,6 @@ export type AppContext = { dataplane: DataPlane; hydrator: Hydrator; views: Views; - logger: Logger; idResolver: IdResolver; authVerifier: AuthVerifier; cfg: ServerConfig; diff --git a/data-plane/background.ts b/data-plane/background.ts index 067a5e4..8da74ed 100644 --- a/data-plane/background.ts +++ b/data-plane/background.ts @@ -1,6 +1,5 @@ import PQueue from "p-queue"; import { Database } from "./db/index.ts"; -import { Logger } from "@logtape/logtape"; // A simple queue for in-process, out-of-band/backgrounded work @@ -10,7 +9,7 @@ export class BackgroundQueue { private processAllInterval: number | null = null; private isProcessingAll = false; - constructor(public db: Database, public logger: Logger) {} + constructor(public db: Database) {} add(task: Task) { if (this.destroyed) { @@ -23,7 +22,7 @@ export class BackgroundQueue { if ( err.message?.includes("Client must be connected") && this.destroyed ) { - this.logger.debug( + console.debug( "Ignoring MongoDB connection error during shutdown", { err: err.message }, ); @@ -33,14 +32,14 @@ export class BackgroundQueue { // Check for MongoDB duplicate key errors const mongoError = err as { code?: number }; if (mongoError.code === 11000) { - this.logger.warn( + console.warn( "Ignoring duplicate key error in background task", { err: err.message }, ); return; } - this.logger.error("background queue task failed", { err }); + console.error("background queue task failed", { err }); }); } @@ -73,7 +72,7 @@ export class BackgroundQueue { await Promise.race([processPromise, timeoutPromise]); } catch (error) { - this.logger.error( + console.error( "Background queue processing failed or timed out", { error }, ); diff --git a/data-plane/db/index.ts b/data-plane/db/index.ts index edef037..87301d7 100644 --- a/data-plane/db/index.ts +++ b/data-plane/db/index.ts @@ -2,7 +2,6 @@ import mongoose, { Connection } from "mongoose"; import { IdResolver, MemoryCache } from "@atp/identity"; import * as models from "./models.ts"; import { getResultFromDoc } from "../util.ts"; -import { getLogger } from "@logtape/logtape"; import { ServerConfig } from "../../config.ts"; const HOUR = 60 * 60 * 1000; @@ -11,7 +10,7 @@ const DAY = HOUR * 24; export class Database { private connection!: Connection; public models!: models.DatabaseModels; - public logger = getLogger(["appview", "database"]); + public idResolver: IdResolver; constructor(private cfg: ServerConfig) { @@ -28,7 +27,7 @@ export class Database { if (!uri) { throw new Error("No database URI provided"); } - this.logger.info(`Connecting to ${uri}`); + console.info(`Connecting to ${uri}`); try { this.connection = mongoose.createConnection(uri, { @@ -41,13 +40,13 @@ export class Database { // Attach basic listeners for visibility this.connection.on("connected", () => { - this.logger.info("MongoDB connection established"); + console.info("MongoDB connection established"); }); this.connection.on("disconnected", () => { - this.logger.warn("MongoDB connection disconnected"); + console.warn("MongoDB connection disconnected"); }); this.connection.on("error", (err) => { - this.logger.error("MongoDB connection error", { err }); + console.error("MongoDB connection error", { err }); }); // Initialize models @@ -150,9 +149,9 @@ export class Database { ), }; - this.logger.info("Started connection to MongoDB"); + console.info("Started connection to MongoDB"); } catch (error) { - this.logger.error("Failed to start connection to MongoDB", { error }); + console.error("Failed to start connection to MongoDB", { error }); throw error; } } @@ -160,7 +159,7 @@ export class Database { async disconnect(): Promise { if (this.connection) { await this.connection.close(); - this.logger.info("Disconnected from MongoDB"); + console.info("Disconnected from MongoDB"); } } @@ -177,7 +176,7 @@ export class Database { try { return await this.idResolver.handle.resolve(handle); } catch (err) { - this.logger.error("Failed to resolve handle", { err, handle }); + console.error("Failed to resolve handle", { err, handle }); return undefined; } } @@ -192,7 +191,7 @@ export class Database { handle: data.handle, }; } catch (err) { - this.logger.error("Failed to resolve DID", { err, did }); + console.error("Failed to resolve DID", { err, did }); return undefined; } } @@ -215,7 +214,7 @@ export class Database { }); return cursorState?.cursorValue || null; } catch (error) { - this.logger.error("Failed to get cursor state", { error }); + console.error("Failed to get cursor state", { error }); return null; } } @@ -231,7 +230,7 @@ export class Database { { upsert: true }, ); } catch (error) { - this.logger.error( + console.error( "Failed to save cursor state", { error, cursorPosition }, ); diff --git a/data-plane/index.ts b/data-plane/index.ts index 4696daa..81c7938 100644 --- a/data-plane/index.ts +++ b/data-plane/index.ts @@ -1,6 +1,5 @@ import { IdResolver } from "@atp/identity"; import { Database } from "./db/index.ts"; -import { getLogger, Logger } from "@logtape/logtape"; import { Blocks } from "./routes/blocks.ts"; import { FeedGens } from "./routes/feed-gens.ts"; import { Feeds } from "./routes/feeds.ts"; @@ -32,7 +31,6 @@ export type ServerContext = { export class DataPlane { private db: Database; - public logger: Logger; private idResolver?: IdResolver; // Route handlers as root-level properties @@ -64,7 +62,6 @@ export class DataPlane { ) { this.db = db; this.idResolver = idResolver; - this.logger = getLogger(["appview", "data-plane"]); // Initialize all route handlers this.blocks = new Blocks(db); diff --git a/data-plane/indexing/index.ts b/data-plane/indexing/index.ts index d87c248..56056a2 100644 --- a/data-plane/indexing/index.ts +++ b/data-plane/indexing/index.ts @@ -27,7 +27,6 @@ import * as Story from "./plugins/story.ts"; import * as Audio from "./plugins/audio.ts"; import * as Labeler from "./plugins/labeler.ts"; import { RecordProcessor } from "./processor.ts"; -import { getLogger, Logger } from "@logtape/logtape"; import { ServerConfig } from "../../config.ts"; import { PushService } from "../../utils/push.ts"; @@ -45,7 +44,6 @@ export class IndexingService { audio: Audio.PluginType; labeler: Labeler.PluginType; }; - logger: Logger; private pushService?: PushService; constructor( @@ -55,7 +53,6 @@ export class IndexingService { public background: BackgroundQueue, pushService?: PushService, ) { - this.logger = getLogger(["appview", "indexer"]); this.pushService = pushService; this.records = { post: Post.makePlugin(this.db, this.background), @@ -143,7 +140,7 @@ export class IndexingService { ); } catch (err) { // Log the error but don't throw - this prevents the firehose from crashing - this.logger.warn( + console.warn( "Failed to index handle, skipping", { err, did, timestamp }, ); @@ -157,7 +154,7 @@ export class IndexingService { { upsert: true, new: true }, ); } catch (dbErr) { - this.logger.error( + console.error( "Failed to update actor record after handle resolution failure", { err: dbErr, did }, ); @@ -170,7 +167,7 @@ export class IndexingService { const actorExists = await this.db.models.Actor.findOne({ did }).lean(); if (!actorExists) { - this.logger.info( + console.info( `indexRepo: No actor record found for ${did}, indexing handle first`, ); await this.indexHandle(did, now); @@ -192,7 +189,7 @@ export class IndexingService { const repoRecords = formatCheckout(did, verifiedRepo); const diff = findDiffFromCheckout(currRecords, repoRecords); - this.logger.info(`Indexing ${diff.length} records for ${did}:`); + console.info(`Indexing ${diff.length} records for ${did}:`); await Promise.all( diff.map(async (op) => { @@ -212,12 +209,12 @@ export class IndexingService { } } catch (err) { if (err instanceof ValidationError) { - this.logger.warn( + console.warn( "skipping indexing of invalid record", { did, commit, uri: uri.toString(), cid: cid.toString() }, ); } else { - this.logger.error( + console.error( "skipping indexing due to error processing record", { err, did, commit, uri: uri.toString(), cid: cid.toString() }, ); @@ -304,7 +301,7 @@ export class IndexingService { return null; } } catch (err) { - this.logger.warn( + console.warn( "Failed to check if actor is hosted, assuming not hosted", { err, did }, ); diff --git a/data-plane/subscription.ts b/data-plane/subscription.ts index 2cd08eb..4bb2342 100644 --- a/data-plane/subscription.ts +++ b/data-plane/subscription.ts @@ -4,7 +4,6 @@ import { Event as FirehoseEvent, Firehose, MemoryRunner } from "@atp/sync"; import { BackgroundQueue } from "./background.ts"; import { Database } from "./db/index.ts"; import { IndexingService } from "./indexing/index.ts"; -import { getLogger, Logger } from "@logtape/logtape"; import { ServerConfig } from "../config.ts"; import { PushService } from "../utils/push.ts"; import { PushTokens } from "./routes/push-tokens.ts"; @@ -14,7 +13,6 @@ export class RepoSubscription { runner: MemoryRunner; background: BackgroundQueue; indexingSvc: IndexingService; - logger: Logger; pushService: PushService; private firehoseRunning = false; @@ -27,8 +25,7 @@ export class RepoSubscription { }, ) { const { db, idResolver, startCursor, cfg } = opts; - this.logger = getLogger(["appview", "subscription"]); - this.background = new BackgroundQueue(db, this.logger); + this.background = new BackgroundQueue(db); // Create push service (FCM handles both iOS and Android) const pushTokens = new PushTokens(db); @@ -49,7 +46,6 @@ export class RepoSubscription { idResolver, service: cfg.relayUrl, indexingSvc: this.indexingSvc, - logger: this.logger, db, startCursor, }); @@ -58,7 +54,7 @@ export class RepoSubscription { } start() { - this.logger.info("Starting firehose subscription"); + console.info("Starting firehose subscription"); this.firehoseRunning = true; this.firehose.start(); } @@ -74,7 +70,6 @@ export class RepoSubscription { idResolver: this.opts.idResolver, service: this.opts.cfg.relayUrl, indexingSvc: this.indexingSvc, - logger: this.logger, db: this.opts.db, startCursor, }); @@ -94,7 +89,7 @@ export class RepoSubscription { await this.firehose.destroy(); this.firehoseRunning = false; } - this.logger.info("Processing remaining runner tasks..."); + console.info("Processing remaining runner tasks..."); if (this.opts.cfg.debugMode) { const timeoutMs = 10000; // Runner destroy with timeout and proper timer cleanup @@ -108,7 +103,7 @@ export class RepoSubscription { }); await Promise.race([this.runner.destroy(), timeoutPromise]); } catch (e) { - this.logger.warn("Runner destroy timed out; continuing shutdown", { + console.warn("Runner destroy timed out; continuing shutdown", { e, }); } finally { @@ -128,7 +123,7 @@ export class RepoSubscription { }); await Promise.race([this.background.processAll(), timeoutPromise]); } catch (e) { - this.logger.warn("Runner destroy timed out; continuing shutdown", { + console.warn("Runner destroy timed out; continuing shutdown", { e, }); } finally { @@ -142,7 +137,7 @@ export class RepoSubscription { await this.background.processAll(); } } catch (error) { - this.logger.error("Error during subscription destroy", { error }); + console.error("Error during subscription destroy", { error }); throw error; } } @@ -152,25 +147,24 @@ function createFirehose(opts: { idResolver: IdResolver; service?: string; indexingSvc: IndexingService; - logger: Logger; db: Database; startCursor?: number; }): { firehose: Firehose; runner: MemoryRunner } { - const { idResolver, service, indexingSvc, logger, db, startCursor } = opts; + const { idResolver, service, indexingSvc, db, startCursor } = opts; const runner = new MemoryRunner({ startCursor, setCursorInterval: 30000, // Save cursor every 30 seconds setCursor: async (cursor: number) => { await db.saveCursorState(cursor); - logger.info("Cursor saved to database", { cursor }); + console.info("Cursor saved to database", { cursor }); }, }); const firehose = new Firehose({ idResolver, runner, service, - onError: (err: Error) => logger.error("error in subscription", { err }), + onError: (err: Error) => console.error("error in subscription", { err }), handleEvent: async (evt: FirehoseEvent) => { if (evt.event === "identity") { await indexingSvc.indexHandle(evt.did, evt.time, true); diff --git a/deno.json b/deno.json index e4e0a71..4bc3d19 100644 --- a/deno.json +++ b/deno.json @@ -17,21 +17,19 @@ "@atp/identity": "jsr:@atp/identity@^0.1.0-alpha.2", "@atp/lexicon": "jsr:@atp/lexicon@^0.1.0-alpha.4", "@atp/repo": "jsr:@atp/repo@^0.1.0-alpha.5", - "@atp/sync": "jsr:@atp/sync@^0.1.0-alpha.8", + "@atp/sync": "jsr:@atp/sync@^0.1.0-alpha.9", "@atp/syntax": "jsr:@atp/syntax@^0.1.0-alpha.2", "@atp/xrpc": "jsr:@atp/xrpc@^0.1.0-alpha.4", "@atp/xrpc-server": "jsr:@atp/xrpc-server@^0.1.0-alpha.9", - "@logtape/logtape": "jsr:@logtape/logtape@^1.3.7", - "@logtape/pretty": "jsr:@logtape/pretty@^1.3.7", "@std/assert": "jsr:@std/assert@^1.0.18", "dotenv": "npm:dotenv@^17.2.4", "hono": "jsr:@hono/hono@^4.11.9", "@std/encoding": "jsr:@std/encoding@^1.0.10", - "@atproto/api": "npm:@atproto/api@^0.16.11", + "@atproto/api": "npm:@atproto/api@^0.18.21", "jose": "npm:jose@^6.1.3", "mongoose": "npm:mongoose@^8.23.0", "multiformats": "npm:multiformats@^13.4.2", - "p-queue": "npm:p-queue@^8.1.1", + "p-queue": "npm:p-queue@^9.1.0", "mongodb-memory-server-core": "npm:mongodb-memory-server-core@^11.0.1", "structured-headers": "npm:structured-headers@^2.0.2" }, diff --git a/deno.lock b/deno.lock index 618fea4..3e67f7d 100644 --- a/deno.lock +++ b/deno.lock @@ -8,17 +8,15 @@ "jsr:@atp/identity@~0.1.0-alpha.2": "0.1.0-alpha.2", "jsr:@atp/lexicon@~0.1.0-alpha.4": "0.1.0-alpha.4", "jsr:@atp/repo@~0.1.0-alpha.5": "0.1.0-alpha.5", - "jsr:@atp/sync@~0.1.0-alpha.8": "0.1.0-alpha.8", + "jsr:@atp/sync@~0.1.0-alpha.9": "0.1.0-alpha.9", "jsr:@atp/syntax@~0.1.0-alpha.2": "0.1.0-alpha.2", "jsr:@atp/xrpc-server@~0.1.0-alpha.9": "0.1.0-alpha.9", "jsr:@atp/xrpc@~0.1.0-alpha.4": "0.1.0-alpha.4", "jsr:@hono/hono@^4.10.8": "4.11.9", "jsr:@hono/hono@^4.11.9": "4.11.9", - "jsr:@logtape/file@^1.2.2": "1.3.5", + "jsr:@logtape/file@^1.2.2": "1.3.7", "jsr:@logtape/logtape@^1.2.2": "1.3.7", - "jsr:@logtape/logtape@^1.3.5": "1.3.7", "jsr:@logtape/logtape@^1.3.7": "1.3.7", - "jsr:@logtape/pretty@^1.3.7": "1.3.7", "jsr:@noble/curves@^2.0.1": "2.0.1", "jsr:@noble/hashes@2": "2.0.1", "jsr:@noble/hashes@^2.0.1": "2.0.1", @@ -27,15 +25,15 @@ "jsr:@std/bytes@^1.0.6": "1.0.6", "jsr:@std/cbor@~0.1.9": "0.1.9", "jsr:@std/encoding@^1.0.10": "1.0.10", - "jsr:@std/fs@^1.0.20": "1.0.21", + "jsr:@std/fs@^1.0.20": "1.0.22", "jsr:@std/internal@^1.0.12": "1.0.12", - "jsr:@std/streams@^1.0.14": "1.0.16", - "jsr:@zod/zod@^4.1.13": "4.2.1", - "npm:@atproto/api@~0.16.11": "0.16.11", + "jsr:@std/streams@^1.0.14": "1.0.17", + "jsr:@zod/zod@^4.1.13": "4.3.6", + "npm:@atproto/api@~0.18.21": "0.18.21", "npm:@atproto/sync@*": "0.1.39", "npm:@bufbuild/protobuf@1.5.0": "1.5.0", "npm:@ipld/dag-cbor@^9.2.5": "9.2.5", - "npm:@types/node@24.0.7": "24.0.7", + "npm:@opentelemetry/api@^1.9.0": "1.9.0", "npm:dotenv@^17.2.4": "17.2.4", "npm:jose@^6.1.3": "6.1.3", "npm:lodash@*": "4.17.21", @@ -44,6 +42,7 @@ "npm:multiformats@^13.4.1": "13.4.2", "npm:multiformats@^13.4.2": "13.4.2", "npm:p-queue@^8.1.1": "8.1.1", + "npm:p-queue@^9.1.0": "9.1.0", "npm:rate-limiter-flexible@9": "9.1.1", "npm:structured-headers@^2.0.2": "2.0.2" }, @@ -106,8 +105,8 @@ "npm:multiformats@^13.4.1" ] }, - "@atp/sync@0.1.0-alpha.8": { - "integrity": "c471fef8fd3e2ab16a565791700967df0b48316e894e005769d4269e3db12dbf", + "@atp/sync@0.1.0-alpha.9": { + "integrity": "7a2c84f69bafc80cf705db7921a7aa12a659d4f82e187b5403be7bf426d28536", "dependencies": [ "jsr:@atp/common@~0.1.0-alpha.9", "jsr:@atp/identity", @@ -115,8 +114,9 @@ "jsr:@atp/repo", "jsr:@atp/syntax", "jsr:@atp/xrpc-server", + "npm:@opentelemetry/api", "npm:multiformats@^13.4.1", - "npm:p-queue" + "npm:p-queue@^8.1.1" ] }, "@atp/syntax@0.1.0-alpha.2": { @@ -149,22 +149,15 @@ "@hono/hono@4.11.9": { "integrity": "c82c6b846abc3c1879d921d8365287d77cdef8073019f509ff80bf53033bdcba" }, - "@logtape/file@1.3.5": { - "integrity": "6e5248e873e260109267b79bd3fb19f307a664a2233c5ae6f699d697549db985", + "@logtape/file@1.3.7": { + "integrity": "8cacd752ac49671135e80abc8cf4a843c377ab80906d075ece0e9105fc24677e", "dependencies": [ - "jsr:@logtape/logtape@^1.3.5" + "jsr:@logtape/logtape@^1.3.7" ] }, "@logtape/logtape@1.3.7": { "integrity": "d9dc1f8c7e2e1e4e3998006ea84eaf4054e40ad39325b056b3f517c013286bed" }, - "@logtape/pretty@1.3.7": { - "integrity": "f13f1e151158d76e5b8e352b7d1a6308bf3a65d14d70f50703f8f2fca125250c", - "dependencies": [ - "jsr:@logtape/logtape@^1.3.7", - "npm:@types/node" - ] - }, "@noble/curves@2.0.1": { "integrity": "21ef41d207a203f60ba37a4fdcbc4f4a545b10c5dab7f293889f18292f81ab23", "dependencies": [ @@ -196,22 +189,31 @@ "@std/fs@1.0.21": { "integrity": "d720fe1056d78d43065a4d6e0eeb2b19f34adb8a0bc7caf3a4dbf1d4178252cd" }, + "@std/fs@1.0.22": { + "integrity": "de0f277a58a867147a8a01bc1b181d0dfa80bfddba8c9cf2bacd6747bcec9308" + }, "@std/internal@1.0.12": { "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" }, "@std/streams@1.0.16": { "integrity": "85030627befb1767c60d4f65cb30fa2f94af1d6ee6e5b2515b76157a542e89c4" }, + "@std/streams@1.0.17": { + "integrity": "7859f3d9deed83cf4b41f19223d4a67661b3d3819e9fc117698f493bf5992140" + }, "@zod/zod@4.2.1": { "integrity": "693a557fccaf73bfcbcd132ca286929f3343cda9efb56e9780985aa41d229b38" + }, + "@zod/zod@4.3.6": { + "integrity": "7144e5e11f8ffc3cf6e2fca624f6597a8762898aac9868cc8938e9398b96ffe4" } }, "npm": { - "@atproto/api@0.16.11": { - "integrity": "sha512-1dhfQNHiclb102RW+Ea8Nft5olfqU0Ev/vlQaSX6mWNo1aP5zT+sPODJ8+BTUOYk3vcuvL7QMkqA/rLYy2PMyw==", + "@atproto/api@0.18.21": { + "integrity": "sha512-s35MIJerGT/pKe2xJtKKswqlIr/ola2r2iURBKBL0Mk1OKe6jP4YvTMh1N2d2PEANFzNNTbKoDaLfJPo2Uvc/w==", "dependencies": [ "@atproto/common-web", - "@atproto/lexicon@0.5.1", + "@atproto/lexicon", "@atproto/syntax", "@atproto/xrpc", "await-lock", @@ -220,10 +222,10 @@ "zod" ] }, - "@atproto/common-web@0.4.15": { - "integrity": "sha512-A4l9gyqUNez8CjZp/Trypz/D3WIQsNj8dN05WR6+RoBbvwc9JhWjKPrm+WoVYc/F16RPdXHLkE3BEJlGIyYIiA==", + "@atproto/common-web@0.4.16": { + "integrity": "sha512-Ufvaff5JgxUyUyTAG0/3o7ltpy3lnZ1DvLjyAnvAf+hHfiK7OMQg+8byr+orN+KP9MtIQaRTsCgYPX+PxMKUoA==", "dependencies": [ - "@atproto/lex-data", + "@atproto/lex-data@0.0.11", "@atproto/lex-json", "@atproto/syntax", "zod" @@ -234,7 +236,7 @@ "dependencies": [ "@atproto/common-web", "@atproto/lex-cbor", - "@atproto/lex-data", + "@atproto/lex-data@0.0.10", "iso-datestring-validator", "multiformats@9.9.0", "pino" @@ -258,7 +260,7 @@ "@atproto/lex-cbor@0.0.10": { "integrity": "sha512-5RtV90iIhRNCXXvvETd3KlraV8XGAAAgOmiszUb+l8GySDU/sGk7AlVvArFfXnj/S/GXJq8DP6IaUxCw/sPASA==", "dependencies": [ - "@atproto/lex-data", + "@atproto/lex-data@0.0.10", "tslib" ] }, @@ -271,21 +273,20 @@ "unicode-segmenter" ] }, - "@atproto/lex-json@0.0.10": { - "integrity": "sha512-L6MyXU17C5ODMeob8myQ2F3xvgCTvJUtM0ew8qSApnN//iDasB/FDGgd7ty4UVNmx4NQ/rtvz8xV94YpG6kneQ==", + "@atproto/lex-data@0.0.11": { + "integrity": "sha512-4+KTtHdqwlhiTKA7D4SACea4jprsNpCQsNALW09wsZ6IHhCDGO5tr1cmV+QnLYe3G3mu1E1yXHXbPUHrUUDT/A==", "dependencies": [ - "@atproto/lex-data", - "tslib" + "multiformats@9.9.0", + "tslib", + "uint8arrays", + "unicode-segmenter" ] }, - "@atproto/lexicon@0.5.1": { - "integrity": "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==", + "@atproto/lex-json@0.0.11": { + "integrity": "sha512-2IExAoQ4KsR5fyPa1JjIvtR316PvdgRH/l3BVGLBd3cSxM3m5MftIv1B6qZ9HjNiK60SgkWp0mi9574bTNDhBQ==", "dependencies": [ - "@atproto/common-web", - "@atproto/syntax", - "iso-datestring-validator", - "multiformats@9.9.0", - "zod" + "@atproto/lex-data@0.0.11", + "tslib" ] }, "@atproto/lexicon@0.6.1": { @@ -304,7 +305,7 @@ "@atproto/common", "@atproto/common-web", "@atproto/crypto", - "@atproto/lexicon@0.6.1", + "@atproto/lexicon", "@ipld/dag-cbor@7.0.3", "multiformats@9.9.0", "uint8arrays", @@ -317,7 +318,7 @@ "dependencies": [ "@atproto/common", "@atproto/identity", - "@atproto/lexicon@0.6.1", + "@atproto/lexicon", "@atproto/repo", "@atproto/syntax", "@atproto/xrpc-server", @@ -345,8 +346,8 @@ "@atproto/common", "@atproto/crypto", "@atproto/lex-cbor", - "@atproto/lex-data", - "@atproto/lexicon@0.6.1", + "@atproto/lex-data@0.0.10", + "@atproto/lexicon", "@atproto/ws-client", "@atproto/xrpc", "express", @@ -360,7 +361,7 @@ "@atproto/xrpc@0.7.7": { "integrity": "sha512-K1ZyO/BU8JNtXX5dmPp7b5UrkLMMqpsIa/Lrj5D3Su+j1Xwq1m6QJ2XJ1AgjEjkI1v4Muzm7klianLE6XGxtmA==", "dependencies": [ - "@atproto/lexicon@0.6.1", + "@atproto/lexicon", "zod" ] }, @@ -396,11 +397,8 @@ "@noble/hashes@1.8.0": { "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==" }, - "@types/node@24.0.7": { - "integrity": "sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==", - "dependencies": [ - "undici-types" - ] + "@opentelemetry/api@1.9.0": { + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" }, "@types/webidl-conversions@7.0.3": { "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" @@ -936,6 +934,13 @@ "p-timeout@6.1.4" ] }, + "p-queue@9.1.0": { + "integrity": "sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==", + "dependencies": [ + "eventemitter3@5.0.4", + "p-timeout@7.0.1" + ] + }, "p-timeout@3.2.0": { "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", "dependencies": [ @@ -945,6 +950,9 @@ "p-timeout@6.1.4": { "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==" }, + "p-timeout@7.0.1": { + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==" + }, "p-try@2.2.0": { "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, @@ -1190,8 +1198,8 @@ "real-require" ] }, - "tlds@1.260.0": { - "integrity": "sha512-78+28EWBhCEE7qlyaHA9OR3IPvbCLiDh3Ckla593TksfFc9vfTsgvH7eS+dr3o9qr31gwGbogcI16yN91PoRjQ==", + "tlds@1.261.0": { + "integrity": "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==", "bin": true }, "toidentifier@1.0.1": { @@ -1219,9 +1227,6 @@ "multiformats@9.9.0" ] }, - "undici-types@7.8.0": { - "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==" - }, "unicode-segmenter@0.14.5": { "integrity": "sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==" }, @@ -1269,22 +1274,20 @@ "jsr:@atp/identity@~0.1.0-alpha.2", "jsr:@atp/lexicon@~0.1.0-alpha.4", "jsr:@atp/repo@~0.1.0-alpha.5", - "jsr:@atp/sync@~0.1.0-alpha.8", + "jsr:@atp/sync@~0.1.0-alpha.9", "jsr:@atp/syntax@~0.1.0-alpha.2", "jsr:@atp/xrpc-server@~0.1.0-alpha.9", "jsr:@atp/xrpc@~0.1.0-alpha.4", "jsr:@hono/hono@^4.11.9", - "jsr:@logtape/logtape@^1.3.7", - "jsr:@logtape/pretty@^1.3.7", "jsr:@std/assert@^1.0.18", "jsr:@std/encoding@^1.0.10", - "npm:@atproto/api@~0.16.11", + "npm:@atproto/api@~0.18.21", "npm:dotenv@^17.2.4", "npm:jose@^6.1.3", "npm:mongodb-memory-server-core@^11.0.1", "npm:mongoose@^8.23.0", "npm:multiformats@^13.4.2", - "npm:p-queue@^8.1.1", + "npm:p-queue@^9.1.0", "npm:structured-headers@^2.0.2" ] } diff --git a/hydration/index.ts b/hydration/index.ts index 8cd7809..7791698 100644 --- a/hydration/index.ts +++ b/hydration/index.ts @@ -48,7 +48,7 @@ import { RecordInfo, urisByCollection, } from "./util.ts"; -import { getLogger } from "@logtape/logtape"; + import { LabelerAggs, Labelers, @@ -143,8 +143,6 @@ export type FollowBlocks = HydrationMap; export type BidirectionalBlocks = HydrationMap>; -const hydrationLogger = getLogger(["appview", "hydrator"]); - export class Hydrator { actor: ActorHydrator; feed: FeedHydrator; @@ -237,7 +235,7 @@ export class Hydrator { try { knownFollowers = await this.actor.getKnownFollowers(dids, ctx.viewer); } catch (err) { - hydrationLogger.error( + console.error( "Failed to get known followers for profiles", { err }, ); diff --git a/ingest.ts b/ingest.ts index 36b471e..b5ad1c3 100644 --- a/ingest.ts +++ b/ingest.ts @@ -2,12 +2,7 @@ import { RepoSubscription } from "./data-plane/subscription.ts"; import { IdResolver } from "@atp/identity"; import { ServerConfig } from "./config.ts"; import { Database } from "./data-plane/db/index.ts"; -import { getLogger } from "@logtape/logtape"; -import { configureLogger } from "./utils/logger.ts"; -await configureLogger(); - -const logger = getLogger(["ingester"]); const cfg = ServerConfig.readEnv(); const idResolver = new IdResolver({ plcUrl: cfg.plcUrl }); @@ -25,4 +20,4 @@ const sub = new RepoSubscription({ }); sub.start(); -logger.info("Subscription started"); +console.info("Subscription started"); diff --git a/main.ts b/main.ts index 2eaa696..01df80e 100644 --- a/main.ts +++ b/main.ts @@ -9,8 +9,6 @@ import wellKnown from "./api/well-known.ts"; import health from "./api/health.ts"; import { IdResolver, MemoryCache } from "@atp/identity"; import { DataPlane } from "./data-plane/index.ts"; -import { getLogger } from "@logtape/logtape"; -import { configureLogger } from "./utils/logger.ts"; import { Hydrator } from "./hydration/index.ts"; import { Views } from "./views/index.ts"; import { AppContext, AppEnv } from "./context.ts"; @@ -18,8 +16,6 @@ import { ServerConfig } from "./config.ts"; import { defaultLabelerHeader, parseLabelerHeader } from "./util.ts"; import { PushService } from "./utils/push.ts"; -await configureLogger(); - // Create app without starting services export function createApp(ctx: AppContext): Hono { const app = new Hono(); @@ -44,8 +40,6 @@ export function createApp(ctx: AppContext): Hono { // Setup function to create context and app export function setupApp(): { app: Hono; ctx: AppContext } { - // Setup logger and database - const appLogger = getLogger(["appview"]); const cfg = ServerConfig.readEnv(); const db = new Database(cfg); db.connect(); @@ -90,7 +84,6 @@ export function setupApp(): { app: Hono; ctx: AppContext } { dataplane, hydrator, views, - logger: appLogger, idResolver, cfg, authVerifier, @@ -111,20 +104,20 @@ export function startServer() { Deno.serve({ port, onListen: (info) => { - ctx.logger.info(`Server listening on ${info.hostname}:${info.port}`); + console.info(`Server listening on ${info.hostname}:${info.port}`); }, }, app.fetch); // Handle shutdown const shutdown = async (signal: string) => { - ctx.logger.info(`Received ${signal}; shutting down...`); + console.info(`Received ${signal}; shutting down...`); try { - ctx.logger.info("Disconnecting database..."); + console.info("Disconnecting database..."); await ctx.db.disconnect(); } catch (err) { - ctx.logger.error("Error disconnecting database during shutdown", { err }); + console.error("Error disconnecting database during shutdown", { err }); } - ctx.logger.info("Shutdown complete"); + console.info("Shutdown complete"); Deno.exit(0); }; diff --git a/tests/util.ts b/tests/util.ts index 7f04e30..9bb69e9 100644 --- a/tests/util.ts +++ b/tests/util.ts @@ -6,7 +6,6 @@ import { createApp } from "../main.ts"; import { AppContext, AppEnv } from "../context.ts"; import { Database } from "../data-plane/db/index.ts"; import { createAuthVerifier } from "../auth-verifier.ts"; -import { getLogger } from "@logtape/logtape"; import { DataPlane } from "../data-plane/index.ts"; import { Hydrator } from "../hydration/index.ts"; import { Views } from "../views/index.ts"; @@ -265,7 +264,6 @@ export function createMockContext( configOverrides: Partial = {}, ): AppContext { const cfg = new ServerConfig({ ...DEFAULT_TEST_CONFIG, ...configOverrides }); - const appLogger = getLogger(["appview"]); const idResolver = new IdResolver(); // Create mock database that doesn't actually connect @@ -298,7 +296,6 @@ export function createMockContext( dataplane, hydrator, views, - logger: appLogger, idResolver, cfg, authVerifier, @@ -319,7 +316,6 @@ export async function createTestContext( ): Promise<{ ctx: AppContext; cleanup: () => Promise }> { const testDb = await createTestDatabase(options); const cfg = new ServerConfig({ ...DEFAULT_TEST_CONFIG, ...configOverrides }); - const appLogger = getLogger(["appview"]); const idResolver = new IdResolver(); // Create a wrapper Database object that uses the test connection and models @@ -327,7 +323,6 @@ export async function createTestContext( connection: testDb.connection, models: testDb.models, idResolver, - logger: getLogger(["appview", "database"]), connect: () => Promise.resolve(), disconnect: async () => { await testDb.cleanup(); @@ -381,7 +376,6 @@ export async function createTestContext( dataplane, hydrator, views, - logger: appLogger, idResolver, cfg, authVerifier, diff --git a/utils/logger.ts b/utils/logger.ts deleted file mode 100644 index f54e285..0000000 --- a/utils/logger.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { configure, getConsoleSink } from "@logtape/logtape"; -import { getPrettyFormatter } from "@logtape/pretty"; - -export async function configureLogger() { - await configure({ - sinks: { - console: getConsoleSink({ - formatter: getPrettyFormatter({ - properties: true, - categoryStyle: "underline", - messageColor: "rgb(255, 255, 255)", - categoryColor: "rgb(255, 255, 255)", - messageStyle: "reset", - }), - }), - }, - loggers: [ - { category: "appview", lowestLevel: "info", sinks: ["console"] }, - { category: "ingester", lowestLevel: "info", sinks: ["console"] }, - { - category: ["logtape", "meta"], - lowestLevel: "error", - sinks: ["console"], - }, - ], - }); -} diff --git a/utils/push.ts b/utils/push.ts index 7ada648..2f5f1fe 100644 --- a/utils/push.ts +++ b/utils/push.ts @@ -1,4 +1,3 @@ -import { getLogger, Logger } from "@logtape/logtape"; import { jsonStringToLex } from "@atp/lexicon"; import { PushToken, PushTokens } from "../data-plane/routes/push-tokens.ts"; import { Database } from "../data-plane/db/index.ts"; @@ -23,7 +22,6 @@ interface FcmServiceAccount { } export class PushService { - private logger: Logger; private pushTokens: PushTokens; private db: Database; private config: PushConfig; @@ -32,7 +30,6 @@ export class PushService { private fcmServiceAccount: FcmServiceAccount | null = null; constructor(pushTokens: PushTokens, db: Database, config: PushConfig) { - this.logger = getLogger(["appview", "push"]); this.pushTokens = pushTokens; this.db = db; this.config = config; @@ -41,7 +38,7 @@ export class PushService { try { this.fcmServiceAccount = JSON.parse(config.fcmServiceAccount); } catch { - this.logger.error("Failed to parse FCM service account JSON"); + console.error("Failed to parse FCM service account JSON"); } } } @@ -72,7 +69,7 @@ export class PushService { invalidTokens.push(token.token); } } catch (err) { - this.logger.error("Failed to send push notification", { + console.error("Failed to send push notification", { err, platform: token.platform, did, @@ -83,7 +80,7 @@ export class PushService { // Clean up invalid tokens if (invalidTokens.length > 0) { await this.pushTokens.deleteInvalidTokens(invalidTokens); - this.logger.info("Removed invalid push tokens", { + console.info("Removed invalid push tokens", { count: invalidTokens.length, }); } @@ -117,7 +114,7 @@ export class PushService { invalidTokens.push(token.token); } } catch (err) { - this.logger.error("Failed to send badge reset", { + console.error("Failed to send badge reset", { err, did, }); @@ -148,7 +145,7 @@ export class PushService { const count = await this.db.models.Notification.countDocuments(filter); return count; } catch (err) { - this.logger.error("Failed to get unread count", { err, did }); + console.error("Failed to get unread count", { err, did }); return 1; // Default to 1 if we can't get the count } } @@ -213,7 +210,7 @@ export class PushService { ) { return false; } - this.logger.error("Badge reset FCM request failed", { + console.error("Badge reset FCM request failed", { error, status: response.status, }); @@ -221,7 +218,7 @@ export class PushService { return true; } catch (err) { - this.logger.error("Badge reset FCM request error", { err }); + console.error("Badge reset FCM request error", { err }); return true; } } @@ -232,7 +229,7 @@ export class PushService { badgeCount: number, ): Promise { if (!this.fcmServiceAccount) { - this.logger.warn("FCM service account not configured"); + console.warn("FCM service account not configured"); return true; // Don't mark as invalid if not configured } @@ -306,7 +303,7 @@ export class PushService { ) { return false; // Mark as invalid } - this.logger.error("FCM request failed", { + console.error("FCM request failed", { error, status: response.status, }); @@ -314,7 +311,7 @@ export class PushService { return true; } catch (err) { - this.logger.error("FCM request error", { err }); + console.error("FCM request error", { err }); return true; // Don't mark as invalid on network errors } } @@ -465,7 +462,7 @@ export class PushService { }); if (!response.ok) { - this.logger.error("Failed to get FCM access token", { + console.error("Failed to get FCM access token", { status: response.status, }); return null; @@ -477,7 +474,7 @@ export class PushService { return this.fcmAccessToken; } catch (err) { - this.logger.error("Error getting FCM access token", { err }); + console.error("Error getting FCM access token", { err }); return null; } }