tapimo 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/ApiKey.d.ts +65 -0
- package/dist/ApiKey.d.ts.map +1 -0
- package/dist/ApiKey.js +105 -0
- package/dist/ApiKey.js.map +1 -0
- package/dist/ApiKeySource.d.ts +166 -0
- package/dist/ApiKeySource.d.ts.map +1 -0
- package/dist/ApiKeySource.js +234 -0
- package/dist/ApiKeySource.js.map +1 -0
- package/dist/App.d.ts +19317 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +612 -0
- package/dist/App.js.map +1 -0
- package/dist/Assets.d.ts +44 -0
- package/dist/Assets.d.ts.map +1 -0
- package/dist/Assets.js +23 -0
- package/dist/Assets.js.map +1 -0
- package/dist/Auth.d.ts +2 -0
- package/dist/Auth.d.ts.map +1 -0
- package/dist/Auth.js +2 -0
- package/dist/Auth.js.map +1 -0
- package/dist/Cli.d.ts +21 -0
- package/dist/Cli.d.ts.map +1 -0
- package/dist/Cli.js +13 -0
- package/dist/Cli.js.map +1 -0
- package/dist/Client.d.ts +20 -0
- package/dist/Client.d.ts.map +1 -0
- package/dist/Client.js +24 -0
- package/dist/Client.js.map +1 -0
- package/dist/Metrics.d.ts +70 -0
- package/dist/Metrics.d.ts.map +1 -0
- package/dist/Metrics.js +91 -0
- package/dist/Metrics.js.map +1 -0
- package/dist/Scope.d.ts +35 -0
- package/dist/Scope.d.ts.map +1 -0
- package/dist/Scope.js +38 -0
- package/dist/Scope.js.map +1 -0
- package/dist/Webhooks.d.ts +79 -0
- package/dist/Webhooks.d.ts.map +1 -0
- package/dist/Webhooks.js +107 -0
- package/dist/Webhooks.js.map +1 -0
- package/dist/admin/Access.d.ts +41 -0
- package/dist/admin/Access.d.ts.map +1 -0
- package/dist/admin/Access.js +75 -0
- package/dist/admin/Access.js.map +1 -0
- package/dist/admin/App.d.ts +1221 -0
- package/dist/admin/App.d.ts.map +1 -0
- package/dist/admin/App.js +113 -0
- package/dist/admin/App.js.map +1 -0
- package/dist/admin/apps/api-keys.d.ts +209 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -0
- package/dist/admin/apps/api-keys.js +129 -0
- package/dist/admin/apps/api-keys.js.map +1 -0
- package/dist/admin/apps/scopes.d.ts +46 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -0
- package/dist/admin/apps/scopes.js +41 -0
- package/dist/admin/apps/scopes.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +1206 -0
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -0
- package/dist/admin/apps/verified-tokens.js +485 -0
- package/dist/admin/apps/verified-tokens.js.map +1 -0
- package/dist/admin/index.d.ts +3 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/ui.generated.d.ts +11 -0
- package/dist/admin/ui.generated.d.ts.map +1 -0
- package/dist/admin/ui.generated.js +43 -0
- package/dist/admin/ui.generated.js.map +1 -0
- package/dist/apps/activities.d.ts +18725 -0
- package/dist/apps/activities.d.ts.map +1 -0
- package/dist/apps/activities.js +3138 -0
- package/dist/apps/activities.js.map +1 -0
- package/dist/apps/addresses.d.ts +3662 -0
- package/dist/apps/addresses.d.ts.map +1 -0
- package/dist/apps/addresses.js +22 -0
- package/dist/apps/addresses.js.map +1 -0
- package/dist/apps/balances.d.ts +342 -0
- package/dist/apps/balances.d.ts.map +1 -0
- package/dist/apps/balances.js +393 -0
- package/dist/apps/balances.js.map +1 -0
- package/dist/apps/blocks.d.ts +931 -0
- package/dist/apps/blocks.d.ts.map +1 -0
- package/dist/apps/blocks.js +689 -0
- package/dist/apps/blocks.js.map +1 -0
- package/dist/apps/coingecko.d.ts +1053 -0
- package/dist/apps/coingecko.d.ts.map +1 -0
- package/dist/apps/coingecko.js +1015 -0
- package/dist/apps/coingecko.js.map +1 -0
- package/dist/apps/exchanges.d.ts +3000 -0
- package/dist/apps/exchanges.d.ts.map +1 -0
- package/dist/apps/exchanges.js +3570 -0
- package/dist/apps/exchanges.js.map +1 -0
- package/dist/apps/fee-amm.d.ts +640 -0
- package/dist/apps/fee-amm.d.ts.map +1 -0
- package/dist/apps/fee-amm.js +815 -0
- package/dist/apps/fee-amm.js.map +1 -0
- package/dist/apps/indexer.d.ts +116 -0
- package/dist/apps/indexer.d.ts.map +1 -0
- package/dist/apps/indexer.js +270 -0
- package/dist/apps/indexer.js.map +1 -0
- package/dist/apps/receipts.d.ts +1438 -0
- package/dist/apps/receipts.d.ts.map +1 -0
- package/dist/apps/receipts.js +874 -0
- package/dist/apps/receipts.js.map +1 -0
- package/dist/apps/rpc.d.ts +173 -0
- package/dist/apps/rpc.d.ts.map +1 -0
- package/dist/apps/rpc.js +191 -0
- package/dist/apps/rpc.js.map +1 -0
- package/dist/apps/tokenlist.d.ts +192 -0
- package/dist/apps/tokenlist.d.ts.map +1 -0
- package/dist/apps/tokenlist.js +153 -0
- package/dist/apps/tokenlist.js.map +1 -0
- package/dist/apps/tokens.d.ts +2246 -0
- package/dist/apps/tokens.d.ts.map +1 -0
- package/dist/apps/tokens.js +1789 -0
- package/dist/apps/tokens.js.map +1 -0
- package/dist/apps/transactions.d.ts +2327 -0
- package/dist/apps/transactions.d.ts.map +1 -0
- package/dist/apps/transactions.js +975 -0
- package/dist/apps/transactions.js.map +1 -0
- package/dist/apps/transfers.d.ts +589 -0
- package/dist/apps/transfers.d.ts.map +1 -0
- package/dist/apps/transfers.js +769 -0
- package/dist/apps/transfers.js.map +1 -0
- package/dist/apps/verified-tokens.d.ts +544 -0
- package/dist/apps/verified-tokens.d.ts.map +1 -0
- package/dist/apps/verified-tokens.js +234 -0
- package/dist/apps/verified-tokens.js.map +1 -0
- package/dist/apps/webhooks.d.ts +7684 -0
- package/dist/apps/webhooks.d.ts.map +1 -0
- package/dist/apps/webhooks.js +2112 -0
- package/dist/apps/webhooks.js.map +1 -0
- package/dist/cloudflare.d.ts +32 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +45 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/Auth.d.ts +298 -0
- package/dist/internal/Auth.d.ts.map +1 -0
- package/dist/internal/Auth.js +618 -0
- package/dist/internal/Auth.js.map +1 -0
- package/dist/internal/Cache.d.ts +74 -0
- package/dist/internal/Cache.d.ts.map +1 -0
- package/dist/internal/Cache.js +215 -0
- package/dist/internal/Cache.js.map +1 -0
- package/dist/internal/Cursor.d.ts +79 -0
- package/dist/internal/Cursor.d.ts.map +1 -0
- package/dist/internal/Cursor.js +116 -0
- package/dist/internal/Cursor.js.map +1 -0
- package/dist/internal/EdgeCache.d.ts +59 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -0
- package/dist/internal/EdgeCache.js +174 -0
- package/dist/internal/EdgeCache.js.map +1 -0
- package/dist/internal/Log.d.ts +104 -0
- package/dist/internal/Log.d.ts.map +1 -0
- package/dist/internal/Log.js +118 -0
- package/dist/internal/Log.js.map +1 -0
- package/dist/internal/MetricSink.d.ts +65 -0
- package/dist/internal/MetricSink.d.ts.map +1 -0
- package/dist/internal/MetricSink.js +146 -0
- package/dist/internal/MetricSink.js.map +1 -0
- package/dist/internal/Mpp.d.ts +71 -0
- package/dist/internal/Mpp.d.ts.map +1 -0
- package/dist/internal/Mpp.js +105 -0
- package/dist/internal/Mpp.js.map +1 -0
- package/dist/internal/OpenApi.d.ts +313 -0
- package/dist/internal/OpenApi.d.ts.map +1 -0
- package/dist/internal/OpenApi.fonts.d.ts +2 -0
- package/dist/internal/OpenApi.fonts.d.ts.map +1 -0
- package/dist/internal/OpenApi.fonts.js +39 -0
- package/dist/internal/OpenApi.fonts.js.map +1 -0
- package/dist/internal/OpenApi.js +335 -0
- package/dist/internal/OpenApi.js.map +1 -0
- package/dist/internal/OpenApi.logo.d.ts +6 -0
- package/dist/internal/OpenApi.logo.d.ts.map +1 -0
- package/dist/internal/OpenApi.logo.js +19 -0
- package/dist/internal/OpenApi.logo.js.map +1 -0
- package/dist/internal/Path.d.ts +5 -0
- package/dist/internal/Path.d.ts.map +1 -0
- package/dist/internal/Path.js +16 -0
- package/dist/internal/Path.js.map +1 -0
- package/dist/internal/RateLimit.d.ts +60 -0
- package/dist/internal/RateLimit.d.ts.map +1 -0
- package/dist/internal/RateLimit.js +48 -0
- package/dist/internal/RateLimit.js.map +1 -0
- package/dist/internal/Response.d.ts +132 -0
- package/dist/internal/Response.d.ts.map +1 -0
- package/dist/internal/Response.js +72 -0
- package/dist/internal/Response.js.map +1 -0
- package/dist/internal/Schema.d.ts +257 -0
- package/dist/internal/Schema.d.ts.map +1 -0
- package/dist/internal/Schema.js +360 -0
- package/dist/internal/Schema.js.map +1 -0
- package/dist/internal/Store.d.ts +204 -0
- package/dist/internal/Store.d.ts.map +1 -0
- package/dist/internal/Store.js +291 -0
- package/dist/internal/Store.js.map +1 -0
- package/dist/internal/Tidx.d.ts +120 -0
- package/dist/internal/Tidx.d.ts.map +1 -0
- package/dist/internal/Tidx.js +156 -0
- package/dist/internal/Tidx.js.map +1 -0
- package/dist/internal/Timing.d.ts +22 -0
- package/dist/internal/Timing.d.ts.map +1 -0
- package/dist/internal/Timing.js +32 -0
- package/dist/internal/Timing.js.map +1 -0
- package/dist/internal/Ttl.d.ts +25 -0
- package/dist/internal/Ttl.d.ts.map +1 -0
- package/dist/internal/Ttl.js +49 -0
- package/dist/internal/Ttl.js.map +1 -0
- package/dist/internal/Value.d.ts +47 -0
- package/dist/internal/Value.d.ts.map +1 -0
- package/dist/internal/Value.js +122 -0
- package/dist/internal/Value.js.map +1 -0
- package/dist/internal/VerifiedTokens.d.ts +228 -0
- package/dist/internal/VerifiedTokens.d.ts.map +1 -0
- package/dist/internal/VerifiedTokens.js +450 -0
- package/dist/internal/VerifiedTokens.js.map +1 -0
- package/dist/internal/Viem.d.ts +2082 -0
- package/dist/internal/Viem.d.ts.map +1 -0
- package/dist/internal/Viem.js +63 -0
- package/dist/internal/Viem.js.map +1 -0
- package/dist/internal/WebhookDestination.d.ts +198 -0
- package/dist/internal/WebhookDestination.d.ts.map +1 -0
- package/dist/internal/WebhookDestination.js +170 -0
- package/dist/internal/WebhookDestination.js.map +1 -0
- package/dist/internal/Webhooks.d.ts +433 -0
- package/dist/internal/Webhooks.d.ts.map +1 -0
- package/dist/internal/Webhooks.js +489 -0
- package/dist/internal/Webhooks.js.map +1 -0
- package/dist/internal/webhookDestinations/betterStack.d.ts +26 -0
- package/dist/internal/webhookDestinations/betterStack.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/betterStack.js +76 -0
- package/dist/internal/webhookDestinations/betterStack.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.d.ts +59 -0
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/slack.js +422 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -0
- package/dist/internal/webhookDestinations/url.d.ts +17 -0
- package/dist/internal/webhookDestinations/url.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/url.js +130 -0
- package/dist/internal/webhookDestinations/url.js.map +1 -0
- package/dist/openrpc.json +5302 -0
- package/package.json +46 -4
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
- package/seeds/31318/verified-tokens.json +30 -0
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +4 -0
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +30 -0
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +11 -0
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +1 -0
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +5 -0
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +177 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +1 -0
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +1 -0
- package/seeds/42431/verified-tokens.json +44 -0
- package/seeds/openrpc/README.md +27 -0
- package/seeds/openrpc/execution-apis.json +8989 -0
- package/src/ApiKey.test.ts +91 -0
- package/src/ApiKey.ts +122 -0
- package/src/ApiKeySource.test-d.ts +11 -0
- package/src/ApiKeySource.test.ts +295 -0
- package/src/ApiKeySource.ts +303 -0
- package/src/App.test-d.ts +38 -0
- package/src/App.test.ts +65927 -0
- package/src/App.ts +855 -0
- package/src/Assets.ts +58 -0
- package/src/Auth.ts +1 -0
- package/src/Cli.test.ts +81 -0
- package/src/Cli.ts +38 -0
- package/src/Client.test-d.ts +1438 -0
- package/src/Client.test.ts +134 -0
- package/src/Client.ts +45 -0
- package/src/Metrics.ts +154 -0
- package/src/Scope.ts +50 -0
- package/src/Webhooks.test.ts +49 -0
- package/src/Webhooks.ts +172 -0
- package/src/admin/Access.test.ts +130 -0
- package/src/admin/Access.ts +87 -0
- package/src/admin/App.test.ts +225 -0
- package/src/admin/App.ts +216 -0
- package/src/admin/apps/api-keys.test.ts +156 -0
- package/src/admin/apps/api-keys.ts +157 -0
- package/src/admin/apps/scopes.test.ts +52 -0
- package/src/admin/apps/scopes.ts +47 -0
- package/src/admin/apps/verified-tokens.test.ts +415 -0
- package/src/admin/apps/verified-tokens.ts +566 -0
- package/src/admin/index.ts +2 -0
- package/src/admin/ui/plugin.ts +135 -0
- package/src/admin/ui/src/components/Checkbox.tsx +22 -0
- package/src/admin/ui/src/components/Dialog.tsx +32 -0
- package/src/admin/ui/src/components/MobileProfile.tsx +31 -0
- package/src/admin/ui/src/components/Page.tsx +53 -0
- package/src/admin/ui/src/components/TempoLogo.tsx +37 -0
- package/src/admin/ui/src/fonts/Pilat-Demi.woff2 +0 -0
- package/src/admin/ui/src/fonts/Pilat-Regular.woff2 +0 -0
- package/src/admin/ui/src/lib/api-keys.ts +63 -0
- package/src/admin/ui/src/lib/client.ts +15 -0
- package/src/admin/ui/src/lib/config.ts +57 -0
- package/src/admin/ui/src/lib/query-client.ts +26 -0
- package/src/admin/ui/src/lib/scopes.ts +25 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +89 -0
- package/src/admin/ui/src/lib/wagmi.ts +18 -0
- package/src/admin/ui/src/routeTree.gen.ts +104 -0
- package/src/admin/ui/src/router.tsx +25 -0
- package/src/admin/ui/src/routes/__root.tsx +219 -0
- package/src/admin/ui/src/routes/api-keys.tsx +329 -0
- package/src/admin/ui/src/routes/index.tsx +7 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +331 -0
- package/src/admin/ui/src/styles.css +20 -0
- package/src/admin/ui/tsconfig.json +16 -0
- package/src/admin/ui/vite.config.ts +29 -0
- package/src/admin/ui.generated.ts +60 -0
- package/src/apps/activities.test.ts +1020 -0
- package/src/apps/activities.ts +3934 -0
- package/src/apps/addresses.ts +24 -0
- package/src/apps/balances.test.ts +274 -0
- package/src/apps/balances.ts +533 -0
- package/src/apps/blocks.test.ts +385 -0
- package/src/apps/blocks.ts +896 -0
- package/src/apps/coingecko.test.ts +218 -0
- package/src/apps/coingecko.ts +1383 -0
- package/src/apps/exchanges.test.ts +958 -0
- package/src/apps/exchanges.ts +4773 -0
- package/src/apps/fee-amm.test.ts +321 -0
- package/src/apps/fee-amm.ts +1121 -0
- package/src/apps/indexer.test.ts +153 -0
- package/src/apps/indexer.ts +330 -0
- package/src/apps/receipts.test.ts +285 -0
- package/src/apps/receipts.ts +1193 -0
- package/src/apps/rpc.test.ts +302 -0
- package/src/apps/rpc.ts +222 -0
- package/src/apps/tokenlist.test.ts +80 -0
- package/src/apps/tokenlist.ts +207 -0
- package/src/apps/tokens.test.ts +1062 -0
- package/src/apps/tokens.ts +2292 -0
- package/src/apps/transactions.test.ts +408 -0
- package/src/apps/transactions.ts +1363 -0
- package/src/apps/transfers.test.ts +371 -0
- package/src/apps/transfers.ts +1116 -0
- package/src/apps/verified-tokens.test.ts +114 -0
- package/src/apps/verified-tokens.ts +295 -0
- package/src/apps/webhooks.test.ts +1937 -0
- package/src/apps/webhooks.ts +2926 -0
- package/src/cloudflare.ts +55 -0
- package/src/index.ts +15 -0
- package/src/internal/Auth.test.ts +980 -0
- package/src/internal/Auth.ts +1012 -0
- package/src/internal/Cache.test.ts +240 -0
- package/src/internal/Cache.ts +262 -0
- package/src/internal/Cursor.test.ts +100 -0
- package/src/internal/Cursor.ts +149 -0
- package/src/internal/EdgeCache.test.ts +234 -0
- package/src/internal/EdgeCache.ts +224 -0
- package/src/internal/Errors.ts +14 -0
- package/src/internal/Log.test.ts +244 -0
- package/src/internal/Log.ts +216 -0
- package/src/internal/MetricSink.ts +220 -0
- package/src/internal/Mpp.test.ts +64 -0
- package/src/internal/Mpp.ts +141 -0
- package/src/internal/OpenApi.fonts.ts +38 -0
- package/src/internal/OpenApi.logo.ts +18 -0
- package/src/internal/OpenApi.ts +488 -0
- package/src/internal/Path.test.ts +14 -0
- package/src/internal/Path.ts +15 -0
- package/src/internal/RateLimit.test.ts +93 -0
- package/src/internal/RateLimit.ts +93 -0
- package/src/internal/Response.ts +131 -0
- package/src/internal/Schema.test.ts +34 -0
- package/src/internal/Schema.ts +523 -0
- package/src/internal/Store.test.ts +545 -0
- package/src/internal/Store.ts +526 -0
- package/src/internal/Tidx.local.test.ts +33 -0
- package/src/internal/Tidx.test.ts +294 -0
- package/src/internal/Tidx.ts +238 -0
- package/src/internal/Timing.test.ts +22 -0
- package/src/internal/Timing.ts +62 -0
- package/src/internal/Ttl.test.ts +18 -0
- package/src/internal/Ttl.ts +59 -0
- package/src/internal/Value.ts +114 -0
- package/src/internal/VerifiedTokens.test.ts +333 -0
- package/src/internal/VerifiedTokens.ts +645 -0
- package/src/internal/Viem.test.ts +115 -0
- package/src/internal/Viem.ts +165 -0
- package/src/internal/WebhookDestination.test.ts +648 -0
- package/src/internal/WebhookDestination.ts +331 -0
- package/src/internal/Webhooks.test.ts +668 -0
- package/src/internal/Webhooks.ts +940 -0
- package/src/internal/webhookDestinations/betterStack.ts +91 -0
- package/src/internal/webhookDestinations/slack.ts +496 -0
- package/src/internal/webhookDestinations/url.ts +128 -0
- package/src/openrpc.json +5302 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { Base64 } from 'ox';
|
|
2
|
+
// Per-request headers that must never be persisted in a shared cache entry.
|
|
3
|
+
// `age`/`cf-cache-status` are CDN telemetry stamped by Cloudflare on Cache API
|
|
4
|
+
// hits (e.g. the inner `Cache.response` layer); storing them would freeze a
|
|
5
|
+
// stale `Age` into every copy served from this cache.
|
|
6
|
+
const volatileHeaders = [
|
|
7
|
+
'age',
|
|
8
|
+
'cf-cache-status',
|
|
9
|
+
'content-encoding',
|
|
10
|
+
'content-length',
|
|
11
|
+
'server-timing',
|
|
12
|
+
'set-cookie',
|
|
13
|
+
'ratelimit-limit',
|
|
14
|
+
'ratelimit-remaining',
|
|
15
|
+
'ratelimit-reset',
|
|
16
|
+
'tempo-request-id',
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Serves GET responses from the edge cache store BEFORE auth and rate-limiting
|
|
20
|
+
* run, so cache hits skip the per-request store round-trips that dominate
|
|
21
|
+
* latency — for every caller, authenticated or not. Place this ahead of the
|
|
22
|
+
* auth middleware.
|
|
23
|
+
*
|
|
24
|
+
* Only 2xx responses from routes that opted into caching (via `Cache.response`,
|
|
25
|
+
* which publishes the `edgeCache` policy) are stored, and the policy is only
|
|
26
|
+
* published for routes whose responses are public and URL-keyed (no per-principal
|
|
27
|
+
* data), so a single shared entry is safe to serve to all callers. The trade-off
|
|
28
|
+
* is that cache hits bypass origin metering: they are not counted against
|
|
29
|
+
* rate-limit quotas.
|
|
30
|
+
*
|
|
31
|
+
* The cache is a plain `Store.Store` — the same store the origin read cache uses
|
|
32
|
+
* — holding the response serialized to a string under a URL key. It is a no-op
|
|
33
|
+
* when no store is supplied.
|
|
34
|
+
*
|
|
35
|
+
* Standard request `Cache-Control` directives let a caller invalidate without an
|
|
36
|
+
* out-of-band purge: `no-cache` forces a refresh (skip the stored hit, re-fetch,
|
|
37
|
+
* overwrite the entry) and `no-store` bypasses the cache entirely. Both fall
|
|
38
|
+
* through to the origin and are metered normally. The store is colo-local, so a
|
|
39
|
+
* refresh only affects the data center serving that request.
|
|
40
|
+
*/
|
|
41
|
+
export function middleware(options = {}) {
|
|
42
|
+
return async (c, next) => {
|
|
43
|
+
const { store } = options;
|
|
44
|
+
const eligible = store !== undefined && c.req.method === 'GET' && !c.req.raw.headers.has('range');
|
|
45
|
+
const key = eligible ? cacheKey(c.req.url) : undefined;
|
|
46
|
+
// Honor the standard request `Cache-Control` directives so a caller can
|
|
47
|
+
// refresh a stale entry on the colo serving them without any out-of-band
|
|
48
|
+
// purge: `no-cache` skips the stored hit but still re-stores the fresh
|
|
49
|
+
// response (revalidate), and `no-store` bypasses the cache on both sides.
|
|
50
|
+
// `Pragma: no-cache` is the HTTP/1.0 fallback, honored only when
|
|
51
|
+
// `Cache-Control` is absent (RFC 9111 §5.4). A forced miss falls through
|
|
52
|
+
// to `next()` and is metered like any other origin request, so this is
|
|
53
|
+
// not an unmetered-access vector.
|
|
54
|
+
const directives = (c.req.header('cache-control') ?? c.req.header('pragma') ?? '').toLowerCase();
|
|
55
|
+
const noStore = directives.includes('no-store');
|
|
56
|
+
const noCache = noStore || directives.includes('no-cache');
|
|
57
|
+
if (store && key && !noCache) {
|
|
58
|
+
const hit = await store.get(key);
|
|
59
|
+
if (hit) {
|
|
60
|
+
// Mark the hit for the canonical request log line; routing never runs
|
|
61
|
+
// for hits, so this is the only signal that the cache answered.
|
|
62
|
+
c.set('edgeCacheStatus', 'hit');
|
|
63
|
+
return serveHit(c.req.header('if-none-match'), hit);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
await next();
|
|
67
|
+
if (!store || !key || noStore)
|
|
68
|
+
return;
|
|
69
|
+
const policy = c.get('edgeCache');
|
|
70
|
+
if (!policy)
|
|
71
|
+
return;
|
|
72
|
+
if (c.res.status < 200 || c.res.status >= 300)
|
|
73
|
+
return;
|
|
74
|
+
if (c.res.headers.has('set-cookie'))
|
|
75
|
+
return;
|
|
76
|
+
if (c.res.headers.get('content-type')?.includes('text/event-stream'))
|
|
77
|
+
return;
|
|
78
|
+
// Store a public, sanitized copy; the client still receives the original
|
|
79
|
+
// (private, metered) response for this miss.
|
|
80
|
+
const value = await serialize(c.res, policy);
|
|
81
|
+
const put = store.put(key, value, { ttl: policy.maxAge * 1_000 });
|
|
82
|
+
const waitUntil = getWaitUntil(c);
|
|
83
|
+
if (waitUntil)
|
|
84
|
+
waitUntil(put);
|
|
85
|
+
else
|
|
86
|
+
await put.catch(() => { });
|
|
87
|
+
return;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async function serialize(response, policy) {
|
|
91
|
+
const headers = new Headers(response.headers);
|
|
92
|
+
for (const name of volatileHeaders)
|
|
93
|
+
headers.delete(name);
|
|
94
|
+
headers.set('Cache-Control', cacheControl(policy));
|
|
95
|
+
headers.set('Vary', 'Accept-Encoding');
|
|
96
|
+
// The store is text-only, so binary bodies (e.g. PNG token logos) must be
|
|
97
|
+
// base64-encoded or the round trip through `.text()` corrupts them. Text
|
|
98
|
+
// bodies (JSON, SVG, HTML) stay verbatim to avoid the 33% base64 overhead.
|
|
99
|
+
const textual = isTextual(headers.get('content-type'));
|
|
100
|
+
const stored = {
|
|
101
|
+
body: textual
|
|
102
|
+
? await response.clone().text()
|
|
103
|
+
: Base64.fromBytes(new Uint8Array(await response.clone().arrayBuffer())),
|
|
104
|
+
...(textual ? {} : { encoding: 'base64' }),
|
|
105
|
+
headers: [...headers],
|
|
106
|
+
status: response.status,
|
|
107
|
+
};
|
|
108
|
+
return JSON.stringify(stored);
|
|
109
|
+
}
|
|
110
|
+
function serveHit(ifNoneMatch, value) {
|
|
111
|
+
const { body, encoding, headers, status } = JSON.parse(value);
|
|
112
|
+
const responseHeaders = new Headers(headers);
|
|
113
|
+
const etag = responseHeaders.get('etag');
|
|
114
|
+
if (etag && ifNoneMatch && etagMatches(etag, ifNoneMatch)) {
|
|
115
|
+
const notModified = new Headers();
|
|
116
|
+
for (const name of ['Cache-Control', 'ETag', 'Vary']) {
|
|
117
|
+
const header = responseHeaders.get(name);
|
|
118
|
+
if (header)
|
|
119
|
+
notModified.set(name, header);
|
|
120
|
+
}
|
|
121
|
+
return new Response(null, { headers: notModified, status: 304, statusText: 'Not Modified' });
|
|
122
|
+
}
|
|
123
|
+
if (encoding === 'base64') {
|
|
124
|
+
// Copy the decoded bytes into an exact `ArrayBuffer`: `Base64.toBytes`
|
|
125
|
+
// returns a `Uint8Array` view, which this TS lib does not accept as a
|
|
126
|
+
// `BodyInit`.
|
|
127
|
+
const bytes = Base64.toBytes(body);
|
|
128
|
+
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
129
|
+
new Uint8Array(buffer).set(bytes);
|
|
130
|
+
return new Response(buffer, { headers: responseHeaders, status });
|
|
131
|
+
}
|
|
132
|
+
return new Response(body, { headers: responseHeaders, status });
|
|
133
|
+
}
|
|
134
|
+
// A body is safe to store as verbatim text when its content type is textual;
|
|
135
|
+
// everything else (images, octet-stream) is treated as binary and base64-coded.
|
|
136
|
+
function isTextual(contentType) {
|
|
137
|
+
if (!contentType)
|
|
138
|
+
return false;
|
|
139
|
+
return /^(?:text\/|application\/(?:json|xml|javascript|[\w.-]+\+(?:json|xml))|image\/svg\+xml)/i.test(contentType);
|
|
140
|
+
}
|
|
141
|
+
// Sort query params so semantically identical URLs share one cache entry.
|
|
142
|
+
function cacheKey(requestUrl) {
|
|
143
|
+
const url = new URL(requestUrl);
|
|
144
|
+
url.searchParams.sort();
|
|
145
|
+
return url.toString();
|
|
146
|
+
}
|
|
147
|
+
function getWaitUntil(c) {
|
|
148
|
+
// `c.executionCtx` throws on runtimes without one (e.g. Node), so probe it
|
|
149
|
+
// defensively and fall back to awaiting the write inline.
|
|
150
|
+
try {
|
|
151
|
+
const ctx = c.executionCtx;
|
|
152
|
+
return ctx ? ctx.waitUntil.bind(ctx) : undefined;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function etagMatches(etag, ifNoneMatch) {
|
|
159
|
+
const strip = (tag) => tag.trim().replace(/^W\//, '');
|
|
160
|
+
return ifNoneMatch.split(',').some((tag) => strip(tag) === strip(etag));
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Builds the shared-cache `Cache-Control` value for a stored copy: `public`
|
|
164
|
+
* with `max-age`/`s-maxage` bound to the policy plus an optional
|
|
165
|
+
* `stale-while-revalidate` window. Used for this layer's stored copies and by
|
|
166
|
+
* `Cache.response` to bound the inner response cache's entry lifetime.
|
|
167
|
+
*/
|
|
168
|
+
export function cacheControl(policy) {
|
|
169
|
+
const directives = ['public', `max-age=${policy.maxAge}`, `s-maxage=${policy.maxAge}`];
|
|
170
|
+
if (policy.staleWhileRevalidate)
|
|
171
|
+
directives.push(`stale-while-revalidate=${policy.staleWhileRevalidate}`);
|
|
172
|
+
return directives.join(', ');
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=EdgeCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EdgeCache.js","sourceRoot":"","sources":["../../src/internal/EdgeCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { RequestIdVariables } from 'hono/request-id';
|
|
3
|
+
import * as ApiKey from '../ApiKey.js';
|
|
4
|
+
import type * as Auth from './Auth.js';
|
|
5
|
+
import type * as EdgeCache from './EdgeCache.js';
|
|
6
|
+
import type * as Timing from './Timing.js';
|
|
7
|
+
/** Hono variables read by the request logger and written by other layers. */
|
|
8
|
+
export type Variables = {
|
|
9
|
+
/** Stable error code recorded by `Response.error` for the request log entry. */
|
|
10
|
+
errorCode?: string | undefined;
|
|
11
|
+
};
|
|
12
|
+
/** Hono environment shape used by the request logger. */
|
|
13
|
+
export type Environment = {
|
|
14
|
+
Variables: Variables & EdgeCache.Variables & RequestIdVariables & Timing.Variables & {
|
|
15
|
+
/** Authenticated or anonymous caller, set by auth middleware. */
|
|
16
|
+
principal?: Auth.Principal | undefined;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
/** Log level, derived from the response status. */
|
|
20
|
+
export type Level = 'error' | 'info' | 'warn';
|
|
21
|
+
/** One canonical request log entry. */
|
|
22
|
+
export type Entry = {
|
|
23
|
+
/** `'hit'` when the edge response cache served the request without reaching the origin handlers. */
|
|
24
|
+
cache?: 'hit' | undefined;
|
|
25
|
+
/** Total request duration in milliseconds. */
|
|
26
|
+
duration: number;
|
|
27
|
+
/** Stable error code when the response is a JSON error envelope (e.g. `not_found`, `api_key_invalid`). */
|
|
28
|
+
errorCode?: string | undefined;
|
|
29
|
+
/** Log level derived from the response status: 5xx `error`, 4xx `warn`, else `info`. */
|
|
30
|
+
level: Level;
|
|
31
|
+
/** Request method. */
|
|
32
|
+
method: string;
|
|
33
|
+
/** Request pathname. */
|
|
34
|
+
path: string;
|
|
35
|
+
/** MPP payment reason when the request was paid per call. */
|
|
36
|
+
payment?: Auth.Payment['reason'] | undefined;
|
|
37
|
+
/** Caller identity. Raw API-key tokens are never logged. */
|
|
38
|
+
principal?: {
|
|
39
|
+
/** Key environment for API-key callers. */
|
|
40
|
+
environment?: ApiKey.ApiKey['environment'] | undefined;
|
|
41
|
+
/** Principal id: the API key id, or the public quota identity. */
|
|
42
|
+
id: string;
|
|
43
|
+
/** Owning organization id for API-key callers. */
|
|
44
|
+
orgId?: string | undefined;
|
|
45
|
+
/** Principal kind. */
|
|
46
|
+
type: 'api_key' | 'public';
|
|
47
|
+
} | undefined;
|
|
48
|
+
/** Raw query string (no leading `?`) with API-key tokens redacted, when present. */
|
|
49
|
+
query?: string | undefined;
|
|
50
|
+
/** Rate limit state from the `RateLimit-*` response headers, when enforced. */
|
|
51
|
+
rateLimit?: {
|
|
52
|
+
/** Quota for the current window. */
|
|
53
|
+
limit: number;
|
|
54
|
+
/** Requests remaining in the current window. */
|
|
55
|
+
remaining: number;
|
|
56
|
+
/** Reset timestamp in Unix seconds. */
|
|
57
|
+
reset?: number | undefined;
|
|
58
|
+
/** Quota bucket scope, when available. */
|
|
59
|
+
scope?: string | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
/** Request id, also echoed in the `tempo-request-id` response header. */
|
|
62
|
+
requestId: string;
|
|
63
|
+
/** Matched handler path (bounded cardinality), e.g. `/v1/tokens/:address`; `/*` when a middleware (e.g. an edge-cache hit) short-circuited routing. */
|
|
64
|
+
route: string;
|
|
65
|
+
/** Response status code. */
|
|
66
|
+
status: number;
|
|
67
|
+
/** Upstream operation durations in milliseconds, from the request's Server-Timing metrics (e.g. RPC and TIDX calls). */
|
|
68
|
+
timings?: Record<string, number> | undefined;
|
|
69
|
+
};
|
|
70
|
+
/** Sink receiving one {@link Entry} per request. */
|
|
71
|
+
export type Emit = (entry: Entry) => Promise<void> | void;
|
|
72
|
+
/**
|
|
73
|
+
* Emits one canonical structured log entry per request, after the response is
|
|
74
|
+
* written. Register after `requestId()` and before the timing and edge-cache
|
|
75
|
+
* layers so the entry covers edge-cache hits and includes the Server-Timing
|
|
76
|
+
* metrics collected inside the request.
|
|
77
|
+
*
|
|
78
|
+
* The entry derives everything from state other layers already produce —
|
|
79
|
+
* `requestId`, the auth principal, `RateLimit-*` headers, Server-Timing
|
|
80
|
+
* metrics, the `errorCode` recorded by `Response.error`, and the edge-cache
|
|
81
|
+
* hit marker — so handlers never log per-request lines themselves.
|
|
82
|
+
*/
|
|
83
|
+
export declare function middleware<environment extends Environment = Environment>(options?: middleware.Options): MiddlewareHandler<environment>;
|
|
84
|
+
export declare namespace middleware {
|
|
85
|
+
/** Options for the request logger middleware. */
|
|
86
|
+
type Options = {
|
|
87
|
+
/** Log sink. Defaults to {@link emit}: the level-matched console method, passed the entry as a structured object. */
|
|
88
|
+
emit?: Emit | undefined;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Default log sink: writes the entry as a structured object through the
|
|
93
|
+
* console method matching its level. Passing the object (not a pre-serialized
|
|
94
|
+
* JSON string) lets Cloudflare Workers Logs index the fields for filtering
|
|
95
|
+
* and querying; Node prints the same object inline on stdout/stderr.
|
|
96
|
+
*/
|
|
97
|
+
export declare function emit(entry: Entry): void;
|
|
98
|
+
/**
|
|
99
|
+
* An {@link Emit} that drops entries below `min` and otherwise delegates to
|
|
100
|
+
* {@link emit}. `'warn'` keeps warn/error (e.g. production, where the request
|
|
101
|
+
* metrics sink carries successful-request volume instead of one info log each).
|
|
102
|
+
*/
|
|
103
|
+
export declare function withMinLevel(min: Level): Emit;
|
|
104
|
+
//# sourceMappingURL=Log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Log.d.ts","sourceRoot":"","sources":["../../src/internal/Log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as ApiKey from '../ApiKey.js';
|
|
2
|
+
/**
|
|
3
|
+
* Emits one canonical structured log entry per request, after the response is
|
|
4
|
+
* written. Register after `requestId()` and before the timing and edge-cache
|
|
5
|
+
* layers so the entry covers edge-cache hits and includes the Server-Timing
|
|
6
|
+
* metrics collected inside the request.
|
|
7
|
+
*
|
|
8
|
+
* The entry derives everything from state other layers already produce —
|
|
9
|
+
* `requestId`, the auth principal, `RateLimit-*` headers, Server-Timing
|
|
10
|
+
* metrics, the `errorCode` recorded by `Response.error`, and the edge-cache
|
|
11
|
+
* hit marker — so handlers never log per-request lines themselves.
|
|
12
|
+
*/
|
|
13
|
+
export function middleware(options = {}) {
|
|
14
|
+
const fn = options.emit ?? emit;
|
|
15
|
+
return async (c, next) => {
|
|
16
|
+
const start = performance.now();
|
|
17
|
+
await next();
|
|
18
|
+
const duration = performance.now() - start;
|
|
19
|
+
const url = new URL(c.req.url);
|
|
20
|
+
const status = c.res.status;
|
|
21
|
+
// Hono cannot resolve variable types through the generic `environment`,
|
|
22
|
+
// so shared-variable reads are cast from the environment contract above
|
|
23
|
+
// (the same pattern EdgeCache uses for its cross-layer reads).
|
|
24
|
+
const principal = c.get('principal');
|
|
25
|
+
const errorCode = c.get('errorCode');
|
|
26
|
+
// The `request` total metric duplicates `duration` (measured here, one
|
|
27
|
+
// layer further out), so only operation timings are kept.
|
|
28
|
+
const metrics = c.get('serverTiming')?.filter((metric) => metric.name !== 'request');
|
|
29
|
+
const timings = metrics?.length
|
|
30
|
+
? Object.fromEntries(metrics.map((metric) => [metric.name, round(metric.duration)]))
|
|
31
|
+
: undefined;
|
|
32
|
+
const rateLimit = (() => {
|
|
33
|
+
const limit = c.res.headers.get('RateLimit-Limit');
|
|
34
|
+
const remaining = c.res.headers.get('RateLimit-Remaining');
|
|
35
|
+
const reset = c.res.headers.get('RateLimit-Reset');
|
|
36
|
+
const scope = c.res.headers.get('RateLimit-Scope');
|
|
37
|
+
if (limit === null || remaining === null)
|
|
38
|
+
return undefined;
|
|
39
|
+
return {
|
|
40
|
+
limit: Number(limit),
|
|
41
|
+
remaining: Number(remaining),
|
|
42
|
+
...(reset === null ? {} : { reset: Number(reset) }),
|
|
43
|
+
...(scope === null ? {} : { scope }),
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
const result = fn({
|
|
47
|
+
...(c.get('edgeCacheStatus') === 'hit' ? { cache: 'hit' } : {}),
|
|
48
|
+
duration: round(duration),
|
|
49
|
+
...(errorCode === undefined ? {} : { errorCode }),
|
|
50
|
+
level: status >= 500 ? 'error' : status >= 400 ? 'warn' : 'info',
|
|
51
|
+
method: c.req.method,
|
|
52
|
+
path: url.pathname,
|
|
53
|
+
...(principal?.payment === undefined ? {} : { payment: principal.payment.reason }),
|
|
54
|
+
...(principal === undefined
|
|
55
|
+
? {}
|
|
56
|
+
: {
|
|
57
|
+
principal: {
|
|
58
|
+
...(principal.type === 'api_key' ? { environment: principal.environment } : {}),
|
|
59
|
+
id: principal.id,
|
|
60
|
+
...(principal.type === 'api_key' ? { orgId: principal.orgId } : {}),
|
|
61
|
+
type: principal.type,
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
// Keys belong in headers, but a confused client may pass one in the
|
|
65
|
+
// query string; redact defensively before it reaches a log store.
|
|
66
|
+
...(url.search.length > 1 ? { query: ApiKey.redact(url.search.slice(1)) } : {}),
|
|
67
|
+
...(rateLimit === undefined ? {} : { rateLimit }),
|
|
68
|
+
requestId: c.get('requestId'),
|
|
69
|
+
route: c.req.routePath,
|
|
70
|
+
status,
|
|
71
|
+
...(timings === undefined ? {} : { timings }),
|
|
72
|
+
});
|
|
73
|
+
if (result instanceof Promise) {
|
|
74
|
+
const promise = result.catch((error) => console.error('request log sink failed', error));
|
|
75
|
+
// Unit tests and non-Worker runtimes do not always provide an execution
|
|
76
|
+
// context. In Workers, waitUntil keeps async sinks alive without holding
|
|
77
|
+
// the response open; elsewhere the promise is deliberately fire-and-forget.
|
|
78
|
+
try {
|
|
79
|
+
c.executionCtx.waitUntil(promise);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
void promise;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Default log sink: writes the entry as a structured object through the
|
|
89
|
+
* console method matching its level. Passing the object (not a pre-serialized
|
|
90
|
+
* JSON string) lets Cloudflare Workers Logs index the fields for filtering
|
|
91
|
+
* and querying; Node prints the same object inline on stdout/stderr.
|
|
92
|
+
*/
|
|
93
|
+
export function emit(entry) {
|
|
94
|
+
if (entry.level === 'error')
|
|
95
|
+
console.error(entry);
|
|
96
|
+
else if (entry.level === 'warn')
|
|
97
|
+
console.warn(entry);
|
|
98
|
+
else
|
|
99
|
+
console.log(entry);
|
|
100
|
+
}
|
|
101
|
+
/** Severity ranking used to filter entries below a minimum level. */
|
|
102
|
+
const severity = { error: 2, info: 0, warn: 1 };
|
|
103
|
+
/**
|
|
104
|
+
* An {@link Emit} that drops entries below `min` and otherwise delegates to
|
|
105
|
+
* {@link emit}. `'warn'` keeps warn/error (e.g. production, where the request
|
|
106
|
+
* metrics sink carries successful-request volume instead of one info log each).
|
|
107
|
+
*/
|
|
108
|
+
export function withMinLevel(min) {
|
|
109
|
+
return (entry) => {
|
|
110
|
+
if (severity[entry.level] < severity[min])
|
|
111
|
+
return;
|
|
112
|
+
emit(entry);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function round(value) {
|
|
116
|
+
return Math.round(value * 10) / 10;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=Log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Log.js","sourceRoot":"","sources":["../../src/internal/Log.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AAkFtC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CACxB,OAAO,GAAuB,EAAE;IAEhC,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAA;IAC/B,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QAC/B,MAAM,IAAI,EAAE,CAAA;QACZ,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAA;QAE1C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAA;QAC3B,wEAAwE;QACxE,wEAAwE;QACxE,+DAA+D;QAC/D,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAoB,CAA+B,CAAA;QAC3E,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAoB,CAAuB,CAAA;QAEnE,uEAAuE;QACvE,0DAA0D;QAC1D,MAAM,OAAO,GAAI,CAAC,CAAC,GAAG,CAAC,cAAuB,CAAiC,EAAE,MAAM,CACrF,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CACtC,CAAA;QACD,MAAM,OAAO,GAAG,OAAO,EAAE,MAAM;YAC7B,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACpF,CAAC,CAAC,SAAS,CAAA;QAEb,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE;YACtB,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;YAClD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;YAC1D,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;YAClD,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;YAClD,IAAI,KAAK,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI;gBAAE,OAAO,SAAS,CAAA;YAC1D,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;gBACpB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC;gBAC5B,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnD,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;aACrC,CAAA;QACH,CAAC,CAAC,EAAE,CAAA;QAEJ,MAAM,MAAM,GAAG,EAAE,CAAC;YAChB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,iBAA0B,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjF,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC;YACzB,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;YACjD,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAChE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM;YACpB,IAAI,EAAE,GAAG,CAAC,QAAQ;YAClB,GAAG,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAClF,GAAG,CAAC,SAAS,KAAK,SAAS;gBACzB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,SAAS,EAAE;wBACT,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC/E,EAAE,EAAE,SAAS,CAAC,EAAE;wBAChB,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACnE,IAAI,EAAE,SAAS,CAAC,IAAI;qBACrB;iBACF,CAAC;YACN,oEAAoE;YACpE,kEAAkE;YAClE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;YACjD,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,WAAoB,CAAW;YAChD,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS;YACtB,MAAM;YACN,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;SAC9C,CAAC,CAAA;QAEF,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC,CAAA;YACxF,wEAAwE;YACxE,yEAAyE;YACzE,4EAA4E;YAC5E,IAAI,CAAC;gBACH,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,KAAK,OAAO,CAAA;YACd,CAAC;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAUD;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,KAAY;IAC/B,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO;QAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;SAC5C,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;;QAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AACzB,CAAC;AAED,qEAAqE;AACrE,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAW,CAAA;AAExD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAU;IACrC,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAM;QACjD,IAAI,CAAC,KAAK,CAAC,CAAA;IACb,CAAC,CAAA;AACH,CAAC;AAED,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;AACpC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Metrics } from '../Metrics.js';
|
|
2
|
+
import type * as Webhooks from '../Webhooks.js';
|
|
3
|
+
import type * as Log from './Log.js';
|
|
4
|
+
/** Webhook event type, including the synthetic `ping` carried on test envelopes. */
|
|
5
|
+
export type EventType = Webhooks.Envelope['type'];
|
|
6
|
+
/** Where a delivery attempt originated. */
|
|
7
|
+
export type Trigger = 'manual_retry' | 'ping' | 'queue';
|
|
8
|
+
/** Context for one poller tick that the {@link Webhooks.createPoller.Result} omits. */
|
|
9
|
+
export type TickMeta = {
|
|
10
|
+
/** Chain polled this tick; used when the tick errored before a result existed. */
|
|
11
|
+
chainId?: number | undefined;
|
|
12
|
+
/** Wall-clock duration of the tick in ms. */
|
|
13
|
+
durationMs: number;
|
|
14
|
+
/** Whether the tick completed. */
|
|
15
|
+
outcome: 'error' | 'ok';
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A webhook metric event, recorded by the {@link webhooks} sink. The poller
|
|
19
|
+
* emits `webhook:tick`/`webhook:enqueue` and the delivery path emits
|
|
20
|
+
* `webhook:delivery`.
|
|
21
|
+
*/
|
|
22
|
+
export type WebhookEvent = {
|
|
23
|
+
meta: TickMeta;
|
|
24
|
+
result: Webhooks.createPoller.Result | undefined;
|
|
25
|
+
type: 'webhook:tick';
|
|
26
|
+
} | {
|
|
27
|
+
chainId: number;
|
|
28
|
+
durationMs: number;
|
|
29
|
+
eventType: EventType;
|
|
30
|
+
ok: boolean;
|
|
31
|
+
type: 'webhook:enqueue';
|
|
32
|
+
} | {
|
|
33
|
+
envelope: Webhooks.Envelope;
|
|
34
|
+
result: Webhooks.Result;
|
|
35
|
+
subscription: Webhooks.Subscription;
|
|
36
|
+
trigger: Trigger;
|
|
37
|
+
type: 'webhook:delivery';
|
|
38
|
+
};
|
|
39
|
+
/** Records request (HTTP) metrics for one request-log entry. Built by {@link requests}. */
|
|
40
|
+
export type RequestSink = (entry: Log.Entry) => void;
|
|
41
|
+
/** Records webhook reliability metrics. Built by {@link webhooks}. */
|
|
42
|
+
export type WebhookSink = {
|
|
43
|
+
/** Ships buffered metrics (call once per poller tick / delivery). */
|
|
44
|
+
flush(): void;
|
|
45
|
+
/** Records one webhook event. */
|
|
46
|
+
record(event: WebhookEvent): void;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Builds a request (HTTP) metrics sink over `backend`: emits the bounded Worker
|
|
50
|
+
* metrics derived from one request-log entry, then flushes (one entry == one
|
|
51
|
+
* request).
|
|
52
|
+
*
|
|
53
|
+
* Metric tags deliberately exclude caller ids, organization ids, request ids,
|
|
54
|
+
* raw paths, and IP-derived identities — those belong in logs or analytics, not
|
|
55
|
+
* StatsD-style series.
|
|
56
|
+
*/
|
|
57
|
+
export declare function requests(backend: Metrics): RequestSink;
|
|
58
|
+
/**
|
|
59
|
+
* Builds a webhook delivery-reliability sink over `backend`. Tags stay
|
|
60
|
+
* low-cardinality (`chain_id`, `event_type`, `destination_type`, `status_class`,
|
|
61
|
+
* `attempt_bucket`, `outcome`) — never subscription/org/event ids, which belong
|
|
62
|
+
* in logs or analytics, not StatsD-style series.
|
|
63
|
+
*/
|
|
64
|
+
export declare function webhooks(backend: Metrics): WebhookSink;
|
|
65
|
+
//# sourceMappingURL=MetricSink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricSink.d.ts","sourceRoot":"","sources":["../../src/internal/MetricSink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC/C,OAAO,KAAK,KAAK,GAAG,MAAM,UAAU,CAAA;AAEpC,oFAAoF;AACpF,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAEjD,2CAA2C;AAC3C,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,OAAO,CAAA;AAEvD,uFAAuF;AACvF,MAAM,MAAM,QAAQ,GAAG;IACrB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CACxB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,GAAG,SAAS,CAAA;IAChD,IAAI,EAAE,cAAc,CAAA;CACrB,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,CAAA;IACpB,EAAE,EAAE,OAAO,CAAA;IACX,IAAI,EAAE,iBAAiB,CAAA;CACxB,GACD;IACE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAA;IAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAA;IACvB,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAA;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,kBAAkB,CAAA;CACzB,CAAA;AAEL,2FAA2F;AAC3F,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,IAAI,CAAA;AAEpD,sEAAsE;AACtE,MAAM,MAAM,WAAW,GAAG;IACxB,qEAAqE;IACrE,KAAK,IAAI,IAAI,CAAA;IACb,iCAAiC;IACjC,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;CAClC,CAAA;AAWD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAwBtD;AAqBD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAqEtD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a request (HTTP) metrics sink over `backend`: emits the bounded Worker
|
|
3
|
+
* metrics derived from one request-log entry, then flushes (one entry == one
|
|
4
|
+
* request).
|
|
5
|
+
*
|
|
6
|
+
* Metric tags deliberately exclude caller ids, organization ids, request ids,
|
|
7
|
+
* raw paths, and IP-derived identities — those belong in logs or analytics, not
|
|
8
|
+
* StatsD-style series.
|
|
9
|
+
*/
|
|
10
|
+
export function requests(backend) {
|
|
11
|
+
return (entry) => {
|
|
12
|
+
const tags = routeTags(entry);
|
|
13
|
+
backend.count('http_response_count', 1, {
|
|
14
|
+
...tags,
|
|
15
|
+
...(entry.errorCode === undefined ? {} : { error_code: entry.errorCode }),
|
|
16
|
+
...(entry.payment === undefined ? {} : { payment: entry.payment }),
|
|
17
|
+
status: entry.status,
|
|
18
|
+
});
|
|
19
|
+
backend.histogram('http_response_duration_ms', entry.duration, tags);
|
|
20
|
+
if (entry.status === 429 || entry.errorCode === 'rate_limit_exceeded')
|
|
21
|
+
backend.count('http_rate_limit_count', 1, {
|
|
22
|
+
...tags,
|
|
23
|
+
rate_limit_scope: entry.rateLimit?.scope ?? 'unknown',
|
|
24
|
+
status: entry.status,
|
|
25
|
+
});
|
|
26
|
+
for (const [operation, duration] of Object.entries(entry.timings ?? {}))
|
|
27
|
+
backend.histogram('upstream_duration_ms', duration, { ...tags, operation });
|
|
28
|
+
backend.flush();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function routeTags(entry) {
|
|
32
|
+
return {
|
|
33
|
+
cache: entry.cache ?? 'miss',
|
|
34
|
+
method: entry.method,
|
|
35
|
+
principal_environment: entry.principal?.environment ?? 'none',
|
|
36
|
+
principal_type: entry.principal?.type ?? 'unknown',
|
|
37
|
+
route: entry.route,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Builds a webhook delivery-reliability sink over `backend`. Tags stay
|
|
42
|
+
* low-cardinality (`chain_id`, `event_type`, `destination_type`, `status_class`,
|
|
43
|
+
* `attempt_bucket`, `outcome`) — never subscription/org/event ids, which belong
|
|
44
|
+
* in logs or analytics, not StatsD-style series.
|
|
45
|
+
*/
|
|
46
|
+
export function webhooks(backend) {
|
|
47
|
+
return {
|
|
48
|
+
flush() {
|
|
49
|
+
backend.flush();
|
|
50
|
+
},
|
|
51
|
+
record(event) {
|
|
52
|
+
switch (event.type) {
|
|
53
|
+
case 'webhook:tick': {
|
|
54
|
+
const { meta, result } = event;
|
|
55
|
+
const chain_id = String(result?.chainId ?? meta.chainId ?? 'unknown');
|
|
56
|
+
backend.count('webhook_poller_tick_count', 1, { chain_id, outcome: meta.outcome });
|
|
57
|
+
backend.histogram('webhook_poller_tick_duration_ms', meta.durationMs, {
|
|
58
|
+
chain_id,
|
|
59
|
+
outcome: meta.outcome,
|
|
60
|
+
});
|
|
61
|
+
if (!result)
|
|
62
|
+
return;
|
|
63
|
+
backend.histogram('webhook_poller_subscription_count', result.subscriptions, { chain_id });
|
|
64
|
+
backend.count('webhook_poller_scanned_count', result.scanned, { chain_id });
|
|
65
|
+
backend.gauge('webhook_poller_safe_block', result.safeBlock, { chain_id });
|
|
66
|
+
backend.count('webhook_poller_dispatch_count', result.dispatched, {
|
|
67
|
+
chain_id,
|
|
68
|
+
outcome: 'dispatched',
|
|
69
|
+
});
|
|
70
|
+
backend.count('webhook_poller_dispatch_count', result.failed, {
|
|
71
|
+
chain_id,
|
|
72
|
+
outcome: 'failed',
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
case 'webhook:enqueue': {
|
|
77
|
+
const tags = { chain_id: String(event.chainId), event_type: event.eventType };
|
|
78
|
+
const outcome = event.ok ? 'ok' : 'error';
|
|
79
|
+
backend.count('webhook_dispatch_enqueue_count', 1, { ...tags, outcome });
|
|
80
|
+
backend.histogram('webhook_dispatch_enqueue_duration_ms', event.durationMs, {
|
|
81
|
+
...tags,
|
|
82
|
+
outcome,
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
case 'webhook:delivery': {
|
|
87
|
+
const { envelope, result, subscription } = event;
|
|
88
|
+
const tags = {
|
|
89
|
+
chain_id: String(envelope.chainId),
|
|
90
|
+
destination_type: subscription.destination.type,
|
|
91
|
+
event_type: envelope.type,
|
|
92
|
+
};
|
|
93
|
+
const outcome = result.ok ? 'succeeded' : 'failed';
|
|
94
|
+
backend.count('webhook_delivery_attempt_count', 1, {
|
|
95
|
+
...tags,
|
|
96
|
+
attempt_bucket: attemptBucket(subscription.failureCount + 1),
|
|
97
|
+
outcome,
|
|
98
|
+
status_class: statusClass(result),
|
|
99
|
+
trigger: event.trigger,
|
|
100
|
+
});
|
|
101
|
+
if (result.durationMs !== undefined)
|
|
102
|
+
backend.histogram('webhook_delivery_duration_ms', result.durationMs, {
|
|
103
|
+
...tags,
|
|
104
|
+
outcome,
|
|
105
|
+
});
|
|
106
|
+
backend.histogram('webhook_delivery_queue_latency_ms', Math.max(0, Date.now() - Date.parse(envelope.createdAt)), tags);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** Buckets a 1-based attempt number into a bounded set of attempt labels. */
|
|
114
|
+
function attemptBucket(attempt) {
|
|
115
|
+
if (attempt <= 1)
|
|
116
|
+
return '1';
|
|
117
|
+
if (attempt === 2)
|
|
118
|
+
return '2';
|
|
119
|
+
if (attempt <= 5)
|
|
120
|
+
return '3-5';
|
|
121
|
+
if (attempt <= 10)
|
|
122
|
+
return '6-10';
|
|
123
|
+
return 'gt10';
|
|
124
|
+
}
|
|
125
|
+
/** Maps a delivery result to a low-cardinality status class. */
|
|
126
|
+
function statusClass(result) {
|
|
127
|
+
if (result.ok)
|
|
128
|
+
return '2xx';
|
|
129
|
+
const { error, status } = result;
|
|
130
|
+
if (status !== undefined) {
|
|
131
|
+
if (status >= 300 && status < 400)
|
|
132
|
+
return 'url_rejected';
|
|
133
|
+
if (status >= 400 && status < 500)
|
|
134
|
+
return '4xx';
|
|
135
|
+
if (status >= 500)
|
|
136
|
+
return '5xx';
|
|
137
|
+
}
|
|
138
|
+
if (error === undefined)
|
|
139
|
+
return 'unknown';
|
|
140
|
+
if (/redirect/i.test(error))
|
|
141
|
+
return 'url_rejected';
|
|
142
|
+
if (/timeout|abort/i.test(error))
|
|
143
|
+
return 'timeout';
|
|
144
|
+
return 'network';
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=MetricSink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricSink.js","sourceRoot":"","sources":["../../src/internal/MetricSink.ts"],"names":[],"mappings":"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"}
|