Files
upstream-tldraw/apps/examples/e2e/fixtures/analytics-reporter.ts
upstream-mirror a774ac673a
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
2026-09-23 16:12:52 +05:00

179 lines
5.1 KiB
TypeScript

import { PerformanceTestResult } from './perf-utils'
export interface AnalyticsConfig {
enabled: boolean
projectKey?: string
apiHost?: string
}
export class PerformanceAnalyticsReporter {
private config: AnalyticsConfig
constructor(config: AnalyticsConfig = { enabled: false }) {
this.config = config
}
async reportPerformanceMetrics(
results: PerformanceTestResult[],
testContext: {
testName: string
timestamp: string
gitCommit?: string
branch?: string
ciEnvironment?: string
}
): Promise<void> {
if (!this.config.enabled) {
// eslint-disable-next-line no-console
console.log(
'Analytics reporting disabled - would have sent:',
results.length,
'performance results'
)
return
}
try {
const payload = this.formatPayload(results, testContext)
// See https://eu.posthog.com/project/45972/insights/ZdpGyj1r
await this.sendToPostHog(payload)
// eslint-disable-next-line no-console
console.log(`Sent ${results.length} performance metrics to PostHog`)
} catch (error) {
console.error('Failed to send performance metrics:', error)
}
}
private formatPayload(results: PerformanceTestResult[], testContext: any) {
return results.map((result) => ({
event: 'performance_test_result',
properties: {
// Test identification
test_name: testContext.testName,
interaction: result.interaction,
timestamp: testContext.timestamp,
// Environment
platform: result.environment.platform,
viewport: result.environment.viewport,
browser: result.environment.browser,
// Performance metrics
avg_fps: result.metrics.averageFps,
min_fps: result.metrics.minFps,
max_fps: result.metrics.maxFps,
total_frames: result.metrics.totalFrames,
duration_seconds: result.metrics.duration,
sample_count: result.metrics.samples.length,
// Comparison results
baseline_avg_fps: result.comparison.baseline.avgFps,
fps_change_percent: result.comparison.avgFpsChange,
is_regression: result.comparison.isRegression,
is_improvement: result.comparison.isImprovement,
status: result.comparison.status,
// CI/Git context
git_commit: testContext.gitCommit,
git_branch: testContext.branch,
ci_environment: testContext.ciEnvironment,
// Additional metadata
fps_samples: result.metrics.samples.slice(0, 10), // First 10 samples for analysis
},
}))
}
private async sendToPostHog(events: any[]): Promise<void> {
if (!this.config.projectKey) {
throw new Error('PostHog project key not configured')
}
const url = `${this.config.apiHost || 'https://analytics.tldraw.com'}/capture/`
for (const event of events) {
const payload = {
api_key: this.config.projectKey,
event: event.event,
properties: {
...event.properties,
distinct_id: `e2e-test-${Date.now()}`, // Anonymous test identifier
$lib: 'tldraw-e2e-perf',
$lib_version: '1.0.0',
},
timestamp: new Date().toISOString(),
}
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
if (!response.ok) {
throw new Error(`PostHog API error: ${response.status} ${response.statusText}`)
}
}
}
async reportRegressionAlert(result: PerformanceTestResult, testContext: any): Promise<void> {
if (!this.config.enabled || result.comparison.status !== 'fail') {
return
}
try {
const alertPayload = {
event: 'performance_regression_alert',
properties: {
test_name: testContext.testName,
interaction: result.interaction,
avg_fps_drop: Math.abs(result.comparison.avgFpsChange),
current_fps: result.metrics.averageFps,
baseline_fps: result.comparison.baseline.avgFps,
platform: result.environment.platform,
browser: result.environment.browser,
timestamp: testContext.timestamp,
git_commit: testContext.gitCommit,
git_branch: testContext.branch,
alert_message: result.comparison.message,
severity: result.comparison.avgFpsChange < -20 ? 'high' : 'medium',
},
}
await this.sendToPostHog([alertPayload])
// eslint-disable-next-line no-console
console.log(`Sent performance regression alert for ${result.interaction}`)
} catch (error) {
console.error('Failed to send regression alert:', error)
}
}
}
// Factory function to create analytics reporter with environment-based config
export function createAnalyticsReporter(): PerformanceAnalyticsReporter {
const config: AnalyticsConfig = {
enabled: process.env.PERFORMANCE_ANALYTICS_ENABLED === 'true',
projectKey: 'phc_i8oKgMzgV38sn3GfjswW9mevQ3gFlo7bJXekZFeDN6',
apiHost: process.env.POSTHOG_API_HOST || 'https://analytics.tldraw.com/ingest',
}
return new PerformanceAnalyticsReporter(config)
}
// Helper to collect test context from environment
export function getTestContext(testName: string) {
return {
testName,
timestamp: new Date().toISOString(),
gitCommit: process.env.GIT_COMMIT || process.env.GITHUB_SHA,
branch: process.env.GIT_BRANCH || process.env.GITHUB_REF_NAME,
ciEnvironment: process.env.CI
? process.env.GITHUB_ACTIONS
? 'github-actions'
: 'ci'
: 'local',
}
}