Skip to content

Commit 6954897

Browse files
Create file to control telemetry event firing
1 parent 9897c43 commit 6954897

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

packages/nextjs/src/app-router/server/keyless-provider.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import React from 'react';
66

77
import { createClerkClientWithOptions } from '../../server/createClerkClient';
88
import { collectKeylessMetadata, formatMetadataHeaders } from '../../server/keyless-custom-headers';
9-
import { detectKeylessEnvDrift } from '../../server/keyless-telemetry';
109
import type { NextClerkProviderProps } from '../../types';
1110
import { canUseKeyless } from '../../utils/feature-flags';
1211
import { mergeNextClerkPropsWithEnv } from '../../utils/mergeNextClerkPropsWithEnv';
@@ -48,11 +47,6 @@ export const KeylessProvider = async (props: KeylessProviderProps) => {
4847
.then(mod => mod.createOrReadKeyless())
4948
.catch(() => null);
5049

51-
// Detect environment variable drift and fire telemetry events
52-
if (newOrReadKeys) {
53-
await detectKeylessEnvDrift();
54-
}
55-
5650
const { clerkDevelopmentCache, createConfirmationMessage, createKeylessModeMessage } = await import(
5751
'../../server/keyless-log-cache.js'
5852
);

packages/nextjs/src/server/keyless-telemetry.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import type { TelemetryEventRaw } from '@clerk/types';
2+
import { promises as fs } from 'fs';
3+
import { join } from 'path';
24

35
import { createClerkClientWithOptions } from './createClerkClient';
46

57
const EVENT_KEYLESS_ENV_DRIFT_DETECTED = 'KEYLESS_ENV_DRIFT_DETECTED';
68
const EVENT_SAMPLING_RATE = 1; // 100% sampling rate
9+
const TELEMETRY_FLAG_FILE = '.clerk/.tmp/keyless-telemetry-fired.json';
710

811
type EventKeylessEnvDriftPayload = {
912
publicKeyMatch: boolean;
@@ -14,6 +17,47 @@ type EventKeylessEnvDriftPayload = {
1417
envPublishableKey: string;
1518
};
1619

20+
/**
21+
* Gets the absolute path to the telemetry flag file.
22+
*/
23+
function getTelemetryFlagFilePath(): string {
24+
return join(process.cwd(), TELEMETRY_FLAG_FILE);
25+
}
26+
27+
/**
28+
* Checks if the telemetry event has already been fired by looking for a flag file.
29+
*/
30+
async function hasTelemetryEventBeenFired(): Promise<boolean> {
31+
try {
32+
await fs.access(getTelemetryFlagFilePath());
33+
return true;
34+
} catch {
35+
return false;
36+
}
37+
}
38+
39+
/**
40+
* Creates a flag file to mark that the telemetry event has been fired.
41+
*/
42+
async function markTelemetryEventAsFired(): Promise<void> {
43+
try {
44+
// Ensure the directory exists
45+
const dir = join(process.cwd(), '.clerk/.tmp');
46+
await fs.mkdir(dir, { recursive: true });
47+
48+
// Create the flag file with timestamp
49+
const flagData = {
50+
firedAt: new Date().toISOString(),
51+
event: EVENT_KEYLESS_ENV_DRIFT_DETECTED,
52+
};
53+
54+
await fs.writeFile(getTelemetryFlagFilePath(), JSON.stringify(flagData, null, 2));
55+
} catch (error) {
56+
// Silently handle errors to avoid breaking the application
57+
console.warn('Failed to create telemetry flag file:', error);
58+
}
59+
}
60+
1761
/**
1862
* Detects environment variable drift for keyless Next.js applications and fires telemetry events.
1963
*
@@ -23,6 +67,8 @@ type EventKeylessEnvDriftPayload = {
2367
* If there's a mismatch, it fires a `KEYLESS_ENV_DRIFT_DETECTED` event.
2468
* For local testing purposes, it also fires a `KEYLESS_ENV_DRIFT_NOT_DETECTED` event when
2569
* keys exist and match the environment variables.
70+
*
71+
* The telemetry event will only fire once per application instance to avoid noise.
2672
*/
2773
export async function detectKeylessEnvDrift(): Promise<void> {
2874
// Only run on server side
@@ -31,6 +77,11 @@ export async function detectKeylessEnvDrift(): Promise<void> {
3177
}
3278

3379
try {
80+
// Check if telemetry event has already been fired
81+
if (await hasTelemetryEventBeenFired()) {
82+
return;
83+
}
84+
3485
// Dynamically import server-side dependencies to avoid client-side issues
3586
const { safeParseClerkFile } = await import('./keyless-node.js');
3687

@@ -87,6 +138,9 @@ export async function detectKeylessEnvDrift(): Promise<void> {
87138
};
88139

89140
clerkClient.telemetry?.record(driftDetectedEvent);
141+
142+
// Mark the telemetry event as fired to prevent future executions
143+
await markTelemetryEventAsFired();
90144
}
91145
} catch (error) {
92146
// Silently handle errors to avoid breaking the application

0 commit comments

Comments
 (0)