• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bandantonio / obsidian-apple-books-highlights-plugin / 21190337405

20 Jan 2026 10:55PM UTC coverage: 71.753%. Remained the same
21190337405

push

github

bandantonio
refactor: add debug timers

78 of 85 branches covered (91.76%)

Branch coverage included in aggregate %.

88 of 184 new or added lines in 8 files covered. (47.83%)

17 existing lines in 3 files now uncovered.

364 of 531 relevant lines covered (68.55%)

8.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.3
/src/utils/diagnostics.ts
1
import type { App } from 'obsidian';
1✔
2
import type { IBookHighlightsPluginSettings } from '../types';
3

4
export interface TimingEntry {
5
  label: string;
6
  duration: number;
7
  timestamp: number;
8
}
9

NEW
10
export class DiagnosticsCollector {
×
NEW
11
  private timings: TimingEntry[] = [];
×
12
  private app: App;
13
  private settings: IBookHighlightsPluginSettings;
NEW
14
  private bookCount: number = 0;
×
NEW
15
  private highlightCount: number = 0;
×
16

NEW
17
  constructor(app: App, settings: IBookHighlightsPluginSettings) {
×
NEW
18
    this.app = app;
×
NEW
19
    this.settings = settings;
×
NEW
20
  }
×
21

NEW
22
  addTiming(label: string, duration: number) {
×
NEW
23
    this.timings.push({
×
NEW
24
      label,
×
NEW
25
      duration,
×
NEW
26
      timestamp: Date.now(),
×
NEW
27
    });
×
NEW
28
  }
×
29

NEW
30
  reset() {
×
NEW
31
    this.timings = [];
×
NEW
32
    this.bookCount = 0;
×
NEW
33
    this.highlightCount = 0;
×
NEW
34
  }
×
35

NEW
36
  setCounts(bookCount: number, highlightCount: number) {
×
NEW
37
    this.bookCount = bookCount;
×
NEW
38
    this.highlightCount = highlightCount;
×
NEW
39
  }
×
40

NEW
41
  async writeDiagnosticsToFile(): Promise<void> {
×
NEW
42
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
×
NEW
43
    const filename = `diagnostics-${timestamp}.md`;
×
NEW
44
    const diagnosticsPath = `diagnostics/${filename}`;
×
45

46
    // Create diagnostics folder if it doesn't exist
NEW
47
    const diagnosticsFolder = this.app.vault.getFolderByPath('diagnostics');
×
NEW
48
    if (!diagnosticsFolder) {
×
NEW
49
      await this.app.vault.createFolder('diagnostics');
×
NEW
50
    }
×
51

NEW
52
    const content = this.generateDiagnosticsContent();
×
NEW
53
    await this.app.vault.create(diagnosticsPath, content);
×
NEW
54
  }
×
55

NEW
56
  private generateDiagnosticsContent(): string {
×
NEW
57
    const totalDuration = this.getTotalDuration();
×
NEW
58
    const bookCount = this.getBookCountFromTimings();
×
NEW
59
    const highlightCount = this.getHighlightCountFromTimings();
×
60

NEW
61
    let content = '# Apple Books Highlights Import Diagnostics\n\n';
×
NEW
62
    content += `**Generated:** ${new Date().toLocaleString()}\n\n`;
×
63

NEW
64
    content += '## Performance Summary\n\n';
×
NEW
65
    content += `- **Total Duration:** ${totalDuration.toFixed(2)}ms\n`;
×
NEW
66
    content += `- **Books Processed:** ${bookCount}\n`;
×
NEW
67
    content += `- **Highlights Processed:** ${highlightCount}\n`;
×
NEW
68
    content += `- **Average per Book:** ${(totalDuration / Math.max(bookCount, 1)).toFixed(2)}ms\n`;
×
NEW
69
    content += `- **Average per Highlight:** ${(totalDuration / Math.max(highlightCount, 1)).toFixed(2)}ms\n\n`;
×
70

NEW
71
    content += '## Detailed Timings\n\n';
×
NEW
72
    content += '| Operation | Duration (ms) | Percentage |\n';
×
NEW
73
    content += '|-----------|---------------|------------|\n';
×
74

NEW
75
    this.timings.forEach((timing) => {
×
76
      // biome-ignore lint/style/noMagicNumbers: Temporarily ignore hardcoded numbers until refactored.
NEW
77
      const percentage = ((timing.duration / totalDuration) * 100).toFixed(1);
×
NEW
78
      content += `| ${timing.label} | ${timing.duration.toFixed(2)} | ${percentage}% |\n`;
×
NEW
79
    });
×
80

NEW
81
    content += '\n## Plugin Configuration\n\n';
×
NEW
82
    content += `\`\`\`json\n${JSON.stringify(this.settings, null, 2)}\n\`\`\`\n\n`;
×
83

NEW
84
    content += '## System Information\n\n';
×
NEW
85
    content += `- **Platform:** ${navigator.platform}\n`;
×
NEW
86
    content += `- **User Agent:** ${navigator.userAgent}\n`;
×
87
    // biome-ignore lint/style/noMagicNumbers: Temporarily ignore hardcoded numbers until refactored.
NEW
88
    content += `- **Memory:** ${(performance as any).memory ? `${((performance as any).memory.usedJSHeapSize / 1024 / 1024).toFixed(1)}MB used` : 'N/A'}\n`;
×
89

NEW
90
    return content;
×
NEW
91
  }
×
92

NEW
93
  private getTotalDuration(): number {
×
94
    // Use the duration of the last "Full Import Cycle" if present, otherwise sum all
NEW
95
    const fullImportTimings = this.timings.filter((t) => t.label.includes('Full Import Cycle'));
×
NEW
96
    if (fullImportTimings.length > 0) {
×
NEW
97
      return fullImportTimings[fullImportTimings.length - 1].duration;
×
NEW
98
    }
×
NEW
99
    return this.timings.reduce((sum, timing) => sum + timing.duration, 0);
×
NEW
100
  }
×
101

NEW
102
  private getBookCountFromTimings(): number {
×
NEW
103
    return this.bookCount;
×
NEW
104
  }
×
105

NEW
106
  private getHighlightCountFromTimings(): number {
×
NEW
107
    return this.highlightCount;
×
NEW
108
  }
×
NEW
109
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc