Просмотр исходного кода

Merge pull request #19531 from overleaf/mj-cite-key-analytics

[web] Add analytics for cite key searches

GitOrigin-RevId: f9215a6db8defb4d7c8356e997b671223cfcfb70
Mathias Jakobsen 2 лет назад
Родитель
Сommit
4eb88a6d1a
1 измененных файлов с 86 добавлено и 0 удалено
  1. 86 0
      services/web/frontend/js/features/source-editor/languages/latex/complete.ts

+ 86 - 0
services/web/frontend/js/features/source-editor/languages/latex/complete.ts

@@ -29,6 +29,7 @@ import {
 } from './completions/apply'
 } from './completions/apply'
 import { snippet } from './completions/data/environments'
 import { snippet } from './completions/data/environments'
 import { syntaxTree } from '@codemirror/language'
 import { syntaxTree } from '@codemirror/language'
+import { sendMBSampled } from '@/infrastructure/event-tracking'
 
 
 function blankCompletions(): Completions {
 function blankCompletions(): Completions {
   return {
   return {
@@ -206,6 +207,90 @@ export const bibKeyArgumentCompletionSource: CompletionSource =
     }
     }
   )
   )
 
 
+const debouncedCounter = (
+  debounceTime: number
+): {
+  debounceTime: number
+  counter: number
+  increment: () => void
+  reset: () => void
+} => {
+  let timeoutId = 0
+  let _counter = 0
+  return {
+    debounceTime,
+    get counter() {
+      return _counter
+    },
+    increment() {
+      if (timeoutId !== 0) {
+        clearTimeout(timeoutId)
+      }
+      timeoutId = window.setTimeout(() => {
+        _counter += 1
+        timeoutId = 0
+      }, debounceTime)
+    },
+    reset() {
+      clearTimeout(timeoutId)
+      _counter = 0
+      timeoutId = 0
+    },
+  }
+}
+
+const CITE_ANALYTICS_REPORT_TIMEOUT = 4000
+
+const analyticsSourceBuilder = (debounceTimes: number[]) => {
+  let timeoutId = 0
+  const counters = debounceTimes.map(debounceTime => {
+    if (debounceTime >= CITE_ANALYTICS_REPORT_TIMEOUT) {
+      throw new Error(
+        `Debounce time ${debounceTime} is greater than the report timeout ${CITE_ANALYTICS_REPORT_TIMEOUT}`
+      )
+    }
+    return debouncedCounter(debounceTime)
+  })
+
+  const incrementCounters = () => {
+    counters.forEach(counter => counter.increment())
+  }
+
+  const resetCounters = () => {
+    counters.forEach(counter => counter.reset())
+  }
+
+  const delayedReport = () => {
+    if (timeoutId !== 0) {
+      clearTimeout(timeoutId)
+    }
+    timeoutId = window.setTimeout(() => {
+      const result: Record<string, number> = {}
+      counters.forEach(debouncedCounter => {
+        result[`${debouncedCounter.debounceTime}ms`] = debouncedCounter.counter
+      })
+      sendMBSampled(
+        'cite-key-search',
+        { searchesForDebouncedTime: result },
+        0.01
+      )
+      timeoutId = 0
+      resetCounters()
+    }, CITE_ANALYTICS_REPORT_TIMEOUT)
+  }
+
+  return () => {
+    incrementCounters()
+    delayedReport()
+    return null
+  }
+}
+
+const citeKeyAnalyticsSource = makeMultipleArgumentCompletionSource(
+  ['BibKeyArgument'],
+  analyticsSourceBuilder([0, 100, 250, 500])
+)
+
 export const refArgumentCompletionSource: CompletionSource =
 export const refArgumentCompletionSource: CompletionSource =
   makeMultipleArgumentCompletionSource(
   makeMultipleArgumentCompletionSource(
     ['RefArgument'],
     ['RefArgument'],
@@ -359,6 +444,7 @@ export const argumentCompletionSources: CompletionSource[] = [
   documentClassArgumentCompletionSource,
   documentClassArgumentCompletionSource,
   bibliographyArgumentCompletionSource,
   bibliographyArgumentCompletionSource,
   bibliographyStyleArgumentCompletionSource,
   bibliographyStyleArgumentCompletionSource,
+  citeKeyAnalyticsSource,
 ]
 ]
 
 
 const commandCompletionSource = (context: CompletionContext) => {
 const commandCompletionSource = (context: CompletionContext) => {