···1+# Grafana Cloud Configuration for wisp.place monorepo
2+# Copy these variables to your .env file to enable Grafana integration
3+# The observability package will automatically pick up these environment variables
4+5+# ============================================================================
6+# Grafana Loki (for logs)
7+# ============================================================================
8+# Get this from your Grafana Cloud portal under Loki → Details
9+# Example: https://logs-prod-012.grafana.net
10+GRAFANA_LOKI_URL=https://logs-prod-xxx.grafana.net
11+12+# Authentication Option 1: Bearer Token (Grafana Cloud)
13+GRAFANA_LOKI_TOKEN=glc_xxx
14+15+# Authentication Option 2: Username/Password (Self-hosted or some Grafana setups)
16+# GRAFANA_LOKI_USERNAME=your-username
17+# GRAFANA_LOKI_PASSWORD=your-password
18+19+# ============================================================================
20+# Grafana Prometheus (for metrics)
21+# ============================================================================
22+# Get this from your Grafana Cloud portal under Prometheus → Details
23+# Note: You need to add /api/prom to the base URL for OTLP export
24+# Example: https://prometheus-prod-10-prod-us-central-0.grafana.net/api/prom
25+GRAFANA_PROMETHEUS_URL=https://prometheus-prod-xxx.grafana.net/api/prom
26+27+# Authentication Option 1: Bearer Token (Grafana Cloud)
28+GRAFANA_PROMETHEUS_TOKEN=glc_xxx
29+30+# Authentication Option 2: Username/Password (Self-hosted or some Grafana setups)
31+# GRAFANA_PROMETHEUS_USERNAME=your-username
32+# GRAFANA_PROMETHEUS_PASSWORD=your-password
33+34+# ============================================================================
35+# Optional Configuration
36+# ============================================================================
37+# These will be used by both main-app and hosting-service if not overridden
38+39+# Service metadata (optional - defaults are provided in code)
40+# SERVICE_NAME=wisp-app
41+# SERVICE_VERSION=1.0.0
42+43+# Batching configuration (optional)
44+# GRAFANA_BATCH_SIZE=100 # Flush after this many entries
45+# GRAFANA_FLUSH_INTERVAL=5000 # Flush every 5 seconds
46+47+# ============================================================================
48+# How to get these values:
49+# ============================================================================
50+# 1. Sign up for Grafana Cloud at https://grafana.com/
51+# 2. Go to your Grafana Cloud portal
52+# 3. For Loki:
53+# - Navigate to "Connections" → "Loki"
54+# - Click "Details"
55+# - Copy the Push endpoint URL (without /loki/api/v1/push)
56+# - Create an API token with push permissions
57+# 4. For Prometheus:
58+# - Navigate to "Connections" → "Prometheus"
59+# - Click "Details"
60+# - Copy the Remote Write endpoint (add /api/prom for OTLP)
61+# - Create an API token with write permissions
62+63+# ============================================================================
64+# Testing the integration:
65+# ============================================================================
66+# 1. Copy this file's contents to your .env file
67+# 2. Fill in the actual values
68+# 3. Restart your services (main-app and hosting-service)
69+# 4. Check your Grafana Cloud dashboard for incoming data
70+# 5. Use Grafana Explore to query:
71+# - Loki: {job="main-app"} or {job="hosting-service"}
72+# - Prometheus: http_requests_total{service="main-app"}
+7-1
apps/hosting-service/src/index.ts
···1import app from './server';
2import { serve } from '@hono/node-server';
3import { FirehoseWorker } from './lib/firehose';
4-import { createLogger } from '@wisp/observability';
5import { mkdirSync, existsSync } from 'fs';
6import { backfillCache } from './lib/backfill';
7import { startDomainCacheCleanup, stopDomainCacheCleanup, setCacheOnlyMode } from './lib/db';
00000089const logger = createLogger('hosting-service');
10
···1import app from './server';
2import { serve } from '@hono/node-server';
3import { FirehoseWorker } from './lib/firehose';
4+import { createLogger, initializeGrafanaExporters } from '@wisp/observability';
5import { mkdirSync, existsSync } from 'fs';
6import { backfillCache } from './lib/backfill';
7import { startDomainCacheCleanup, stopDomainCacheCleanup, setCacheOnlyMode } from './lib/db';
8+9+// Initialize Grafana exporters if configured
10+initializeGrafanaExporters({
11+ serviceName: 'hosting-service',
12+ serviceVersion: '1.0.0'
13+});
1415const logger = createLogger('hosting-service');
16
+7-1
apps/main-app/src/index.ts
···20import { siteRoutes } from './routes/site'
21import { csrfProtection } from './lib/csrf'
22import { DNSVerificationWorker } from './lib/dns-verification-worker'
23-import { createLogger, logCollector } from '@wisp/observability'
24import { observabilityMiddleware } from '@wisp/observability/middleware/elysia'
25import { promptAdminSetup } from './lib/admin-auth'
26import { adminRoutes } from './routes/admin'
0000002728const logger = createLogger('main-app')
29
···20import { siteRoutes } from './routes/site'
21import { csrfProtection } from './lib/csrf'
22import { DNSVerificationWorker } from './lib/dns-verification-worker'
23+import { createLogger, logCollector, initializeGrafanaExporters } from '@wisp/observability'
24import { observabilityMiddleware } from '@wisp/observability/middleware/elysia'
25import { promptAdminSetup } from './lib/admin-auth'
26import { adminRoutes } from './routes/admin'
27+28+// Initialize Grafana exporters if configured
29+initializeGrafanaExporters({
30+ serviceName: 'main-app',
31+ serviceVersion: '1.0.50'
32+})
3334const logger = createLogger('main-app')
35
···6// Export everything from core
7export * from './core'
8000000009// Note: Middleware should be imported from specific subpaths:
10// - import { observabilityMiddleware } from '@wisp/observability/middleware/elysia'
11// - import { observabilityMiddleware, observabilityErrorHandler } from '@wisp/observability/middleware/hono'
···6// Export everything from core
7export * from './core'
89+// Export Grafana integration
10+export {
11+ initializeGrafanaExporters,
12+ shutdownGrafanaExporters,
13+ grafanaConfig,
14+ type GrafanaConfig
15+} from './exporters'
16+17// Note: Middleware should be imported from specific subpaths:
18// - import { observabilityMiddleware } from '@wisp/observability/middleware/elysia'
19// - import { observabilityMiddleware, observabilityErrorHandler } from '@wisp/observability/middleware/hono'