CHORE: debounce telems to prevent spamming (#3505)

debounce telems to prevent spamming
This commit is contained in:
Timothy Carambat 2025-03-20 08:40:28 -07:00 committed by GitHub
parent 039a6c73e4
commit b54ab7be05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 1 deletions

View File

@ -825,7 +825,6 @@ function workspaceEndpoints(app) {
: "Forked Thread", : "Forked Thread",
}); });
await Telemetry.sendTelemetry("thread_forked");
await EventLogs.logEvent( await EventLogs.logEvent(
"thread_forked", "thread_forked",
{ {

View File

@ -1,11 +1,28 @@
const { v4 } = require("uuid"); const { v4 } = require("uuid");
const { SystemSettings } = require("./systemSettings"); const { SystemSettings } = require("./systemSettings");
// Map of events and last sent time to check if the event is on cooldown
// This will be cleared on server restart - but that is fine since it is mostly to just
// prevent spamming the logs.
const TelemetryCooldown = new Map();
const Telemetry = { const Telemetry = {
// Write-only key. It can't read events or any of your other data, so it's safe to use in public apps. // Write-only key. It can't read events or any of your other data, so it's safe to use in public apps.
pubkey: "phc_9qu7QLpV8L84P3vFmEiZxL020t2EqIubP7HHHxrSsqS", pubkey: "phc_9qu7QLpV8L84P3vFmEiZxL020t2EqIubP7HHHxrSsqS",
stubDevelopmentEvents: true, // [DO NOT TOUCH] Core team only. stubDevelopmentEvents: true, // [DO NOT TOUCH] Core team only.
label: "telemetry_id", label: "telemetry_id",
/*
Key value pairs of events that should be debounced to prevent spamming the logs.
This should be used for events that could be triggered in rapid succession that are not useful to atomically log.
The value is the number of seconds to debounce the event
*/
debounced: {
agent_chat_started: 1800,
sent_chat: 1800,
agent_chat_sent: 1800,
agent_chat_started: 1800,
agent_tool_call: 1800,
},
id: async function () { id: async function () {
const result = await SystemSettings.get({ label: this.label }); const result = await SystemSettings.get({ label: this.label });
@ -34,6 +51,34 @@ const Telemetry = {
return "other"; return "other";
}, },
/**
* Checks if the event is on cooldown
* @param {string} event - The event to check
* @returns {boolean} - True if the event is on cooldown, false otherwise
*/
isOnCooldown: function (event) {
// If the event is not debounced, return false
if (!this.debounced[event]) return false;
// If the event is not in the cooldown map, return false
const lastSent = TelemetryCooldown.get(event);
if (!lastSent) return false;
// If the event is in the cooldown map, check if it has expired
const now = Date.now();
const cooldown = this.debounced[event] * 1000;
return now - lastSent < cooldown;
},
/**
* Marks the event as on cooldown - will check if the event is debounced first
* @param {string} event - The event to mark
*/
markOnCooldown: function (event) {
if (!this.debounced[event]) return;
TelemetryCooldown.set(event, Date.now());
},
sendTelemetry: async function ( sendTelemetry: async function (
event, event,
eventProperties = {}, eventProperties = {},
@ -46,6 +91,9 @@ const Telemetry = {
const distinctId = !!subUserId ? `${systemId}::${subUserId}` : systemId; const distinctId = !!subUserId ? `${systemId}::${subUserId}` : systemId;
const properties = { ...eventProperties, runtime: this.runtime() }; const properties = { ...eventProperties, runtime: this.runtime() };
// If the event is on cooldown, return
if (this.isOnCooldown(event)) return;
// Silence some events to keep logs from being too messy in production // Silence some events to keep logs from being too messy in production
// eg: Tool calls from agents spamming the logs. // eg: Tool calls from agents spamming the logs.
if (!silent) { if (!silent) {
@ -63,6 +111,9 @@ const Telemetry = {
}); });
} catch { } catch {
return; return;
} finally {
// Mark the event as on cooldown if needed
this.markOnCooldown(event);
} }
}, },