304 lines
8.0 KiB
Markdown
304 lines
8.0 KiB
Markdown
# 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 `/metrics` endpoint
|
|
- **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](https://docs.microsoft.com/cli/azure/install-azure-cli) installed and configured
|
|
- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)
|
|
- Azure subscription with appropriate permissions
|
|
- [Grafana](https://grafana.com/) 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 `/metrics` endpoint
|
|
- **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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
1. In Grafana, add a new Prometheus data source
|
|
2. Set the URL to: `https://<your-webapp-name>.azurewebsites.net`
|
|
3. Configure scrape interval (e.g., 15s)
|
|
4. Save and test the connection
|
|
|
|
### Option 2: Azure Monitor Data Source
|
|
|
|
1. In Grafana, add an Azure Monitor data source
|
|
2. Configure with your Azure subscription details
|
|
3. Point to your Application Insights instance
|
|
4. You'll have access to:
|
|
- Application logs
|
|
- Traces
|
|
- Metrics
|
|
- Dependencies
|
|
|
|
### Creating Dashboards
|
|
|
|
**Sample Queries for Prometheus:**
|
|
```promql
|
|
# 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:**
|
|
```kusto
|
|
// 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 received
|
|
- `http_request_duration_seconds` - HTTP request duration histogram
|
|
- `http_requests_in_progress` - Current HTTP requests in progress
|
|
- `process_cpu_seconds_total` - Process CPU time
|
|
- `process_working_set_bytes` - Process memory usage
|
|
- `dotnet_*` - Various .NET runtime metrics
|
|
|
|
## Local Development
|
|
|
|
```bash
|
|
cd BlazorApp
|
|
dotnet run
|
|
```
|
|
|
|
Access the app at `https://localhost:5001` or `http://localhost:5000`
|
|
|
|
## Configuration
|
|
|
|
### appsettings.json
|
|
|
|
Configure logging levels and Application Insights:
|
|
|
|
```json
|
|
{
|
|
"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_STRING`
|
|
- `APPINSIGHTS_INSTRUMENTATIONKEY`
|
|
- `ASPNETCORE_ENVIRONMENT`
|
|
|
|
## Customization
|
|
|
|
### Adding Custom Metrics
|
|
|
|
```csharp
|
|
// 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
|
|
|
|
```csharp
|
|
@inject ILogger<MyComponent> Logger
|
|
|
|
Logger.LogInformation("User {UserId} performed action {Action}",
|
|
userId, actionName);
|
|
```
|
|
|
|
## Monitoring Best Practices
|
|
|
|
1. **Use structured logging** - Always use parameterized log messages
|
|
2. **Set appropriate log levels** - Don't overuse Information level
|
|
3. **Add context** - Include relevant properties in logs
|
|
4. **Monitor error rates** - Set up alerts in Grafana
|
|
5. **Track business metrics** - Not just technical metrics
|
|
6. **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 `/metrics` endpoint 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:
|
|
|
|
```bash
|
|
az group delete --name rg-blazor-grafana --yes --no-wait
|
|
```
|
|
|
|
## Resources
|
|
|
|
- [Blazor Documentation](https://docs.microsoft.com/aspnet/core/blazor/)
|
|
- [Application Insights](https://docs.microsoft.com/azure/azure-monitor/app/app-insights-overview)
|
|
- [Prometheus](https://prometheus.io/docs/introduction/overview/)
|
|
- [Grafana](https://grafana.com/docs/)
|
|
- [OpenTelemetry](https://opentelemetry.io/docs/)
|
|
- [Serilog](https://serilog.net/)
|
|
|
|
## License
|
|
|
|
This project is provided as-is for educational and demonstration purposes.
|