|
|
const { v4 } = require("uuid"); |
|
|
const { SystemSettings } = require("./systemSettings"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const TelemetryCooldown = new Map(); |
|
|
|
|
|
const Telemetry = { |
|
|
|
|
|
pubkey: "phc_9qu7QLpV8L84P3vFmEiZxL020t2EqIubP7HHHxrSsqS", |
|
|
stubDevelopmentEvents: true, |
|
|
label: "telemetry_id", |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debounced: { |
|
|
sent_chat: 1800, |
|
|
agent_chat_sent: 1800, |
|
|
agent_chat_started: 1800, |
|
|
agent_tool_call: 1800, |
|
|
|
|
|
|
|
|
document_uploaded: 30, |
|
|
documents_embedded_in_workspace: 30, |
|
|
link_uploaded: 30, |
|
|
raw_document_uploaded: 30, |
|
|
document_parsed: 30, |
|
|
}, |
|
|
|
|
|
id: async function () { |
|
|
const result = await SystemSettings.get({ label: this.label }); |
|
|
return result?.value || null; |
|
|
}, |
|
|
|
|
|
connect: async function () { |
|
|
const client = this.client(); |
|
|
const distinctId = await this.findOrCreateId(); |
|
|
return { client, distinctId }; |
|
|
}, |
|
|
|
|
|
isDev: function () { |
|
|
return process.env.NODE_ENV === "development" && this.stubDevelopmentEvents; |
|
|
}, |
|
|
|
|
|
client: function () { |
|
|
if (process.env.DISABLE_TELEMETRY === "true" || this.isDev()) return null; |
|
|
const { PostHog } = require("posthog-node"); |
|
|
return new PostHog(this.pubkey); |
|
|
}, |
|
|
|
|
|
runtime: function () { |
|
|
if (process.env.ANYTHING_LLM_RUNTIME === "docker") return "docker"; |
|
|
if (process.env.NODE_ENV === "production") return "production"; |
|
|
return "other"; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isOnCooldown: function (event) { |
|
|
|
|
|
if (!this.debounced[event]) return false; |
|
|
|
|
|
|
|
|
const lastSent = TelemetryCooldown.get(event); |
|
|
if (!lastSent) return false; |
|
|
|
|
|
|
|
|
const now = Date.now(); |
|
|
const cooldown = this.debounced[event] * 1000; |
|
|
return now - lastSent < cooldown; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
markOnCooldown: function (event) { |
|
|
if (!this.debounced[event]) return; |
|
|
TelemetryCooldown.set(event, Date.now()); |
|
|
}, |
|
|
|
|
|
sendTelemetry: async function ( |
|
|
event, |
|
|
eventProperties = {}, |
|
|
subUserId = null, |
|
|
silent = false |
|
|
) { |
|
|
try { |
|
|
const { client, distinctId: systemId } = await this.connect(); |
|
|
if (!client) return; |
|
|
const distinctId = !!subUserId ? `${systemId}::${subUserId}` : systemId; |
|
|
const properties = { ...eventProperties, runtime: this.runtime() }; |
|
|
|
|
|
|
|
|
if (this.isOnCooldown(event)) return; |
|
|
|
|
|
|
|
|
|
|
|
if (!silent) { |
|
|
console.log(`\x1b[32m[TELEMETRY SENT]\x1b[0m`, { |
|
|
event, |
|
|
distinctId, |
|
|
properties, |
|
|
}); |
|
|
} |
|
|
|
|
|
client.capture({ |
|
|
event, |
|
|
distinctId, |
|
|
properties, |
|
|
}); |
|
|
} catch { |
|
|
return; |
|
|
} finally { |
|
|
|
|
|
this.markOnCooldown(event); |
|
|
} |
|
|
}, |
|
|
|
|
|
flush: async function () { |
|
|
const client = this.client(); |
|
|
if (!client) return; |
|
|
await client.shutdownAsync(); |
|
|
}, |
|
|
|
|
|
setUid: async function () { |
|
|
const newId = v4(); |
|
|
await SystemSettings._updateSettings({ [this.label]: newId }); |
|
|
return newId; |
|
|
}, |
|
|
|
|
|
findOrCreateId: async function () { |
|
|
let currentId = await this.id(); |
|
|
if (currentId) return currentId; |
|
|
|
|
|
currentId = await this.setUid(); |
|
|
return currentId; |
|
|
}, |
|
|
}; |
|
|
|
|
|
module.exports = { Telemetry }; |
|
|
|