8.0 KiB
8.0 KiB
Blazor Server App with Grafana Observability Stack
This project provides a complete infrastructure-as-code setup for deploying a Blazor Server application to Azure with comprehensive logging and metrics capabilities for use with Grafana.
Architecture
The solution includes:
- Azure App Service - Hosting the Blazor Server application
- Application Insights - Azure-native monitoring and telemetry
- Log Analytics Workspace - Centralized logging
- Prometheus Metrics - Exposed at
/metricsendpoint - OpenTelemetry - Distributed tracing support
- Serilog - Structured logging
Project Structure
.
├── main.bicep # Main Bicep file (subscription-level)
├── modules/
│ ├── monitoring.bicep # Log Analytics & Application Insights
│ └── appService.bicep # App Service Plan & Web App
├── BlazorApp/ # Blazor Server application
│ ├── Components/
│ │ ├── Layout/
│ │ │ ├── MainLayout.razor
│ │ │ └── NavMenu.razor
│ │ └── Pages/
│ │ ├── Home.razor
│ │ ├── Metrics.razor # Metrics demo page
│ │ └── Logs.razor # Logging demo page
│ ├── Program.cs # App configuration
│ ├── BlazorApp.csproj # Project file with dependencies
│ └── appsettings.json # Configuration
├── deploy.sh # Deployment script
└── README.md # This file
Prerequisites
- Azure CLI installed and configured
- .NET 8 SDK
- Azure subscription with appropriate permissions
- Grafana instance (can be Azure Managed Grafana or self-hosted)
Features
Logging
- Serilog for structured logging with console and file outputs
- Application Insights integration for Azure-native logging
- Log levels: Information, Warning, Error
- Structured log properties for better querying
Metrics
- Prometheus metrics exposed at
/metricsendpoint - OpenTelemetry instrumentation for ASP.NET Core and HTTP clients
- Custom metrics tracking (counters, timers)
- Health check endpoint at
/health
Demo Pages
- Home - Overview and quick log generation
- Metrics - Interactive metrics demonstration
- Logs - Test different log levels and structured logging
Deployment
1. Deploy Azure Infrastructure
# Login to Azure
az login
# Run the deployment script
./deploy.sh
This will create:
- Resource Group
- App Service Plan (Basic B1 tier)
- Web App (Linux, .NET 8)
- Application Insights
- Log Analytics Workspace
2. Build and Deploy the Application
# Navigate to the app directory
cd BlazorApp
# Restore dependencies
dotnet restore
# Build the application
dotnet build
# Publish the application
dotnet publish -c Release -o ./publish
# Create deployment package
cd publish
zip -r ../app.zip .
cd ..
# Deploy to Azure
az webapp deployment source config-zip \
--resource-group rg-blazor-grafana \
--name <your-webapp-name> \
--src app.zip
3. Verify Deployment
Once deployed, you can access:
- Application:
https://<your-webapp-name>.azurewebsites.net - Metrics:
https://<your-webapp-name>.azurewebsites.net/metrics - Health Check:
https://<your-webapp-name>.azurewebsites.net/health
Grafana Integration
Option 1: Prometheus Data Source
- In Grafana, add a new Prometheus data source
- Set the URL to:
https://<your-webapp-name>.azurewebsites.net - Configure scrape interval (e.g., 15s)
- Save and test the connection
Option 2: Azure Monitor Data Source
- In Grafana, add an Azure Monitor data source
- Configure with your Azure subscription details
- Point to your Application Insights instance
- You'll have access to:
- Application logs
- Traces
- Metrics
- Dependencies
Creating Dashboards
Sample Queries for Prometheus:
# Request rate
rate(http_requests_received_total[5m])
# Request duration
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
# Error rate
rate(http_requests_received_total{status_code=~"5.."}[5m])
Sample Queries for Azure Monitor:
// Application logs
traces
| where timestamp > ago(1h)
| project timestamp, message, severityLevel
// Request performance
requests
| where timestamp > ago(1h)
| summarize avg(duration), percentile(duration, 95) by bin(timestamp, 5m)
// Custom events
customEvents
| where timestamp > ago(1h)
| summarize count() by name
Available Metrics
The application exposes the following metrics at /metrics:
http_requests_received_total- Total HTTP requests receivedhttp_request_duration_seconds- HTTP request duration histogramhttp_requests_in_progress- Current HTTP requests in progressprocess_cpu_seconds_total- Process CPU timeprocess_working_set_bytes- Process memory usagedotnet_*- Various .NET runtime metrics
Local Development
cd BlazorApp
dotnet run
Access the app at https://localhost:5001 or http://localhost:5000
Configuration
appsettings.json
Configure logging levels and Application Insights:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning"
}
}
},
"ApplicationInsights": {
"ConnectionString": "your-connection-string"
}
}
Environment Variables
The following environment variables are automatically set in Azure:
APPLICATIONINSIGHTS_CONNECTION_STRINGAPPINSIGHTS_INSTRUMENTATIONKEYASPNETCORE_ENVIRONMENT
Customization
Adding Custom Metrics
// In your Razor component
@using Prometheus
private static readonly Counter CustomCounter = Metrics
.CreateCounter("myapp_custom_counter", "Description");
private void MyMethod()
{
CustomCounter.Inc();
}
Adding Custom Logs
@inject ILogger<MyComponent> Logger
Logger.LogInformation("User {UserId} performed action {Action}",
userId, actionName);
Monitoring Best Practices
- Use structured logging - Always use parameterized log messages
- Set appropriate log levels - Don't overuse Information level
- Add context - Include relevant properties in logs
- Monitor error rates - Set up alerts in Grafana
- Track business metrics - Not just technical metrics
- Use distributed tracing - Leverage OpenTelemetry spans
Troubleshooting
Application Insights not receiving data
- Check the connection string in Azure portal
- Verify Application Insights instrumentation key
- Check network connectivity from App Service
Prometheus metrics not showing
- Ensure
/metricsendpoint is accessible - Check if Prometheus is configured correctly in Grafana
- Verify App Service networking rules
Logs not appearing
- Check Log Analytics workspace connection
- Verify Serilog configuration
- Check file permissions for log files
Cost Considerations
This setup uses:
- App Service Plan: Basic B1 (~$55/month)
- Application Insights: Pay-as-you-go (first 5GB free)
- Log Analytics: Pay-as-you-go (first 5GB free)
To reduce costs:
- Use Free tier App Service for testing
- Adjust log retention periods
- Implement sampling in Application Insights
Clean Up
To delete all resources:
az group delete --name rg-blazor-grafana --yes --no-wait
Resources
License
This project is provided as-is for educational and demonstration purposes.