From 7a8de3f68dfab91f45ebcb1e29434dc2bff9a3cf Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Tue, 14 Nov 2023 13:28:33 -0600 Subject: [PATCH 1/3] feat(backend): Add TelemetryCollector instance to clerk backend client --- packages/backend/src/index.ts | 12 ++++++- packages/fastify/src/clerkClient.ts | 3 +- packages/fastify/src/constants.ts | 4 +++ packages/fastify/src/global.d.ts | 6 ++++ packages/fastify/tsconfig.json | 2 +- .../src/GatsbyClerkProvider.tsx | 7 +--- packages/gatsby-plugin-clerk/src/constants.ts | 5 +++ .../src/ssr/clerkClient.ts | 7 +++- packages/nextjs/src/server/authMiddleware.ts | 14 ++------ packages/nextjs/src/server/clerkClient.ts | 17 +++++++++- packages/nextjs/src/server/constants.ts | 7 ++++ .../src/utils/mergeNextClerkPropsWithEnv.ts | 6 ++-- packages/sdk-node/src/globals.d.ts | 6 ++++ packages/sdk-node/src/utils.ts | 4 +++ packages/sdk-node/tsconfig.json | 2 +- packages/shared/src/telemetry.ts | 32 ++++++++++++------- playground/app-router/src/middleware.ts | 4 ++- 17 files changed, 98 insertions(+), 40 deletions(-) create mode 100644 packages/fastify/src/global.d.ts create mode 100644 packages/sdk-node/src/globals.d.ts diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 0d1a552ca2e..45992d644de 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -1,4 +1,7 @@ import { deprecatedObjectProperty } from '@clerk/shared/deprecated'; +import type { TelemetryCollectorOptions } from '@clerk/shared/telemetry'; +import { TelemetryCollector } from '@clerk/shared/telemetry'; +import type { SDKMetadata } from '@clerk/types'; import type { CreateBackendApiOptions } from './api'; import { createBackendApiClient } from './api'; @@ -21,16 +24,23 @@ export type ClerkOptions = CreateBackendApiOptions & CreateAuthenticateRequestOptions['options'], 'audience' | 'jwtKey' | 'proxyUrl' | 'secretKey' | 'publishableKey' | 'domain' | 'isSatellite' > - >; + > & { sdkMetadata?: SDKMetadata; telemetry?: Pick }; export function Clerk(options: ClerkOptions) { const opts = { ...options }; const apiClient = createBackendApiClient(opts); const requestState = createAuthenticateRequest({ options: opts, apiClient }); + const telemetry = new TelemetryCollector({ + ...options.telemetry, + publishableKey: opts.publishableKey, + secretKey: opts.secretKey, + ...(opts.sdkMetadata ? { sdk: opts.sdkMetadata.name, sdkVersion: opts.sdkMetadata.version } : {}), + }); const clerkInstance = { ...apiClient, ...requestState, + telemetry, /** * @deprecated This prop has been deprecated and will be removed in the next major release. */ diff --git a/packages/fastify/src/clerkClient.ts b/packages/fastify/src/clerkClient.ts index 03141d50442..3e31939e2eb 100644 --- a/packages/fastify/src/clerkClient.ts +++ b/packages/fastify/src/clerkClient.ts @@ -1,6 +1,6 @@ import { Clerk } from '@clerk/backend'; -import { API_URL, API_VERSION, JWT_KEY, SECRET_KEY } from './constants'; +import { API_URL, API_VERSION, JWT_KEY, SDK_METADATA, SECRET_KEY } from './constants'; export const createClerkClient = Clerk; @@ -9,4 +9,5 @@ export const clerkClient = createClerkClient({ apiUrl: API_URL, apiVersion: API_VERSION, jwtKey: JWT_KEY, + sdkMetadata: SDK_METADATA, }); diff --git a/packages/fastify/src/constants.ts b/packages/fastify/src/constants.ts index 6699d20ee09..725f748d28e 100644 --- a/packages/fastify/src/constants.ts +++ b/packages/fastify/src/constants.ts @@ -6,5 +6,9 @@ export const SECRET_KEY = process.env.CLERK_SECRET_KEY || ''; export const PUBLISHABLE_KEY = process.env.CLERK_PUBLISHABLE_KEY || ''; export const API_URL = process.env.CLERK_API_URL || apiUrlFromPublishableKey(PUBLISHABLE_KEY); export const JWT_KEY = process.env.CLERK_JWT_KEY || ''; +export const SDK_METADATA = { + name: PACKAGE_NAME, + version: PACKAGE_VERSION, +}; export const { Cookies, Headers } = constants; diff --git a/packages/fastify/src/global.d.ts b/packages/fastify/src/global.d.ts new file mode 100644 index 00000000000..1ae75219e34 --- /dev/null +++ b/packages/fastify/src/global.d.ts @@ -0,0 +1,6 @@ +declare global { + const PACKAGE_NAME: string; + const PACKAGE_VERSION: string; +} + +export {}; diff --git a/packages/fastify/tsconfig.json b/packages/fastify/tsconfig.json index f06061d1ecf..5fbaf3766c4 100644 --- a/packages/fastify/tsconfig.json +++ b/packages/fastify/tsconfig.json @@ -15,6 +15,6 @@ "resolveJsonModule": true, "declarationDir": "dist/types" }, - "include": ["src/index.ts"], + "include": ["src/index.ts", "src/global.d.ts"], "exclude": ["node_modules"] } diff --git a/packages/gatsby-plugin-clerk/src/GatsbyClerkProvider.tsx b/packages/gatsby-plugin-clerk/src/GatsbyClerkProvider.tsx index 74d558f0989..29ec9a41c0e 100644 --- a/packages/gatsby-plugin-clerk/src/GatsbyClerkProvider.tsx +++ b/packages/gatsby-plugin-clerk/src/GatsbyClerkProvider.tsx @@ -7,12 +7,7 @@ import { import { navigate } from 'gatsby'; import React from 'react'; -import { TELEMETRY_DEBUG, TELEMETRY_DISABLED } from './constants'; - -const SDK_METADATA = { - name: PACKAGE_NAME, - version: PACKAGE_VERSION, -}; +import { SDK_METADATA, TELEMETRY_DEBUG, TELEMETRY_DISABLED } from './constants'; __internal__setErrorThrowerOptions({ packageName: 'gatsby-plugin-clerk' }); diff --git a/packages/gatsby-plugin-clerk/src/constants.ts b/packages/gatsby-plugin-clerk/src/constants.ts index d3423677597..5fcf6a6f262 100644 --- a/packages/gatsby-plugin-clerk/src/constants.ts +++ b/packages/gatsby-plugin-clerk/src/constants.ts @@ -11,3 +11,8 @@ export const PROXY_URL = process.env.GATSBY_CLERK_PROXY_URL; export const TELEMETRY_DISABLED = isTruthy(process.env.GATSBY_CLERK_TELEMETRY_DISABLED); export const TELEMETRY_DEBUG = isTruthy(process.env.GATSBY_CLERK_TELEMETRY_DEBUG); + +export const SDK_METADATA = { + name: PACKAGE_NAME, + version: PACKAGE_VERSION, +}; diff --git a/packages/gatsby-plugin-clerk/src/ssr/clerkClient.ts b/packages/gatsby-plugin-clerk/src/ssr/clerkClient.ts index b70a88df128..5584cd09497 100644 --- a/packages/gatsby-plugin-clerk/src/ssr/clerkClient.ts +++ b/packages/gatsby-plugin-clerk/src/ssr/clerkClient.ts @@ -1,6 +1,6 @@ import { Clerk } from '@clerk/backend'; -import { API_URL, API_VERSION, SECRET_KEY } from '../constants'; +import { API_URL, API_VERSION, SDK_METADATA, SECRET_KEY, TELEMETRY_DEBUG, TELEMETRY_DISABLED } from '../constants'; const clerkClient = Clerk({ secretKey: SECRET_KEY, @@ -8,6 +8,11 @@ const clerkClient = Clerk({ apiVersion: API_VERSION, // TODO: Fetch version from package.json userAgent: 'gatsby-plugin-clerk', + sdkMetadata: SDK_METADATA, + telemetry: { + disabled: TELEMETRY_DISABLED, + debug: TELEMETRY_DEBUG, + }, }); const createClerkClient = Clerk; diff --git a/packages/nextjs/src/server/authMiddleware.ts b/packages/nextjs/src/server/authMiddleware.ts index d59038eff74..bcdf0066c64 100644 --- a/packages/nextjs/src/server/authMiddleware.ts +++ b/packages/nextjs/src/server/authMiddleware.ts @@ -1,7 +1,6 @@ import type { AuthObject, RequestState } from '@clerk/backend'; import { buildRequestUrl, constants } from '@clerk/backend'; import { isDevelopmentFromApiKey } from '@clerk/shared/keys'; -import { TelemetryCollector } from '@clerk/shared/telemetry'; import type Link from 'next/link'; import type { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; @@ -9,7 +8,8 @@ import { NextResponse } from 'next/server'; import { isRedirect, mergeResponses, paths, setHeader, stringifyHeaders } from '../utils'; import { withLogger } from '../utils/debugLogger'; import { authenticateRequest, handleInterstitialState, handleUnknownState } from './authenticateRequest'; -import { PUBLISHABLE_KEY, SECRET_KEY } from './constants'; +import { clerkClient } from './clerkClient'; +import { SECRET_KEY } from './constants'; import { DEV_BROWSER_JWT_MARKER, setDevBrowserJWTInURL } from './devBrowser'; import { clockSkewDetected, @@ -27,14 +27,6 @@ import { setRequestHeadersOnNextResponse, } from './utils'; -const telemetry = new TelemetryCollector({ - verbose: true, - samplingRate: 1, - publishableKey: PUBLISHABLE_KEY, - sdk: PACKAGE_NAME, - sdkVersion: PACKAGE_VERSION, -}); - type WithPathPatternWildcard = `${T & string}(.*)`; type NextTypedRoute['0']['href']> = T extends string ? T : never; @@ -159,7 +151,7 @@ const authMiddleware: AuthMiddleware = (...args: unknown[]) => { const isApiRoute = createApiRoutes(apiRoutes); const defaultAfterAuth = createDefaultAfterAuth(isPublicRoute, isApiRoute, params); - telemetry.record('METHOD_CALLED', { + clerkClient.telemetry.record('METHOD_CALLED', { method: 'authMiddleware', publicRoutes: Boolean(publicRoutes), ignoredRoutes: Boolean(ignoredRoutes), diff --git a/packages/nextjs/src/server/clerkClient.ts b/packages/nextjs/src/server/clerkClient.ts index 04e6413ef34..4c8fe410435 100644 --- a/packages/nextjs/src/server/clerkClient.ts +++ b/packages/nextjs/src/server/clerkClient.ts @@ -1,6 +1,16 @@ import { Clerk } from '@clerk/backend'; -import { API_URL, API_VERSION, DOMAIN, IS_SATELLITE, PROXY_URL, SECRET_KEY } from './constants'; +import { + API_URL, + API_VERSION, + DOMAIN, + IS_SATELLITE, + PROXY_URL, + SDK_METADATA, + SECRET_KEY, + TELEMETRY_DEBUG, + TELEMETRY_DISABLED, +} from './constants'; const clerkClient = Clerk({ secretKey: SECRET_KEY, @@ -11,6 +21,11 @@ const clerkClient = Clerk({ proxyUrl: PROXY_URL, domain: DOMAIN, isSatellite: IS_SATELLITE, + sdkMetadata: SDK_METADATA, + telemetry: { + disabled: TELEMETRY_DISABLED, + debug: TELEMETRY_DEBUG, + }, }); const createClerkClient = Clerk; diff --git a/packages/nextjs/src/server/constants.ts b/packages/nextjs/src/server/constants.ts index 00b7dcbe774..3b6603c107d 100644 --- a/packages/nextjs/src/server/constants.ts +++ b/packages/nextjs/src/server/constants.ts @@ -12,3 +12,10 @@ export const PROXY_URL = process.env.NEXT_PUBLIC_CLERK_PROXY_URL || ''; export const IS_SATELLITE = isTruthy(process.env.NEXT_PUBLIC_CLERK_IS_SATELLITE) || false; export const SIGN_IN_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL || ''; export const SIGN_UP_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL || ''; +export const SDK_METADATA = { + name: PACKAGE_NAME, + version: PACKAGE_VERSION, +}; + +export const TELEMETRY_DISABLED = isTruthy(process.env.NEXT_PUBLIC_CLERK_TELEMETRY_DISABLED); +export const TELEMETRY_DEBUG = isTruthy(process.env.NEXT_PUBLIC_CLERK_TELEMETRY_DEBUG); diff --git a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts index d2b742bd21c..1c3de67aa8c 100644 --- a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts +++ b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts @@ -1,5 +1,6 @@ import { isTruthy } from '@clerk/shared/underscore'; +import { SDK_METADATA } from '../server/constants'; import type { NextClerkProviderProps } from '../types'; export const mergeNextClerkPropsWithEnv = (props: Omit) => { @@ -19,9 +20,6 @@ export const mergeNextClerkPropsWithEnv = (props: Omit { signInUrl: process.env.CLERK_SIGN_IN_URL || '', isSatellite: isTruthy(process.env.CLERK_IS_SATELLITE), jwtKey: process.env.CLERK_JWT_KEY || '', + sdkMetadata: { + name: PACKAGE_NAME, + version: PACKAGE_VERSION, + }, }; }; diff --git a/packages/sdk-node/tsconfig.json b/packages/sdk-node/tsconfig.json index 81ebb93d55d..d30cd134410 100644 --- a/packages/sdk-node/tsconfig.json +++ b/packages/sdk-node/tsconfig.json @@ -19,5 +19,5 @@ "types": ["jest"] }, "exclude": ["node_modules"], - "include": ["src/index.ts", "src/instance.ts"] + "include": ["src/index.ts", "src/instance.ts", "src/globals.d.ts"] } diff --git a/packages/shared/src/telemetry.ts b/packages/shared/src/telemetry.ts index 3be742efd88..c52564f5ccd 100644 --- a/packages/shared/src/telemetry.ts +++ b/packages/shared/src/telemetry.ts @@ -3,7 +3,7 @@ import type { InstanceType } from '@clerk/types'; import { parsePublishableKey } from './keys'; import { isTruthy } from './underscore'; -type TelemetryCollectorOptions = { +export type TelemetryCollectorOptions = { /** * If true, telemetry will not be collected. */ @@ -21,13 +21,13 @@ type TelemetryCollectorOptions = { */ maxBufferSize?: number; /** - * Determines whether or not events will be logged to the console. + * The publishableKey to associate with the collected events. */ - verbose?: boolean; + publishableKey?: string; /** - * The publishableKey to associate with the collected events. + * The secretKey to associate with the collected events. */ - publishableKey: string; + secretKey?: string; /** * The current clerk-js version. */ @@ -44,13 +44,13 @@ type TelemetryCollectorOptions = { type TelemetryCollectorConfig = Pick< TelemetryCollectorOptions, - 'samplingRate' | 'verbose' | 'disabled' | 'debug' | 'maxBufferSize' + 'samplingRate' | 'disabled' | 'debug' | 'maxBufferSize' > & { endpoint: string; }; type TelemetryMetadata = Required< - Pick + Pick > & { /** * The instance type, derived from the provided publishableKey. @@ -64,6 +64,10 @@ type TelemetryEvent = { * publishableKey */ pk?: string; + /** + * secretKey + */ + sk?: string; /** * instanceType */ @@ -85,7 +89,6 @@ type TelemetryEvent = { const DEFAULT_CONFIG: Partial> = { samplingRate: 1, - verbose: false, maxBufferSize: 5, }; @@ -100,7 +103,6 @@ export class TelemetryCollector { this.#config = { maxBufferSize: options.maxBufferSize ?? DEFAULT_CONFIG.maxBufferSize, samplingRate: options.samplingRate ?? DEFAULT_CONFIG.samplingRate, - verbose: options.verbose ?? DEFAULT_CONFIG.verbose, disabled: options.disabled ?? false, debug: options.debug ?? false, } as Required; @@ -116,15 +118,20 @@ export class TelemetryCollector { this.#metadata.sdk = options.sdk!; this.#metadata.sdkVersion = options.sdkVersion!; - this.#metadata.publishableKey = options.publishableKey; + this.#metadata.publishableKey = options.publishableKey ?? ''; const parsedKey = parsePublishableKey(options.publishableKey); if (parsedKey) { this.#metadata.instanceType = parsedKey.instanceType; } - // this.#config.endpoint = 'https://telemetry-service-staging.bryce-clerk.workers.dev'; - this.#config.endpoint = 'http://localhost:8787'; + if (options.secretKey) { + // Only send the first 16 characters of the secret key to to avoid sending the full key. We can still query against the partial key. + this.#metadata.secretKey = options.secretKey.substring(0, 16); + } + + this.#config.endpoint = 'https://staging.clerk-telemetry.com'; + // this.#config.endpoint = 'http://localhost:8787'; } get isEnabled(): boolean { @@ -265,6 +272,7 @@ export class TelemetryCollector { sdk: sdkMetadata.name, sdkv: sdkMetadata.version, ...(this.#metadata.publishableKey ? { pk: this.#metadata.publishableKey } : {}), + ...(this.#metadata.secretKey ? { sk: this.#metadata.secretKey } : {}), payload, }; } diff --git a/playground/app-router/src/middleware.ts b/playground/app-router/src/middleware.ts index b89c54e56d9..6010f58b825 100644 --- a/playground/app-router/src/middleware.ts +++ b/playground/app-router/src/middleware.ts @@ -1,11 +1,13 @@ import { authMiddleware } from '@clerk/nextjs'; import { NextMiddleware, NextResponse } from 'next/server'; +const clerkMiddleware = authMiddleware() + const middleware: NextMiddleware = (request, event) => { if (request.geo?.country?.toLocaleUpperCase() === 'IN') { return new NextResponse(null, { status: 403 }); } - return authMiddleware()(request, event); + return clerkMiddleware(request, event); }; export default middleware; From d4c29aceb8e4231b563053802999854a828abfdc Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Tue, 14 Nov 2023 13:44:22 -0600 Subject: [PATCH 2/3] feat(shared): Set default endpoint as staging --- packages/shared/src/telemetry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/telemetry.ts b/packages/shared/src/telemetry.ts index c52564f5ccd..8f7b04c5752 100644 --- a/packages/shared/src/telemetry.ts +++ b/packages/shared/src/telemetry.ts @@ -90,6 +90,7 @@ type TelemetryEvent = { const DEFAULT_CONFIG: Partial> = { samplingRate: 1, maxBufferSize: 5, + endpoint: 'https://staging.clerk-telemetry.com', }; // TODO: determine some type of throttle/dedupe heuristic to avoid sending excessive events for e.g. a component render @@ -130,7 +131,6 @@ export class TelemetryCollector { this.#metadata.secretKey = options.secretKey.substring(0, 16); } - this.#config.endpoint = 'https://staging.clerk-telemetry.com'; // this.#config.endpoint = 'http://localhost:8787'; } From f9e9be084bbe15cf7f828a04f68cc383d233ef46 Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Thu, 16 Nov 2023 11:14:54 -0600 Subject: [PATCH 3/3] fix(shared): Add default for instance type --- packages/shared/src/telemetry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shared/src/telemetry.ts b/packages/shared/src/telemetry.ts index 8f7b04c5752..dd1c59bbeb6 100644 --- a/packages/shared/src/telemetry.ts +++ b/packages/shared/src/telemetry.ts @@ -267,8 +267,8 @@ export class TelemetryCollector { return { event, - cv: this.#metadata.clerkVersion, - it: this.#metadata.instanceType, + cv: this.#metadata.clerkVersion ?? '', + it: this.#metadata.instanceType ?? '', sdk: sdkMetadata.name, sdkv: sdkMetadata.version, ...(this.#metadata.publishableKey ? { pk: this.#metadata.publishableKey } : {}),