mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(analytics): instance census, full capture, richer error context (#511)
Add a once-per-boot instance_started event (arch, os, deploy_mode, gpu_present) so the fleet architecture mix is measurable. It reuses the existing per-instance instance_id and is exempt from the volume sample rate, since a census that fires once per boot must not be thinned. Restore useful capture depth now that the sponsored plan removes the quota pressure behind the earlier hardening: - PostHog sample rate 0.1 to 1.0 (full analytics when enabled); the property allowlist still blocks file data. - Sentry per-instance ceiling 20 to 500/hr, breadcrumb trail restored (sanitized: urls/paths redacted, data payloads dropped), full stack paths kept; local vars, request bodies, and PII still dropped. Both api and web. Honor ANALYTICS_ENABLED=false as an opt-out alias: it was documented on the Docker Hub README but never wired in 2.x, so anyone who set it was still tracked. All capture stays behind the analytics opt-out gate.
This commit is contained in:
@@ -5,7 +5,7 @@ import cors from "@fastify/cors";
|
||||
import rateLimit from "@fastify/rate-limit";
|
||||
import { trace } from "@opentelemetry/api";
|
||||
import { getDispatcherStatus, initDispatcher, isGpuAvailable } from "@snapotter/ai";
|
||||
import { APP_VERSION, SafeError } from "@snapotter/shared";
|
||||
import { ANALYTICS_EVENTS, APP_VERSION, SafeError } from "@snapotter/shared";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import Fastify from "fastify";
|
||||
import { env } from "./config.js";
|
||||
@@ -17,7 +17,7 @@ import { closeFlowProducer, closeQueueEvents, warmQueueEvents } from "./jobs/enq
|
||||
import { closeQueues, perPoolHealth, queueCounts } from "./jobs/queues.js";
|
||||
import { enqueueSystemJob, SYSTEM_JOBS, scheduleSystemJobs } from "./jobs/system-jobs.js";
|
||||
import { closeWorkers, startWorkers } from "./jobs/worker.js";
|
||||
import { initAnalytics, shutdownAnalytics } from "./lib/analytics.js";
|
||||
import { initAnalytics, shutdownAnalytics, trackEvent } from "./lib/analytics.js";
|
||||
import { shouldRunStartupCleanup } from "./lib/cleanup.js";
|
||||
import { buildCsp } from "./lib/csp.js";
|
||||
import { reportError } from "./lib/error-report.js";
|
||||
@@ -27,6 +27,7 @@ import { logger } from "./lib/logger.js";
|
||||
import { requestDuration } from "./lib/metrics.js";
|
||||
import { getSettingString } from "./lib/settings-helpers.js";
|
||||
import { assertStorageWritable } from "./lib/storage-writable.js";
|
||||
import { gatherSystemProperties } from "./lib/system-info.js";
|
||||
import { requirePermission } from "./permissions.js";
|
||||
import {
|
||||
authMiddleware,
|
||||
@@ -183,6 +184,11 @@ if (!env.COOKIE_SECRET) {
|
||||
await initAnalytics();
|
||||
const { primeAnalyticsGate } = await import("./lib/analytics-gate.js");
|
||||
await primeAnalyticsGate();
|
||||
// ignoreSampleRate: this once-per-boot census must not be thinned by the
|
||||
// volume sample rate that exists to throttle high-frequency usage events.
|
||||
await trackEvent(ANALYTICS_EVENTS.INSTANCE_STARTED, { ...gatherSystemProperties() }, undefined, {
|
||||
ignoreSampleRate: true,
|
||||
});
|
||||
|
||||
// Enterprise features (license-gated)
|
||||
let enterpriseLicense: { org: string; plan: string } | null = null;
|
||||
|
||||
Reference in New Issue
Block a user