add workers-shared package and source-maps for dotcom-worker sentry reports (#4052)
Share the new sentry stuff that plays nice with releases/sourcemaps with dotcom-worker using a new `worker-shared` package.
This commit is contained in:
parent
7ec30e56da
commit
031547749f
20 changed files with 150 additions and 54 deletions
|
@ -24,11 +24,11 @@
|
|||
"@tldraw/tlschema": "workspace:*",
|
||||
"@tldraw/tlsync": "workspace:*",
|
||||
"@tldraw/utils": "workspace:*",
|
||||
"@tldraw/worker-shared": "workspace:*",
|
||||
"itty-router": "^4.0.13",
|
||||
"nanoid": "4.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"toucan-js": "^3.4.0"
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20240620.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { createSentry } from '@tldraw/worker-shared'
|
||||
import { DurableObject } from 'cloudflare:workers'
|
||||
import { Router } from 'itty-router'
|
||||
import { createSentry } from './sentry'
|
||||
import { Environment } from './types'
|
||||
|
||||
export class BemoDO extends DurableObject<Environment> {
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
import { Toucan } from 'toucan-js'
|
||||
import { Environment } from './types'
|
||||
|
||||
interface Context {
|
||||
waitUntil: ExecutionContext['waitUntil']
|
||||
request?: Request
|
||||
}
|
||||
|
||||
export function createSentry(ctx: Context, env: Environment, request?: Request) {
|
||||
return new Toucan({
|
||||
dsn: env.SENTRY_DSN,
|
||||
release: `${env.WORKER_NAME}.${env.CF_VERSION_METADATA.id}`,
|
||||
environment: env.WORKER_NAME,
|
||||
context: ctx,
|
||||
request,
|
||||
requestDataOptions: {
|
||||
allowedHeaders: ['user-agent'],
|
||||
allowedSearchParams: /(.*)/,
|
||||
},
|
||||
})
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
/// <reference no-default-lib="true"/>
|
||||
/// <reference types="@cloudflare/workers-types" />
|
||||
|
||||
import { createSentry } from '@tldraw/worker-shared'
|
||||
import { WorkerEntrypoint } from 'cloudflare:workers'
|
||||
import { Router, createCors } from 'itty-router'
|
||||
import { createSentry } from './sentry'
|
||||
import { Environment } from './types'
|
||||
|
||||
export { BemoDO } from './BemoDO'
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
{
|
||||
"path": "../../packages/dotcom-shared"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/worker-shared"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/store"
|
||||
},
|
||||
|
|
|
@ -40,7 +40,7 @@ bucket_name = 'uploads-preview'
|
|||
|
||||
# in production, we write to the main bucket
|
||||
[[env.production.r2_buckets]]
|
||||
binding = "ROOMS"
|
||||
binding = "UPLOADS"
|
||||
bucket_name = "uploads"
|
||||
|
||||
#################### Analytics engine ####################
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
"@tldraw/tlsync": "workspace:*",
|
||||
"@tldraw/utils": "workspace:*",
|
||||
"@tldraw/validate": "workspace:*",
|
||||
"@tldraw/worker-shared": "workspace:*",
|
||||
"itty-router": "^4.0.13",
|
||||
"nanoid": "4.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"toucan-js": "^3.4.0"
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20240620.0",
|
||||
|
|
|
@ -17,8 +17,8 @@ import {
|
|||
type PersistedRoomSnapshotForSupabase,
|
||||
} from '@tldraw/tlsync'
|
||||
import { assert, assertExists, exhaustiveSwitchError } from '@tldraw/utils'
|
||||
import { createSentry } from '@tldraw/worker-shared'
|
||||
import { IRequest, Router } from 'itty-router'
|
||||
import { Toucan } from 'toucan-js'
|
||||
import { AlarmScheduler } from './AlarmScheduler'
|
||||
import { PERSIST_INTERVAL_MS } from './config'
|
||||
import { getR2KeyForRoom } from './r2'
|
||||
|
@ -215,14 +215,7 @@ export class TLDrawDurableObject {
|
|||
|
||||
// Handle a request to the Durable Object.
|
||||
async fetch(req: IRequest) {
|
||||
const sentry = new Toucan({
|
||||
dsn: this.sentryDSN,
|
||||
request: req,
|
||||
requestDataOptions: {
|
||||
allowedHeaders: ['user-agent'],
|
||||
allowedSearchParams: /(.*)/,
|
||||
},
|
||||
})
|
||||
const sentry = createSentry(this.state, this.env, req)
|
||||
|
||||
try {
|
||||
return await this.router.handle(req)
|
||||
|
|
|
@ -25,6 +25,8 @@ export interface Environment {
|
|||
SLUG_TO_READONLY_SLUG: KVNamespace
|
||||
READONLY_SLUG_TO_SLUG: KVNamespace
|
||||
|
||||
CF_VERSION_METADATA: WorkerVersionMetadata
|
||||
|
||||
// env vars
|
||||
SUPABASE_URL: string | undefined
|
||||
SUPABASE_KEY: string | undefined
|
||||
|
|
|
@ -7,8 +7,8 @@ import {
|
|||
ROOM_PREFIX,
|
||||
} from '@tldraw/dotcom-shared'
|
||||
import { T } from '@tldraw/validate'
|
||||
import { createSentry } from '@tldraw/worker-shared'
|
||||
import { Router, createCors, json } from 'itty-router'
|
||||
import { Toucan } from 'toucan-js'
|
||||
import { createRoom } from './routes/createRoom'
|
||||
import { createRoomSnapshot } from './routes/createRoomSnapshot'
|
||||
import { forwardRoomRequest } from './routes/forwardRoomRequest'
|
||||
|
@ -55,15 +55,7 @@ const router = Router()
|
|||
|
||||
const Worker = {
|
||||
fetch(request: Request, env: Environment, context: ExecutionContext) {
|
||||
const sentry = new Toucan({
|
||||
dsn: env.SENTRY_DSN,
|
||||
context, // Includes 'waitUntil', which is essential for Sentry logs to be delivered. Modules workers do not include 'request' in context -- you'll need to set it separately.
|
||||
request, // request is not included in 'context', so we set it here.
|
||||
requestDataOptions: {
|
||||
allowedHeaders: ['user-agent'],
|
||||
allowedSearchParams: /(.*)/,
|
||||
},
|
||||
})
|
||||
const sentry = createSentry(context, env, request)
|
||||
|
||||
return router
|
||||
.handle(request, env, context)
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
{
|
||||
"path": "../../packages/dotcom-shared"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/worker-shared"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/store"
|
||||
},
|
||||
|
|
|
@ -8,11 +8,11 @@ ip = "0.0.0.0"
|
|||
# these migrations are append-only. you can't change them. if you do need to change something, do so
|
||||
# by creating new migrations
|
||||
[[migrations]]
|
||||
tag = "v1" # Should be unique for each entry
|
||||
tag = "v1" # Should be unique for each entry
|
||||
new_classes = ["TLDrawDurableObject"]
|
||||
|
||||
[[migrations]]
|
||||
tag = "v2"
|
||||
tag = "v2"
|
||||
new_classes = ["TLProWorkspaceDurableObject"]
|
||||
|
||||
[[migrations]]
|
||||
|
@ -44,9 +44,7 @@ name = "TLDR_DOC"
|
|||
class_name = "TLDrawDurableObject"
|
||||
|
||||
[durable_objects]
|
||||
bindings = [
|
||||
{ name = "TLDR_DOC", class_name = "TLDrawDurableObject" },
|
||||
]
|
||||
bindings = [{ name = "TLDR_DOC", class_name = "TLDrawDurableObject" }]
|
||||
|
||||
[[env.preview.durable_objects.bindings]]
|
||||
name = "TLDR_DOC"
|
||||
|
@ -186,3 +184,19 @@ id = "2fb5fc7f7ca54a5a9dfae1b07a30a778"
|
|||
[[env.production.kv_namespaces]]
|
||||
binding = "READONLY_SLUG_TO_SLUG"
|
||||
id = "96be6637b281412ab35b2544539d78e8"
|
||||
|
||||
#################### Version metadata ####################
|
||||
[version_metadata]
|
||||
binding = "CF_VERSION_METADATA"
|
||||
|
||||
[env.dev.version_metadata]
|
||||
binding = "CF_VERSION_METADATA"
|
||||
|
||||
[env.preview.version_metadata]
|
||||
binding = "CF_VERSION_METADATA"
|
||||
|
||||
[env.staging.version_metadata]
|
||||
binding = "CF_VERSION_METADATA"
|
||||
|
||||
[env.production.version_metadata]
|
||||
binding = "CF_VERSION_METADATA"
|
||||
|
|
26
packages/worker-shared/package.json
Normal file
26
packages/worker-shared/package.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@tldraw/worker-shared",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"/* NOTE */": "These `main` and `types` fields are rewritten by the build script. They are not the actual values we publish",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./.tsbuild/index.d.ts",
|
||||
"/* GOTCHA */": "files will include ./dist and index.d.ts by default, add any others you want to include in here",
|
||||
"files": [],
|
||||
"dependencies": {
|
||||
"@cloudflare/workers-types": "^4.20240620.0",
|
||||
"@tldraw/utils": "workspace:*",
|
||||
"lazyrepo": "0.0.0-alpha.27",
|
||||
"toucan-js": "^3.4.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test-ci": "lazy inherit",
|
||||
"test": "yarn run -T jest",
|
||||
"lint": "yarn run -T tsx ../../scripts/lint.ts"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "config/jest/node",
|
||||
"testEnvironment": "jsdom"
|
||||
}
|
||||
}
|
13
packages/worker-shared/src/env.ts
Normal file
13
packages/worker-shared/src/env.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { getOwnProperty } from '@tldraw/utils'
|
||||
|
||||
export function requiredEnv<T extends object>(
|
||||
env: T,
|
||||
keys: { [K in keyof T]: true }
|
||||
): { [K in keyof T]-?: NonNullable<T[K]> } {
|
||||
for (const key of Object.keys(keys)) {
|
||||
if (getOwnProperty(env, key) === undefined) {
|
||||
throw new Error(`Missing required env var: ${key}`)
|
||||
}
|
||||
}
|
||||
return env as any
|
||||
}
|
3
packages/worker-shared/src/index.test.ts
Normal file
3
packages/worker-shared/src/index.test.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
it('works', () => {
|
||||
// we need a test for jest to pass.
|
||||
})
|
4
packages/worker-shared/src/index.ts
Normal file
4
packages/worker-shared/src/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
/// <reference no-default-lib="true"/>
|
||||
/// <reference types="@cloudflare/workers-types" />
|
||||
|
||||
export { createSentry } from './sentry'
|
34
packages/worker-shared/src/sentry.ts
Normal file
34
packages/worker-shared/src/sentry.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { WorkerVersionMetadata } from '@cloudflare/workers-types'
|
||||
import { Toucan } from 'toucan-js'
|
||||
import { requiredEnv } from './env'
|
||||
|
||||
interface Context {
|
||||
waitUntil: ExecutionContext['waitUntil']
|
||||
request?: Request
|
||||
}
|
||||
|
||||
interface SentryEnvironment {
|
||||
readonly SENTRY_DSN: string | undefined
|
||||
readonly WORKER_NAME: string | undefined
|
||||
readonly CF_VERSION_METADATA: WorkerVersionMetadata
|
||||
}
|
||||
|
||||
export function createSentry(ctx: Context, env: SentryEnvironment, request?: Request) {
|
||||
const { SENTRY_DSN, WORKER_NAME, CF_VERSION_METADATA } = requiredEnv(env, {
|
||||
SENTRY_DSN: true,
|
||||
WORKER_NAME: true,
|
||||
CF_VERSION_METADATA: true,
|
||||
})
|
||||
|
||||
return new Toucan({
|
||||
dsn: SENTRY_DSN,
|
||||
release: `${WORKER_NAME}.${CF_VERSION_METADATA.id}`,
|
||||
environment: WORKER_NAME,
|
||||
context: ctx,
|
||||
request,
|
||||
requestDataOptions: {
|
||||
allowedHeaders: ['user-agent'],
|
||||
allowedSearchParams: /(.*)/,
|
||||
},
|
||||
})
|
||||
}
|
14
packages/worker-shared/tsconfig.json
Normal file
14
packages/worker-shared/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../config/tsconfig.base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", ".tsbuild*"],
|
||||
"compilerOptions": {
|
||||
"outDir": "./.tsbuild",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../utils"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -196,6 +196,10 @@ async function deployTlsyncWorker({ dryRun }: { dryRun: boolean }) {
|
|||
APP_ORIGIN: env.APP_ORIGIN,
|
||||
WORKER_NAME: workerId,
|
||||
},
|
||||
sentry: {
|
||||
project: 'tldraw-sync',
|
||||
authToken: env.SENTRY_AUTH_TOKEN,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -6000,13 +6000,13 @@ __metadata:
|
|||
"@tldraw/tlschema": "workspace:*"
|
||||
"@tldraw/tlsync": "workspace:*"
|
||||
"@tldraw/utils": "workspace:*"
|
||||
"@tldraw/worker-shared": "workspace:*"
|
||||
esbuild: "npm:^0.21.5"
|
||||
itty-router: "npm:^4.0.13"
|
||||
lazyrepo: "npm:0.0.0-alpha.27"
|
||||
nanoid: "npm:4.0.2"
|
||||
react: "npm:^18.2.0"
|
||||
react-dom: "npm:^18.2.0"
|
||||
toucan-js: "npm:^3.4.0"
|
||||
typescript: "npm:^5.3.3"
|
||||
wrangler: "npm:3.62.0"
|
||||
languageName: unknown
|
||||
|
@ -6089,13 +6089,13 @@ __metadata:
|
|||
"@tldraw/tlsync": "workspace:*"
|
||||
"@tldraw/utils": "workspace:*"
|
||||
"@tldraw/validate": "workspace:*"
|
||||
"@tldraw/worker-shared": "workspace:*"
|
||||
esbuild: "npm:^0.21.5"
|
||||
itty-router: "npm:^4.0.13"
|
||||
lazyrepo: "npm:0.0.0-alpha.27"
|
||||
nanoid: "npm:4.0.2"
|
||||
react: "npm:^18.2.0"
|
||||
react-dom: "npm:^18.2.0"
|
||||
toucan-js: "npm:^3.4.0"
|
||||
typescript: "npm:^5.3.3"
|
||||
wrangler: "npm:3.62.0"
|
||||
languageName: unknown
|
||||
|
@ -6349,6 +6349,18 @@ __metadata:
|
|||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@tldraw/worker-shared@workspace:*, @tldraw/worker-shared@workspace:packages/worker-shared":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@tldraw/worker-shared@workspace:packages/worker-shared"
|
||||
dependencies:
|
||||
"@cloudflare/workers-types": "npm:^4.20240620.0"
|
||||
"@tldraw/utils": "workspace:*"
|
||||
lazyrepo: "npm:0.0.0-alpha.27"
|
||||
toucan-js: "npm:^3.4.0"
|
||||
typescript: "npm:^5.3.3"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@tootallnate/once@npm:1":
|
||||
version: 1.1.2
|
||||
resolution: "@tootallnate/once@npm:1.1.2"
|
||||
|
|
Loading…
Reference in a new issue