Skip to content

Commit 462c19c

Browse files
committed
Simplify logger design
1 parent b8ee462 commit 462c19c

32 files changed

Lines changed: 335 additions & 217 deletions

packages/adapter-sql-js/src/SQLJSAdapter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ class SqlJsConnectionPool extends BaseObserver<DBAdapterListener> implements Con
123123
const SQL = await SQLJs({
124124
locateFile: (filename: any) => `../dist/${filename}`,
125125
print: (text) => {
126-
this.options.logger.log(LogLevels.info, text);
126+
this.options.logger.log({ level: LogLevels.info, message: text });
127127
},
128128
printErr: (text) => {
129-
this.options.logger.log(LogLevels.error, '[stderr]', text);
129+
this.options.logger.log({ level: LogLevels.error, message: `[stderr]: ${text}` });
130130
}
131131
});
132132
const existing = await this.options.persister?.readFile();

packages/attachments/src/AbstractAttachmentQueue.ts

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
127127
async watchAttachmentIds() {
128128
this.onAttachmentIdsChange(async (ids) => {
129129
const _ids = `${ids.map((id) => `'${id}'`).join(',')}`;
130-
this.logger.log(LogLevels.debug, `Queuing for sync, attachment IDs: [${_ids}]`);
130+
this.logger.log({ level: LogLevels.debug, message: `Queuing for sync, attachment IDs: [${_ids}]` });
131131

132132
if (this.initialSync) {
133133
this.initialSync = false;
@@ -155,14 +155,17 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
155155
id: id,
156156
state: AttachmentState.QUEUED_SYNC
157157
});
158-
this.logger.log(LogLevels.debug, `Attachment (${id}) not found in database, creating new record`);
158+
this.logger.log({
159+
level: LogLevels.debug,
160+
message: `Attachment (${id}) not found in database, creating new record`
161+
});
159162
await this.saveToQueue(newRecord);
160163
} else if (record.local_uri == null || !(await this.storage.fileExists(this.getLocalUri(record.local_uri)))) {
161164
// 2. Attachment in database but no local file, mark as queued download
162-
this.logger.log(
163-
LogLevels.debug,
164-
`Attachment (${id}) found in database but no local file, marking as queued download`
165-
);
165+
this.logger.log({
166+
level: LogLevels.debug,
167+
message: `Attachment (${id}) found in database but no local file, marking as queued download`
168+
});
166169
await this.update({
167170
...record,
168171
state: AttachmentState.QUEUED_DOWNLOAD
@@ -247,8 +250,8 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
247250
await this.storage.deleteFile(localFilePathUri, {
248251
filename: record.filename
249252
});
250-
} catch (e) {
251-
this.logger.log(LogLevels.error, e);
253+
} catch (error) {
254+
this.logger.log({ level: LogLevels.error, message: 'Error deleting attachment', error });
252255
}
253256
}
254257

@@ -274,7 +277,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
274277
const localFilePathUri = this.getLocalUri(record.local_uri);
275278
try {
276279
if (!(await this.storage.fileExists(localFilePathUri))) {
277-
this.logger.log(LogLevels.warn, `File for ${record.id} does not exist, skipping upload`);
280+
this.logger.log({ level: LogLevels.warn, message: `File for ${record.id} does not exist, skipping upload` });
278281
await this.update({
279282
...record,
280283
state: AttachmentState.QUEUED_DOWNLOAD
@@ -292,11 +295,11 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
292295
});
293296
// Mark as uploaded
294297
await this.update({ ...record, state: AttachmentState.SYNCED });
295-
this.logger.log(LogLevels.debug, `Uploaded attachment "${record.id}" to Cloud Storage`);
298+
this.logger.log({ level: LogLevels.debug, message: `Uploaded attachment "${record.id}" to Cloud Storage` });
296299
return true;
297300
} catch (e: any) {
298301
if (e.error == 'Duplicate') {
299-
this.logger.log(LogLevels.debug, `File already uploaded, marking ${record.id} as synced`);
302+
this.logger.log({ level: LogLevels.debug, message: `File already uploaded, marking ${record.id} as synced` });
300303
await this.update({ ...record, state: AttachmentState.SYNCED });
301304
return false;
302305
}
@@ -307,7 +310,10 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
307310
return true;
308311
}
309312
}
310-
this.logger.log(LogLevels.error, `UploadAttachment error for record ${JSON.stringify(record, null, 2)}`);
313+
this.logger.log({
314+
level: LogLevels.error,
315+
message: `UploadAttachment error for record ${JSON.stringify(record, null, 2)}`
316+
});
311317
return false;
312318
}
313319
}
@@ -321,7 +327,10 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
321327
}
322328
const localFilePathUri = this.getLocalUri(record.local_uri);
323329
if (await this.storage.fileExists(localFilePathUri)) {
324-
this.logger.log(LogLevels.debug, `Local file already downloaded, marking "${record.id}" as synced`);
330+
this.logger.log({
331+
level: LogLevels.debug,
332+
message: `Local file already downloaded, marking "${record.id}" as synced`
333+
});
325334
await this.update({ ...record, state: AttachmentState.SYNCED });
326335
return true;
327336
}
@@ -352,7 +361,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
352361
media_type: fileBlob.type,
353362
state: AttachmentState.SYNCED
354363
});
355-
this.logger.log(LogLevels.debug, `Downloaded attachment "${record.id}"`);
364+
this.logger.log({ level: LogLevels.debug, message: `Downloaded attachment "${record.id}"` });
356365
return true;
357366
} catch (e) {
358367
if (this.options.onDownloadError) {
@@ -362,7 +371,11 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
362371
return true;
363372
}
364373
}
365-
this.logger.log(LogLevels.error, `Download attachment error for record ${JSON.stringify(record, null, 2)}`, e);
374+
this.logger.log({
375+
level: LogLevels.error,
376+
message: `Download attachment error for record ${JSON.stringify(record, null, 2)}`,
377+
error: e
378+
});
366379
}
367380
return false;
368381
}
@@ -403,7 +416,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
403416
if (!record) {
404417
return;
405418
}
406-
this.logger.log(LogLevels.debug, `Uploading attachments...`);
419+
this.logger.log({ level: LogLevels.debug, message: `Uploading attachments...` });
407420
while (record) {
408421
const uploaded = await this.uploadAttachment(record);
409422
if (!uploaded) {
@@ -412,9 +425,9 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
412425
}
413426
record = await this.getNextUploadRecord();
414427
}
415-
this.logger.log(LogLevels.debug, 'Finished uploading attachments');
428+
this.logger.log({ level: LogLevels.debug, message: 'Finished uploading attachments' });
416429
} catch (error) {
417-
this.logger.log(LogLevels.error, 'Upload failed:', error);
430+
this.logger.log({ level: LogLevels.error, message: 'Upload failed:', error });
418431
} finally {
419432
this.uploading = false;
420433
}
@@ -471,7 +484,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
471484

