Skip to content

Commit 85ff892

Browse files
committed
chore(logging): some optional debug logging
yjs and editor update logging can be very verbose. Uncomment it but keep it disabled by default. Can be enabled by setting the corresponding key in OCA.Text - i.e. `window.OCA.Text.logWebSocketPolyfill = true` in the browser console. Signed-off-by: Max <max@nextcloud.com>
1 parent 925ca85 commit 85ff892

5 files changed

Lines changed: 56 additions & 21 deletions

File tree

src/components/Editor.vue

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -410,13 +410,13 @@ export default defineComponent({
410410
if (!val) {
411411
return
412412
}
413-
console.debug('Document is outdated')
413+
logger.debug('Document is outdated')
414414
if (this.dirty) {
415-
console.debug('There are local edits, need to resolve conflict')
415+
logger.debug('There are local edits, need to resolve conflict')
416416
// handle conflict between active editing session and offline content
417417
} else {
418418
// clear the outdated cached content and reload without it.
419-
console.debug(
419+
logger.debug(
420420
'No local edits... clearing storage and reloading the editor',
421421
)
422422
this.clearIndexedDb().then(() => {
@@ -442,8 +442,16 @@ export default defineComponent({
442442
created() {
443443
// The following can be useful for debugging ydoc updates
444444
this.ydoc.on('update', function (update, origin, doc, tr) {
445-
console.debug('ydoc update', update, origin, doc, tr)
446-
logUpdate(update)
445+
if (window.OCA.Text.logYjsUpdates) {
446+
logger.debug('ydoc update', {
447+
update,
448+
origin,
449+
doc,
450+
tr,
451+
content: doc.getXmlFragment('default').toJSON(),
452+
})
453+
logUpdate(update)
454+
}
447455
})
448456
this.$attachmentResolver = null
449457
if (this.active && this.hasDocumentParameters) {
@@ -452,6 +460,7 @@ export default defineComponent({
452460
}
453461
},
454462
async beforeDestroy() {
463+
logger.debug('beforeDestroy')
455464
if (!this.richWorkspace) {
456465
window.removeEventListener('beforeprint', this.preparePrinting)
457466
window.removeEventListener('afterprint', this.preparePrinting)
@@ -556,6 +565,7 @@ export default defineComponent({
556565
this.lowlightLoaded.then(() => {
557566
this.syncService.startSync()
558567
if (!documentState) {
568+
logger.debug('loading initial content', { content, isRichEditor: this.isRichEditor })
559569
setInitialYjsState(this.ydoc, content, {
560570
isRichEditor: this.isRichEditor,
561571
})
@@ -579,7 +589,9 @@ export default defineComponent({
579589
},
580590
581591
onUpdate({ editor }) {
582-
// this.debugContent(editor)
592+
if (window.OCA.Text.logEditorUpdates) {
593+
this.debugContent(editor)
594+
}
583595
const proseMirrorMarkdown = this.serialize()
584596
this.emit('update:content', {
585597
markdown: proseMirrorMarkdown,
@@ -651,7 +663,6 @@ export default defineComponent({
651663
if (Object.prototype.hasOwnProperty.call(state, 'dirty')) {
652664
// ignore initial loading and other automated changes before first user change
653665
if (this.editor.can().undo() || this.editor.can().redo()) {
654-
console.debug('Setting dirty to', state.dirty)
655666
this.setDirty(state.dirty)
656667
if (this.dirty) {
657668
this.saveService.autosave()
@@ -707,6 +718,7 @@ export default defineComponent({
707718
},
708719
709720
async disconnect() {
721+
logger.debug('disconnecting')
710722
await this.syncService.close()
711723
this.unlistenSyncServiceEvents()
712724
this.syncProvider?.destroy()
@@ -715,11 +727,13 @@ export default defineComponent({
715727
},
716728
717729
async close() {
730+
logger.debug('closing')
718731
await this.syncService
719732
.sendRemainingSteps()
720733
.catch((err) =>
721734
logger.warn('Failed to send remaining steps', { err }),
722735
)
736+
logger.debug('sent remaining steps')
723737
await this.disconnect().catch((err) =>
724738
logger.warn('Failed to disconnect', { err }),
725739
)
@@ -767,17 +781,18 @@ export default defineComponent({
767781
* @param {object} editor The Tiptap editor
768782
*/
769783
debugContent(editor) {
784+
// markdown, serialized from editor state by prosemirror-markdown
770785
const proseMirrorMarkdown = this.serialize()
786+
// HTML, serialized from markdown by markdown-it
771787
const markdownItHtml = markdownit.render(proseMirrorMarkdown)
788+
// HTML, as rendered in the browser by Tiptap
789+
const tiptapHtml = editor.getHTML()
772790
773-
logger.debug(
774-
'markdown, serialized from editor state by prosemirror-markdown',
775-
)
776-
console.debug(proseMirrorMarkdown)
777-
logger.debug('HTML, serialized from markdown by markdown-it')
778-
console.debug(markdownItHtml)
779-
logger.debug('HTML, as rendered in the browser by Tiptap')
780-
console.debug(editor.getHTML())
791+
logger.debug('editor update', {
792+
proseMirrorMarkdown,
793+
markdownItHtml,
794+
tiptapHtml,
795+
})
781796
},
782797
783798
/**

src/composables/useIndexedDbProvider.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { readonly, ref } from 'vue'
77
import { IndexeddbPersistence } from 'y-indexeddb'
88
import type { Doc } from 'yjs'
9+
import { logger } from '../helpers/logger.js'
910

1011
/**
1112
* Initialize a indexed db provider for the given ydoc
@@ -21,8 +22,11 @@ export function useIndexedDbProvider(
2122
) {
2223
const name = `${props.fileId}`
2324
const indexedDbProvider = new IndexeddbPersistence(name, ydoc)
24-
indexedDbProvider.on('synced', (provider: IndexeddbPersistence) => {
25-
console.info('synced from indexeddb', provider)
25+
indexedDbProvider.on('synced', async (provider: IndexeddbPersistence) => {
26+
logger.info('synced from indexeddb', {
27+
dirty: await provider.get('dirty'),
28+
baseVersionEtag: await provider.get('baseVersionEtag'),
29+
})
2630
})
2731
const dirty = ref(false)
2832
indexedDbProvider.get('dirty').then((val) => {
@@ -58,6 +62,7 @@ export function useIndexedDbProvider(
5862
* Used to reset the browser state to load a new editing session.
5963
*/
6064
function clearIndexedDb() {
65+
logger.info('clearing indexeddb')
6166
return indexedDbProvider.clearData()
6267
}
6368

src/helpers/debug.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ if (!window.OCA.Text) {
1111
window.OCA.Text = {}
1212
}
1313

14+
// These can be changed in the browser console for more verbose logging.
15+
window.OCA.Text.logEditorUpdates = false
16+
window.OCA.Text.logWebSocketPolyfill = false
17+
window.OCA.Text.logYjsUpdates = false
18+
1419
const editorComponents = window.OCA.Text.editorComponents ?? new Set()
1520
window.OCA.Text.editorComponents = editorComponents
1621

src/services/WebSocketPolyfill.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import { stepsFromOpenData } from '../helpers/yjs'
1010
import getNotifyBus from './NotifyService'
1111
import type { Step, SyncService } from './SyncService'
1212

13+
// Optional debug logging if window.OCA.Text.logWebSocketPolyfill is set.
14+
const debug = (message: string, context: object) => {
15+
if (window.OCA.Text.logWebSocketPolyfill) {
16+
debug(message, context)
17+
}
18+
}
19+
1320
/**
1421
*
1522
* @param syncService - the sync service to build upon
@@ -35,9 +42,10 @@ export default function initWebSocketPolyfill(
3542
this.#notifyPushBus = getNotifyBus()
3643
this.#notifyPushBus?.on('notify_push', this.#onNotifyPush.bind(this))
3744
this.#url = url
38-
logger.debug('WebSocketPolyfill#constructor', { url, fileId })
45+
debug('WebSocketPolyfill#constructor', { url, fileId })
3946

4047
this.#onOpened = (data: OpenData) => {
48+
debug('WebSocketPolyfill#onOpen', { data })
4149
if (syncService.hasActiveConnection()) {
4250
this.onopen?.()
4351
}
@@ -46,9 +54,10 @@ export default function initWebSocketPolyfill(
4654
syncService.bus.on('opened', this.#onOpened)
4755

4856
this.#onSync = ({ steps }: { steps: Step[] }) => {
57+
debug('WebSocketPolyfill#onSync', { steps })
4958
if (steps) {
5059
this.#processSteps(steps)
51-
logger.debug('synced ', {
60+
debug('synced ', {
5261
version: syncService.version,
5362
steps,
5463
})
@@ -95,7 +104,7 @@ export default function initWebSocketPolyfill(
95104
// If `this.#processingVersion` is set, we're in the middle of applying steps of one version.
96105
// If `isSyncStep1`, Yjs failed to integrate a message due to pending structs.
97106
// Log and ask for recovery due to a not applied/missing step.
98-
console.error(`Failed to process step ${this.#processingVersion}.`, {
107+
logger.error(`Failed to process step ${this.#processingVersion}.`, {
99108
lastSuccessfullyProcessed: syncService.version,
100109
sendingSyncStep1: step,
101110
})
@@ -110,14 +119,15 @@ export default function initWebSocketPolyfill(
110119
syncService.bus.off('opened', this.#onOpened)
111120
this.#notifyPushBus?.off('notify_push', this.#onNotifyPush.bind(this))
112121
this.onclose?.(new CloseEvent('closing'))
113-
logger.debug('Websocket closed')
122+
debug('Websocket closed')
114123
}
115124

116125
#onNotifyPush({
117126
messageBody,
118127
}: {
119128
messageBody: { documentId: number; steps: string[] }
120129
}) {
130+
debug('WebSocketPolyfill#onNotifyPush', messageBody)
121131
if (messageBody.documentId !== fileId) {
122132
return
123133
}

0 commit comments

Comments
 (0)