Skip to content

Commit 17def2b

Browse files
fix(nextjs): Keyless environment drift telemetry event works client-side and only in dev mode (#6539)
Co-authored-by: panteliselef <[email protected]>
1 parent cd9f96b commit 17def2b

File tree

5 files changed

+35
-2
lines changed

5 files changed

+35
-2
lines changed

.changeset/fine-weeks-give.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/nextjs': patch
3+
---
4+
5+
Fix keyless drift logic to support client components and ensure only apps on development are included. Change createClerkClient to accept an argument for samplingRate in telemetry options and update the ClerkOptions type.

packages/backend/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export type ClerkOptions = Omit<CreateBackendApiOptions, 'skipApiVersionInUrl' |
1717
CreateAuthenticateRequestOptions['options'],
1818
'audience' | 'jwtKey' | 'proxyUrl' | 'secretKey' | 'publishableKey' | 'domain' | 'isSatellite'
1919
>
20-
> & { sdkMetadata?: SDKMetadata; telemetry?: Pick<TelemetryCollectorOptions, 'disabled' | 'debug'> };
20+
> & { sdkMetadata?: SDKMetadata; telemetry?: Pick<TelemetryCollectorOptions, 'disabled' | 'debug' | 'samplingRate'> };
2121

2222
// The current exported type resolves the following issue in packages importing createClerkClient
2323
// TS4023: Exported variable 'clerkClient' has or is using name 'AuthErrorReason' from external module "/packages/backend/dist/index" but cannot be named.
@@ -31,11 +31,11 @@ export function createClerkClient(options: ClerkOptions): ClerkClient {
3131
const apiClient = createBackendApiClient(opts);
3232
const requestState = createAuthenticateRequest({ options: opts, apiClient });
3333
const telemetry = new TelemetryCollector({
34-
...options.telemetry,
3534
publishableKey: opts.publishableKey,
3635
secretKey: opts.secretKey,
3736
samplingRate: 0.1,
3837
...(opts.sdkMetadata ? { sdk: opts.sdkMetadata.name, sdkVersion: opts.sdkMetadata.version } : {}),
38+
...(opts.telemetry || {}),
3939
});
4040

4141
return {

packages/nextjs/src/app-router/client/ClerkProvider.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { canUseKeyless } from '../../utils/feature-flags';
1515
import { mergeNextClerkPropsWithEnv } from '../../utils/mergeNextClerkPropsWithEnv';
1616
import { RouterTelemetry } from '../../utils/router-telemetry';
1717
import { isNextWithUnstableServerActions } from '../../utils/sdk-versions';
18+
import { detectKeylessEnvDriftAction } from '../keyless-actions';
1819
import { invalidateCacheAction } from '../server-actions';
1920
import { useAwaitablePush } from './useAwaitablePush';
2021
import { useAwaitableReplace } from './useAwaitableReplace';
@@ -43,6 +44,13 @@ const NextClientClerkProvider = (props: NextClerkProviderProps) => {
4344
const replace = useAwaitableReplace();
4445
const [isPending, startTransition] = useTransition();
4546

47+
// Call drift detection on mount (client-side)
48+
useSafeLayoutEffect(() => {
49+
if (canUseKeyless) {
50+
void detectKeylessEnvDriftAction();
51+
}
52+
}, []);
53+
4654
// Avoid rendering nested ClerkProviders by checking for the existence of the ClerkNextOptions context provider
4755
const isNested = Boolean(useClerkNextOptions());
4856
if (isNested) {

packages/nextjs/src/app-router/keyless-actions.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,16 @@ export async function deleteKeylessAction() {
9393
await import('../server/keyless-node.js').then(m => m.removeKeyless()).catch(() => {});
9494
return;
9595
}
96+
97+
export async function detectKeylessEnvDriftAction() {
98+
if (!canUseKeyless) {
99+
return;
100+
}
101+
102+
try {
103+
const { detectKeylessEnvDrift } = await import('../server/keyless-telemetry.js');
104+
await detectKeylessEnvDrift();
105+
} catch {
106+
// ignore
107+
}
108+
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { TelemetryEventRaw } from '@clerk/types';
22
import { promises as fs } from 'fs';
33
import { dirname, join } from 'path';
44

5+
import { canUseKeyless } from '../utils/feature-flags';
56
import { createClerkClientWithOptions } from './createClerkClient';
67

78
const EVENT_KEYLESS_ENV_DRIFT_DETECTED = 'KEYLESS_ENV_DRIFT_DETECTED';
@@ -86,6 +87,9 @@ async function tryMarkTelemetryEventAsFired(): Promise<boolean> {
8687
* @returns Promise<void> - Function completes silently, errors are logged but don't throw
8788
*/
8889
export async function detectKeylessEnvDrift(): Promise<void> {
90+
if (!canUseKeyless) {
91+
return;
92+
}
8993
// Only run on server side
9094
if (typeof window !== 'undefined') {
9195
return;
@@ -163,6 +167,9 @@ export async function detectKeylessEnvDrift(): Promise<void> {
163167
const clerkClient = createClerkClientWithOptions({
164168
publishableKey: keylessFile.publishableKey,
165169
secretKey: keylessFile.secretKey,
170+
telemetry: {
171+
samplingRate: 1,
172+
},
166173
});
167174

168175
const shouldFireEvent = await tryMarkTelemetryEventAsFired();

0 commit comments

Comments
 (0)