124 lines
2.9 KiB
Markdown
124 lines
2.9 KiB
Markdown
# @mintel/observability
|
|
|
|
Standardized observability package for the Mintel ecosystem, providing Umami analytics and Sentry/GlitchTip error tracking with a focus on privacy and ad-blocker resilience.
|
|
|
|
## Features
|
|
|
|
- **Umami Smart Proxy**: Track analytics without external scripts and hide your Website ID.
|
|
- **Sentry Relay**: Bypass ad-blockers for error tracking by relaying envelopes through your own server.
|
|
- **Unified API**: consistent interface for tracking across multiple projects.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
pnpm add @mintel/observability @sentry/nextjs
|
|
```
|
|
|
|
## Usage
|
|
|
|
### 1. Unified Environment (via @mintel/next-utils)
|
|
|
|
Define the following environment variables:
|
|
|
|
```bash
|
|
# Analytics
|
|
UMAMI_WEBSITE_ID=your-website-id
|
|
UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me
|
|
|
|
# Error Tracking
|
|
SENTRY_DSN=your-sentry-dsn
|
|
```
|
|
|
|
Note: No `NEXT_PUBLIC_` prefix is required for these anymore, as they are handled by server-side proxies.
|
|
|
|
### 2. Analytics Setup
|
|
|
|
In your root layout:
|
|
|
|
```tsx
|
|
import {
|
|
AnalyticsContextProvider,
|
|
AnalyticsAutoTracker,
|
|
UmamiAnalyticsService,
|
|
} from "@mintel/observability";
|
|
|
|
const analytics = new UmamiAnalyticsService({
|
|
enabled: true,
|
|
websiteId: process.env.UMAMI_WEBSITE_ID, // Server-side
|
|
apiEndpoint:
|
|
typeof window === "undefined" ? process.env.UMAMI_API_ENDPOINT : "/stats",
|
|
});
|
|
|
|
export default function Layout({ children }) {
|
|
return (
|
|
<AnalyticsContextProvider service={analytics}>
|
|
<AnalyticsAutoTracker />
|
|
{children}
|
|
</AnalyticsContextProvider>
|
|
);
|
|
}
|
|
```
|
|
|
|
### 3. Route Handlers
|
|
|
|
Create a proxy for Umami:
|
|
`app/stats/api/send/route.ts`
|
|
|
|
```ts
|
|
import { createUmamiProxyHandler } from "@mintel/observability";
|
|
export const POST = await createUmamiProxyHandler({
|
|
websiteId: process.env.UMAMI_WEBSITE_ID,
|
|
apiEndpoint: process.env.UMAMI_API_ENDPOINT,
|
|
});
|
|
```
|
|
|
|
Create a relay for Sentry:
|
|
`app/errors/api/relay/route.ts`
|
|
|
|
```ts
|
|
import { createSentryRelayHandler } from "@mintel/observability";
|
|
export const POST = await createSentryRelayHandler({
|
|
dsn: process.env.SENTRY_DSN,
|
|
});
|
|
```
|
|
|
|
### 4. Notification Setup (Server-side)
|
|
|
|
```ts
|
|
import { GotifyNotificationService } from "@mintel/observability";
|
|
|
|
const notifications = new GotifyNotificationService({
|
|
enabled: true,
|
|
url: process.env.GOTIFY_URL,
|
|
token: process.env.GOTIFY_TOKEN,
|
|
});
|
|
|
|
await notifications.notify({
|
|
title: "Lead Capture",
|
|
message: "New contact form submission",
|
|
priority: 5,
|
|
});
|
|
```
|
|
|
|
### 5. Sentry Configuration
|
|
|
|
Use `initSentry` in your `sentry.server.config.ts` and `sentry.client.config.ts`.
|
|
|
|
On the client, use the tunnel:
|
|
|
|
```ts
|
|
initSentry({
|
|
dsn: "https://public@errors.infra.mintel.me/1", // Placeholder
|
|
tunnel: "/errors/api/relay",
|
|
});
|
|
```
|
|
|
|
## Architecture
|
|
|
|
This package implements the **Smart Proxy** pattern:
|
|
|
|
- The client NEVER knows the real `UMAMI_WEBSITE_ID`.
|
|
- Tracking events are sent to your own domain (`/stats/api/send`).
|
|
- Your server injects the secret ID and forwards to Umami.
|
|
- This bypasses ad-blockers and keeps your configuration secure.
|