Skip to content

Commit 1a42dd4

Browse files
authored
feat(stats): add Sentry observability with distributed tracing (#2530)
1 parent fa5d731 commit 1a42dd4

File tree

21 files changed

+1607
-82
lines changed

21 files changed

+1607
-82
lines changed

apps/stats-web/.env.local.sample

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ BASE_API_TESTNET_URL=${BASE_API_MAINNET_URL}
1414
BASE_API_SANDBOX_URL=${BASE_API_MAINNET_URL}
1515
LOG_LEVEL=debug
1616

17-
NEXT_PUBLIC_LOG_LEVEL=debug
17+
NEXT_PUBLIC_LOG_LEVEL=debug
18+
NEXT_PUBLIC_SENTRY_ENABLED=false

apps/stats-web/env/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
NEXT_PUBLIC_UNLEASH_APP_NAME=stats-web
22
NEXT_PUBLIC_UNLEASH_ENABLE_ALL=false
3+
NEXT_PUBLIC_SENTRY_APPLICATION_KEY="AKASH-STATS-WEB"

apps/stats-web/env/.env.production

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ BASE_API_SANDBOX_URL=$NEXT_PUBLIC_BASE_API_SANDBOX_URL
1212

1313
NEXT_PUBLIC_UNLEASH_FRONTEND_API_URL=https://features-edge.akash.network/api/frontend
1414
NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN=*:production.3de2776029292b1860a520b1aa3ee9e417ae300283811fd77d231060
15+
16+
NEXT_PUBLIC_SENTRY_ENABLED="true"

apps/stats-web/env/.env.sample

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ NEXT_PUBLIC_API_BASE_URL=
22
NEXT_PUBLIC_UNLEASH_ENABLE_ALL=true
33
NEXT_PUBLIC_UNLEASH_FRONTEND_API_URL=
44
NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN=
5+
6+
NEXT_PUBLIC_SENTRY_APPLICATION_KEY=
7+
NEXT_PUBLIC_SENTRY_DSN=
8+
NEXT_PUBLIC_SENTRY_SERVER_NAME=

apps/stats-web/env/.env.staging

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ BASE_API_SANDBOX_URL=$NEXT_PUBLIC_BASE_API_SANDBOX_URL
1010

1111
NEXT_PUBLIC_UNLEASH_FRONTEND_API_URL=https://features-edge-beta.akash.network/api/frontend
1212
NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN=*:development.34efccc4c8ba7d6ddeeb4083d72bc8ac05770774ac4d6668e749ca5a
13+
14+
NEXT_PUBLIC_SENTRY_ENABLED="true"

apps/stats-web/next.config.js

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require("@akashnetwork/env-loader");
2-
const { version } = require("./package.json");
2+
const { version, repository } = require("./package.json");
3+
const { withSentryConfig } = require("@sentry/nextjs");
34

45
try {
56
const { browserEnvSchema } = require("./env-config.schema");
@@ -14,13 +15,67 @@ try {
1415
/** @type {import('next').NextConfig} */
1516
const nextConfig = {
1617
output: "standalone",
17-
publicRuntimeConfig: {
18-
version
18+
env: {
19+
NEXT_PUBLIC_APP_VERSION: version
1920
},
2021
eslint: {
2122
ignoreDuringBuilds: true
2223
},
23-
transpilePackages: ["geist", "@akashnetwork/ui"]
24+
transpilePackages: ["geist", "@akashnetwork/ui"],
25+
experimental: {
26+
instrumentationHook: true
27+
},
28+
/**
29+
*
30+
* @param {import('webpack').Configuration} config
31+
* @returns
32+
*/
33+
webpack: config => {
34+
config.externals.push("pino-pretty");
35+
36+
return config;
37+
}
38+
};
39+
40+
/**
41+
* For all available options, see:
42+
* https://github.com/getsentry/sentry-webpack-plugin#options.
43+
* @type {import('@sentry/nextjs').SentryBuildOptions}
44+
*/
45+
const sentryWebpackPluginOptions = {
46+
// Additional config options for the Sentry Webpack plugin. Keep in mind that
47+
// the following options are set automatically, and overriding them is not
48+
// recommended:
49+
// release, url, org, project, authToken, configFile, stripPrefix,
50+
// urlPrefix, include, ignore
51+
52+
// silent: !process.env.CI, // Suppresses all logs,
53+
// dryRun: true,
54+
authToken: process.env.SENTRY_AUTH_TOKEN,
55+
org: process.env.SENTRY_ORG,
56+
project: process.env.SENTRY_PROJECT,
57+
release: repository
58+
? {
59+
name: version,
60+
setCommits: {
61+
repo: new URL(repository.url).pathname.slice(1).replace(/\.git$/, ""),
62+
commit: process.env.GIT_COMMIT_HASH
63+
}
64+
}
65+
: { name: version },
66+
sourcemaps: {
67+
deleteSourcemapsAfterUpload: false
68+
},
69+
widenClientFileUpload: true,
70+
debug: !process.env.CI,
71+
reactComponentAnnotation: {
72+
enabled: true
73+
},
74+
unstable_sentryWebpackPluginOptions: {
75+
applicationKey: process.env.NEXT_PUBLIC_SENTRY_APPLICATION_KEY
76+
}
2477
};
2578

26-
module.exports = nextConfig;
79+
// Make sure adding Sentry options is the last code to run before exporting, to
80+
// ensure that your source maps include changes from all other Webpack plugins
81+
module.exports = sentryWebpackPluginOptions.authToken ? withSentryConfig(nextConfig, sentryWebpackPluginOptions) : nextConfig;

apps/stats-web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
"@date-fns/utc": "^2.1.0",
2424
"@json2csv/plainjs": "^7.0.4",
2525
"@nivo/line": "^0.87.0",
26-
"@opentelemetry/api": "^1.9.0",
2726
"@radix-ui/react-icons": "^1.3.0",
2827
"@radix-ui/react-slot": "^1.0.2",
28+
"@sentry/nextjs": "^9.37.0",
2929
"@tanstack/react-query": "^5.67.2",
3030
"@tanstack/react-table": "^8.11.2",
3131
"@textea/json-viewer": "^3.2.3",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// This file configures the initialization of Sentry on the browser.
2+
// The config you add here will be used whenever a page is visited.
3+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
4+
5+
import { inboundFiltersIntegration, init as initSentry, thirdPartyErrorFilterIntegration } from "@sentry/nextjs";
6+
7+
initSentry({
8+
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
9+
// Adjust this value in production, or use tracesSampler for greater control
10+
tracesSampleRate: 0.1,
11+
enabled: process.env.NEXT_PUBLIC_SENTRY_ENABLED === "true",
12+
// propagate sentry-trace and baggage headers to internal API only
13+
// everything else will be done with custom interceptor
14+
tracePropagationTargets: [/^\/api\//, /^\/_next\//],
15+
integrations: [
16+
// Filter out errors originating from browser extensions
17+
// Note: uses inboundFiltersIntegration (not eventFiltersIntegration) to override defaultIntegrations
18+
inboundFiltersIntegration({
19+
denyUrls: [/^chrome-extension:\/\//, /^moz-extension:\/\//]
20+
}),
21+
thirdPartyErrorFilterIntegration({
22+
filterKeys: [process.env.NEXT_PUBLIC_SENTRY_APPLICATION_KEY!],
23+
behaviour: "drop-error-if-exclusively-contains-third-party-frames"
24+
})
25+
]
26+
// ...
27+
// Note: if you want to override the automatic release value, do not set a
28+
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
29+
// that it will also get attached to your source maps
30+
});

apps/stats-web/src/app/addresses/[address]/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { LoggerService } from "@akashnetwork/logging";
21
import type { Network } from "@akashnetwork/network-store";
32
import type { Metadata } from "next";
43
import { z } from "zod";
@@ -11,12 +10,13 @@ import { LatestTransactions } from "./LatestTransactions";
1110

1211
import { Title } from "@/components/Title";
1312
import { networkId } from "@/config/env-config.schema";
13+
import { createLogger } from "@/lib/createLogger/createLogger";
1414
import { serverFetch } from "@/lib/serverFetch";
1515
import { UrlService } from "@/lib/urlUtils";
1616
import { serverApiUrlService } from "@/services/api-url/server-api-url.service";
1717
import type { AddressDetail } from "@/types";
1818

19-
const logger = new LoggerService({ context: "AddressDetailPage" });
19+
const logger = createLogger({ context: "AddressDetailPage" });
2020

2121
const AddressDetailPageSchema = z.object({
2222
params: z.object({
@@ -46,11 +46,11 @@ async function fetchAddressData(address: string, network: Network["id"]): Promis
4646
const apiUrl = serverApiUrlService.getBaseApiUrlFor(network);
4747
const response = await serverFetch(`${apiUrl}/v1/addresses/${address}`);
4848

49+
logger.debug({ event: "FETCHING_ADDRESS_DATA", address, network, status: response.status });
50+
4951
if (!response.ok && response.status !== 404) {
50-
logger.error({ event: "ADDRESS_FETCH_ERROR", address, network, status: response.status });
5152
throw new Error(`Error fetching address data: ${address}`);
5253
} else if (response.status === 404) {
53-
logger.debug({ event: "ADDRESS_NOT_FOUND", address, network });
5454
return null;
5555
}
5656

apps/stats-web/src/app/blocks/[height]/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { LoggerService } from "@akashnetwork/logging";
21
import type { Network } from "@akashnetwork/network-store";
32
import { Card, CardContent, Table, TableBody, TableHead, TableHeader, TableRow } from "@akashnetwork/ui/components";
43
import { SearchX } from "lucide-react";
@@ -11,11 +10,12 @@ import { TransactionRow } from "@/components/blockchain/TransactionRow";
1110
import PageContainer from "@/components/PageContainer";
1211
import { Title } from "@/components/Title";
1312
import { networkId } from "@/config/env-config.schema";
13+
import { createLogger } from "@/lib/createLogger/createLogger";
1414
import { serverFetch } from "@/lib/serverFetch";
1515
import { serverApiUrlService } from "@/services/api-url/server-api-url.service";
1616
import type { BlockDetail } from "@/types";
1717

18-
const logger = new LoggerService({ context: "BlockDetailPage" });
18+
const logger = createLogger({ context: "BlockDetailPage" });
1919

2020
const BlockDetailPageSchema = z.object({
2121
params: z.object({

0 commit comments

Comments
 (0)