Better Stack Integration Guide
Overview
Section titled “Overview”This guide shows how to set up observability and operational alerting with Better Stack (formerly Logtail) for ERP-Unlocked. Note that Cloud Run and GCE VM stdout logs land natively in GCP Cloud Logging; Better Stack handles operational alerting (#3335), OTLP trace/log ingestion, and optional @logtail/pino log streaming (see the Cloud Logging cutover).
Environment Variables (Better Stack Standard)
Section titled “Environment Variables (Better Stack Standard)”Primary Configuration (Recommended)
Section titled “Primary Configuration (Recommended)”Following Better Stack’s official documentation and packages/observability/src/logger.ts, use these environment variables:
# Better Stack OTLP Configuration (Traces & OTLP Logs)OTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.betterstack.comOTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer <your-better-stack-token>OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://in-otel.betterstack.com/v1/logsOTEL_LOGS_EXPORTER=otlp
# Optional: Pino -> Better Stack Logtail worker transportLOGTAIL_SOURCE_TOKEN=<your-logtail-source-token>LOGTAIL_INGEST_HOST=in.logs.betterstack.com
# Service ConfigurationOTEL_SERVICE_NAME=erp-unlocked-webapp # or temporal-worker, ts-temporal-worker, dagsterOTEL_NODE_RESOURCE_DETECTORS=env,host,os
# Development/Debug SettingsOTEL_CONSOLE_EXPORT=false # Set to true for local developmentSetup Instructions
Section titled “Setup Instructions”Step 1: Better Stack Account
Section titled “Step 1: Better Stack Account”- Sign up at https://betterstack.com/
- Create a new project
- Go to Settings → API Tokens
- Create a new token with “Send logs” and “Send traces” permissions
Step 2: Environment Configuration
Section titled “Step 2: Environment Configuration”For Production (.env.production)
Section titled “For Production (.env.production)”# Better Stack OTLP ConfigurationOTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.betterstack.comOTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-actual-better-stack-token-hereOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://in-otel.betterstack.com/v1/logsOTEL_LOGS_EXPORTER=otlpOTEL_RESOURCE_ATTRIBUTES=service.name=erp-unlocked-webapp,service.version=1.0.0
# Optional: Direct Logtail transport for PinoLOGTAIL_SOURCE_TOKEN=your-logtail-source-tokenLOGTAIL_INGEST_HOST=in.logs.betterstack.comOTEL_CONSOLE_EXPORT=falseFor Development (.env.development)
Section titled “For Development (.env.development)”# Development - Use console / stdout exportOTEL_CONSOLE_EXPORT=trueLOG_LEVEL=debug
# Optional: Test with Better Stack in development# OTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.betterstack.com# OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-token# OTEL_LOGS_EXPORTER=otlpNode.js Logging with Pino
Section titled “Node.js Logging with Pino”Implementation
Section titled “Implementation”Our packages/observability/src/logger.ts provides:
Features
Section titled “Features”- OTLP & Logtail Support: Emits logs via
@opentelemetry/api-logswhenOTEL_LOGS_EXPORTER=otlp, or streams via@logtail/pinoalongsidestdoutwhenLOGTAIL_SOURCE_TOKENandLOGTAIL_INGEST_HOSTare configured - Development Mode: Clean
stdout/ console output for local development - Production Mode: JSON structured logs sent to
stdout(GCP Cloud Logging) and optionally Better Stack - Trace Correlation: Automatic correlation with OpenTelemetry traces
Usage Examples
Section titled “Usage Examples”import { logger } from '@repo/observability/logger';
// Basic logginglogger.info('User logged in', { userId: '123', method: 'oauth' });logger.warn('High memory usage detected', { usage: '85%' });logger.error('Payment failed', error, { orderId: 'order-456' });
// With structured metadatalogger.info('Order processed', { orderId: 'order-789', customerId: 'customer-123', amount: 99.99, currency: 'USD', processingTime: 1.2,});Environment Variables
Section titled “Environment Variables”# Enable OTLP logs in productionOTEL_LOGS_EXPORTER=otlpOTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.betterstack.comOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://in-otel.betterstack.com/v1/logsOTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-tokenOTEL_RESOURCE_ATTRIBUTES=service.name=erp-unlocked-webapp,service.version=1.0.0
# Or enable @logtail/pino transportLOGTAIL_SOURCE_TOKEN=your-logtail-tokenLOGTAIL_INGEST_HOST=in.logs.betterstack.com
# Development modeNODE_ENV=developmentLOG_LEVEL=debugPython Logging with OpenTelemetry
Section titled “Python Logging with OpenTelemetry”Implementation
Section titled “Implementation”Our Python services use OpenTelemetry’s logging instrumentation:
Features
Section titled “Features”- Structured Logging: JSON format for better parsing
- Trace Correlation: Automatic span context injection
- Error Tracking: Comprehensive error logging with stack traces
- Performance Metrics: Request timing and resource usage
Environment Variables
Section titled “Environment Variables”# Python servicesOTEL_SERVICE_NAME=temporal-worker # or webapp, internal, dagsterOTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.betterstack.comOTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-tokenOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://in-otel.betterstack.com/v1/logsBetter Stack Features
Section titled “Better Stack Features”- Structured JSON logs with automatic parsing
- Log correlation with traces and metrics
- Real-time search and filtering
- Log retention and archiving
- Alerting based on log patterns
Traces
Section titled “Traces”- Distributed tracing across all services
- Trace correlation with logs and metrics
- Performance insights and bottleneck identification
- Service dependency mapping
- Error tracking and debugging
Metrics
Section titled “Metrics”- Custom metrics from your application
- Infrastructure metrics (CPU, memory, etc.)
- Business metrics (orders processed, user activity)
- Alerting and monitoring dashboards
Validation
Section titled “Validation”Automated Validation
Section titled “Automated Validation”Run the validation script to check Better Stack integration:
pnpm tsx scripts/validate-observability.tsManual Validation
Section titled “Manual Validation”- Upload a test PDF document through the webapp
- Check Better Stack dashboard for:
- Single trace spanning webapp → Temporal workflow → temporal-worker activities
- User context in span attributes (
user.id,session.id) - Temporal activity spans linked to parent workflow traces
- Check Langfuse dashboard (if configured) for:
- LLM traces linked to OpenTelemetry spans
- End-to-end visibility from user action to LLM generation
Better Stack Dashboard
Section titled “Better Stack Dashboard”Logs View
Section titled “Logs View”- Real-time log streaming from all services
- Structured log parsing with automatic field extraction
- Log correlation with traces and metrics
- Search and filtering by service, level, or custom fields
Traces View
Section titled “Traces View”- Service map showing dependencies
- Trace timeline with detailed span information
- Error tracking and performance bottlenecks
- Custom span attributes for business context
Metrics View
Section titled “Metrics View”- Custom dashboards for business and technical metrics
- Alerting rules for proactive monitoring
- Historical data and trending analysis
Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”-
No traces appearing in Better Stack
- Check that
OTEL_EXPORTER_OTLP_ENDPOINTis set tohttps://in-otel.betterstack.com - Verify
OTEL_EXPORTER_OTLP_HEADERScontains valid Bearer token - Ensure services are sending data (check logs for OpenTelemetry initialization)
- Check that
-
Logs not appearing
- Verify
OTEL_LOGS_EXPORTER=otlpandOTEL_EXPORTER_OTLP_ENDPOINTare set (orLOGTAIL_SOURCE_TOKENandLOGTAIL_INGEST_HOSTif using@logtail/pino) - Ensure Pino or OTel logger initialization succeeded in startup logs
- Verify
-
High latency or timeouts
- Check network connectivity to Better Stack endpoints
- Verify OTLP exporter timeout settings
- Consider increasing buffer limits for high-volume applications
Debug Mode
Section titled “Debug Mode”Enable debug logging to troubleshoot issues:
# Node.jsDEBUG=otel* node app.js
# PythonOTEL_LOG_LEVEL=debug python app.pySwitching OTLP Endpoints
Section titled “Switching OTLP Endpoints”# Better Stack OTLP configurationOTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.betterstack.comOTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-better-stack-tokenThe OpenTelemetry instrumentation code in @repo/observability remains the same across environments — only the OTLP endpoint and authorization header change.
Cost Optimization
Section titled “Cost Optimization”Better Stack Pricing
Section titled “Better Stack Pricing”- Logs: Pay per GB ingested
- Traces: Included with logs
- Metrics: Included with logs
- Retention: Configurable retention periods
Optimization Tips
Section titled “Optimization Tips”- Structured logging: Use JSON format for better parsing and lower costs
- Log levels: Use appropriate log levels to reduce noise
- Sampling: Configure trace sampling for high-volume applications
- Retention: Set appropriate retention periods for different log types