feat(backend): integrate PostHog analytics for enhanced observability

- Added PostHog configuration options to .env.example files for both Docker and Surfsense backend.
- Introduced PostHog dependency in pyproject.toml.
- Implemented analytics middleware to capture various events across the application, including user authentication, automation runs, and API requests.
- Enhanced existing routes and services to emit analytics events, providing insights into user interactions and system performance.
- Ensured graceful shutdown of analytics clients in worker processes and application lifecycles.
This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-07-22 22:16:28 -07:00
parent ca4f231577
commit dbedf0cfa5
47 changed files with 1618 additions and 513 deletions

View file

@ -21,8 +21,6 @@ import { OAUTH_RESULT_COOKIE, parseOAuthCallbackResult } from "@/contracts/types
import { authenticatedFetch } from "@/lib/auth-fetch";
import { buildBackendUrl } from "@/lib/env-config";
import {
trackConnectorConnected,
trackConnectorDeleted,
trackConnectorSetupFailure,
trackConnectorSetupStarted,
trackIndexWithDateRangeOpened,
@ -296,11 +294,9 @@ export const useConnectorDialog = () => {
if (newConnector && oauthConnector) {
const connectorValidation = searchSourceConnector.safeParse(newConnector);
if (connectorValidation.success) {
trackConnectorConnected(
Number(workspaceId),
oauthConnector.connectorType,
newConnector.id
);
// connector_connected is now emitted server-side (after_insert
// listener in search_source_connectors_routes.py) — covers the
// OAuth callback redirect the frontend often never observes.
const isLiveConnector = LIVE_CONNECTOR_TYPES.has(oauthConnector.connectorType);
@ -436,12 +432,7 @@ export const useConnectorDialog = () => {
if (connector) {
const connectorValidation = searchSourceConnector.safeParse(connector);
if (connectorValidation.success) {
// Track webcrawler connector connected
trackConnectorConnected(
Number(workspaceId),
EnumConnectorName.WEBCRAWLER_CONNECTOR,
connector.id
);
// connector_connected is now emitted server-side (after_insert).
const config = validateIndexingConfigState({
connectorType: EnumConnectorName.WEBCRAWLER_CONNECTOR,
@ -540,8 +531,7 @@ export const useConnectorDialog = () => {
// Store connectingConnectorType before clearing it
const currentConnectorType = connectingConnectorType;
// Track connector connected event for non-OAuth connectors
trackConnectorConnected(Number(workspaceId), currentConnectorType, connector.id);
// connector_connected is now emitted server-side (after_insert).
// Find connector title from constants
const connectorInfo = OTHER_CONNECTORS.find(
@ -1229,12 +1219,8 @@ export const useConnectorDialog = () => {
id: editingConnector.id,
});
// Track connector deleted event
trackConnectorDeleted(
Number(workspaceId),
editingConnector.connector_type,
editingConnector.id
);
// connector_deleted is now emitted server-side
// (search_source_connectors_routes.delete_search_source_connector).
toast.success(
editingConnector.connector_type === "MCP_CONNECTOR"