472485
this.downloading = true;
473486
try {
474-
this.logger.log(LogLevels.debug, `Downloading ${this.downloadQueue.size} attachments...`);
487+
this.logger.log({ level: LogLevels.debug, message: `Downloading ${this.downloadQueue.size} attachments...` });
475488
while (this.downloadQueue.size > 0) {
476489
const id = this.downloadQueue.values().next().value;
477490
this.downloadQueue.delete(id);
@@ -481,9 +494,9 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
481494
}
482495
await this.downloadRecord(record);
483496
}
484-
this.logger.log(LogLevels.debug, 'Finished downloading attachments');
485-
} catch (e) {
486-
this.logger.log(LogLevels.error, 'Downloads failed:', e);
497+
this.logger.log({ level: LogLevels.debug, message: 'Finished downloading attachments' });
498+
} catch (error) {
499+
this.logger.log({ level: LogLevels.error, message: 'Downloads failed:', error });
487500
} finally {
488501
this.downloading = false;
489502
}
@@ -525,7 +538,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
525538
return;
526539
}
527540

528-
this.logger.log(LogLevels.debug, `Deleting ${res.length} attachments from cache...`);
541+
this.logger.log({ level: LogLevels.debug, message: `Deleting ${res.length} attachments from cache...` });
529542
await this.powersync.writeTransaction(async (tx) => {
530543
for (const record of res) {
531544
await this.delete(record, tx);
@@ -534,7 +547,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
534547
}
535548

536549
async clearQueue(): Promise<void> {
537-
this.logger.log(LogLevels.debug, `Clearing attachment queue...`);
550+
this.logger.log({ level: LogLevels.debug, message: `Clearing attachment queue...` });
538551
await this.powersync.writeTransaction(async (tx) => {
539552
await tx.execute(`DELETE FROM ${this.table}`);
540553
});

packages/capacitor/src/PowerSyncDatabase.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ export class PowerSyncDatabase extends WebPowerSyncDatabase {
3838
? SyncStreamConnectionMethod.HTTP
3939
: DEFAULT_STREAM_CONNECTION_OPTIONS.connectionMethod;
4040
if (options?.connectionMethod == SyncStreamConnectionMethod.WEB_SOCKET && isUsingCapacitorDriver) {
41-
this.logger.log(
42-
LogLevels.warn,
43-
`Connecting via 'SyncStreamConnectionMethod.WEB_SOCKET' when using the 'CapacitorSQLiteAdapter' will result in poor sync performance. Use 'SyncStreamConnectionMethod.HTTP' (the default for native) instead.`
44-
);
41+
this.logger.log({
42+
level: LogLevels.warn,
43+
message: `Connecting via 'SyncStreamConnectionMethod.WEB_SOCKET' when using the 'CapacitorSQLiteAdapter' will result in poor sync performance. Use 'SyncStreamConnectionMethod.HTTP' (the default for native) instead.`
44+
});
4545
}
4646

4747
return super.connect(connector, {
@@ -59,20 +59,23 @@ export class PowerSyncDatabase extends WebPowerSyncDatabase {
5959
const platform = Capacitor.getPlatform();
6060
if (platform == 'ios' || platform == 'android') {
6161
if (options.database.dbLocation) {
62-
options.logger?.log(
63-
LogLevels.warn,
64-
`
62+
options.logger?.log({
63+
level: LogLevels.warn,
64+
message: `
6565
dbLocation is ignored on iOS and Android platforms.
6666
The database directory can be configured in the Capacitor project.
6767
See https://github.com/capacitor-community/sqlite?tab=readme-ov-file#installation`
68-
);
68+
});
6969
}
70-
options.logger?.log(LogLevels.debug, `Using CapacitorSQLiteAdapter for platform: ${platform}`);
70+
options.logger?.log({
71+
level: LogLevels.debug,
72+
message: `Using CapacitorSQLiteAdapter for platform: ${platform}`
73+
});
7174
return new CapacitorSQLiteAdapter({
7275
...options.database
7376
});
7477
} else {
75-
options.logger?.log(LogLevels.debug, `Using default web adapter for web platform`);
78+
options.logger?.log({ level: LogLevels.debug, message: `Using default web adapter for web platform` });
7679
return super.openDBAdapter(options);
7780
}
7881
}
@@ -107,12 +110,12 @@ export class PowerSyncDatabase extends WebPowerSyncDatabase {
107110
if (this.isNativeCapacitorPlatform) {
108111
// We don't want to support multi-tab on mobile platforms.
109112
// We technically can, but it's not a common use case and requires additional work/testing.
110-
this.logger.log(LogLevels.debug, `Using Capacitor sync implementation`);
113+
this.logger.log({ level: LogLevels.debug, message: `Using Capacitor sync implementation` });
111114
if (this.options.flags?.enableMultiTabs) {
112-
this.logger.log(
113-
LogLevels.warn,
114-
`enableMultiTabs is not supported on Capacitor mobile platforms. Ignoring the flag.`
115-
);
115+
this.logger.log({
116+
level: LogLevels.warn,
117+
message: `enableMultiTabs is not supported on Capacitor mobile platforms. Ignoring the flag.`
118+
});
116119
}
117120

118121
const remote = new CapacitorRemote(connector, this.logger);
@@ -132,7 +135,7 @@ export class PowerSyncDatabase extends WebPowerSyncDatabase {
132135
subscriptions: options.subscriptions
133136
});
134137
} else {
135-
this.logger.log(LogLevels.debug, `Using default web sync implementation for web platform`);
138+
this.logger.log({ level: LogLevels.debug, message: `Using default web sync implementation for web platform` });
136139
return super.generateSyncStreamImplementation(connector, options);
137140
}
138141
}

packages/common/src/attachments/AttachmentContext.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ export class AttachmentContext {
233233
if (archivedAttachments.length === 0) return false;
234234

235235
await callback?.(archivedAttachments);
236-
this.logger.log(
237-
LogLevels.info,
238-
`Deleting ${archivedAttachments.length} archived attachments. Archived attachment exceeds cache archiveCacheLimit of ${this.archivedCacheLimit}.`
239-
);
236+
this.logger.log({
237+
level: LogLevels.info,
238+
message: `Deleting ${archivedAttachments.length} archived attachments. Archived attachment exceeds cache archiveCacheLimit of ${this.archivedCacheLimit}.`
239+
});
240240

241241
const ids = archivedAttachments.map((attachment) => attachment.id);
242242

@@ -255,7 +255,7 @@ export class AttachmentContext {
255255
[JSON.stringify(ids)]
256256
);
257257

258-
this.logger.log(LogLevels.info, `Deleted ${archivedAttachments.length} archived attachments`);
258+
this.logger.log({ level: LogLevels.info, message: `Deleted ${archivedAttachments.length} archived attachments` });
259259
return archivedAttachments.length < limit;
260260
}
261261

packages/common/src/attachments/AttachmentQueue.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export class AttachmentQueue {
190190
if (status.connected) {
191191
// Device came online, process attachments immediately
192192
this.syncStorage().catch((error) => {
193-
this.logger.log(LogLevels.error, 'Error syncing storage on connection:', error);
193+
this.logger.log({ level: LogLevels.error, message: 'Error syncing storage on connection:', error });
194194
});
195195
}
196196
}

packages/common/src/attachments/AttachmentService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class AttachmentService {
2828
* @returns Watch query that emits changes for queued uploads, downloads, and deletes
2929
*/
3030
watchActiveAttachments({ throttleMs }: { throttleMs?: number } = {}): DifferentialWatchedQuery<AttachmentRecord> {
31-
this.logger.log(LogLevels.info, 'Watching active attachments...');
31+
this.logger.log({ level: LogLevels.info, message: 'Watching active attachments...' });
3232
const watch = this.db
3333
.query<AttachmentRecord>({
3434
sql: /* sql */ `

packages/common/src/attachments/SyncingService.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export class SyncingService {
7575
* @throws Error if the attachment has no localUri
7676
*/
7777
async uploadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord> {
78-
this.logger.log(LogLevels.info, `Uploading attachment ${attachment.filename}`);
78+
this.logger.log({ level: LogLevels.info, message: `Uploading attachment ${attachment.filename}` });
7979
try {
8080
if (attachment.localUri == null) {
8181
throw new Error(`No localUri for attachment ${attachment.id}`);
@@ -111,7 +111,7 @@ export class SyncingService {
111111
* @returns Updated attachment record with local URI and new state
112112
*/
113113
async downloadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord> {
114-
this.logger.log(LogLevels.info, `Downloading attachment ${attachment.filename}`);
114+
this.logger.log({ level: LogLevels.info, message: `Downloading attachment ${attachment.filename}` });
115115
try {
116116
const fileData = await this.remoteStorage.downloadFile(attachment);
117117

@@ -183,7 +183,11 @@ export class SyncingService {
183183
try {
184184
await this.localStorage.deleteFile(attachment.localUri);
185185
} catch (error) {
186-
this.logger.log(LogLevels.error, 'Error deleting local file for archived attachment', error);
186+
this.logger.log({
187+
level: LogLevels.error,
188+
message: 'Error deleting local file for archived attachment',
189+
error
190+
});
187191
}
188192
}
189193
}

packages/common/src/client/AbstractPowerSyncDatabase.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
495495
try {
496496
schema.validate();
497497
} catch (ex) {
498-
this.logger.log(LogLevels.warn, 'Schema validation failed. Unexpected behaviour could occur', ex);
498+
this.logger.log({
499+
level: LogLevels.warn,
500+
message: 'Schema validation failed. Unexpected behaviour could occur',
501+
error: ex
502+
});
499503
}
500504
this._schema = schema;
501505

@@ -1079,7 +1083,10 @@ SELECT * FROM crud_entries;
10791083
* @param options Options for configuring watch behavior
10801084
*/
10811085
watchWithCallback(sql: string, parameters?: any[], handler?: WatchHandler, options?: SQLWatchOptions): void {
1082-
const { onResult, onError = (e: Error) => this.logger.log(LogLevels.error, e) } = handler ?? {};
1086+
const {
1087+
onResult,
1088+
onError = (e: Error) => this.logger.log({ level: LogLevels.error, message: 'Error in watch', error: e })
1089+
} = handler ?? {};
10831090
if (!onResult) {
10841091
throw new Error('onResult is required');
10851092
}
@@ -1240,7 +1247,10 @@ SELECT * FROM crud_entries;
12401247
* @returns A dispose function to stop watching for changes
12411248
*/
12421249
onChangeWithCallback(handler?: WatchOnChangeHandler, options?: SQLOnChangeOptions): () => void {
1243-
const { onChange, onError = (e: Error) => this.logger.log(LogLevels.error, e) } = handler ?? {};
1250+
const {
1251+
onChange,
1252+
onError = (e: Error) => this.logger.log({ level: LogLevels.error, message: 'error in onChange', error: e })
1253+
} = handler ?? {};
12441254
if (!onChange) {
12451255
throw new Error('onChange is required');
12461256
}

0 commit comments

Comments
 (0)