This commit is contained in:
bob
2026-01-28 10:29:49 -06:00
commit 1e90daabb5
157 changed files with 9503 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

View File

@@ -0,0 +1,21 @@
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="metrics">
<span class="bi bi-graph-up-arrow" aria-hidden="true"></span> Metrics
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="logs">
<span class="bi bi-journal-text" aria-hidden="true"></span> Logs Demo
</NavLink>
</div>
</nav>
</div>

View File

@@ -0,0 +1,42 @@
@page "/"
@inject ILogger<Home> Logger
<PageTitle>Home</PageTitle>
<h1>Blazor Server App - Grafana Observability Demo</h1>
<p>Welcome! This application is configured with:</p>
<ul>
<li><strong>Serilog</strong> - Structured logging</li>
<li><strong>Application Insights</strong> - Azure native monitoring</li>
<li><strong>OpenTelemetry</strong> - Distributed tracing</li>
<li><strong>Prometheus</strong> - Metrics endpoint at <code>/metrics</code></li>
</ul>
<h2>Available Endpoints</h2>
<ul>
<li><code>/health</code> - Health check endpoint</li>
<li><code>/metrics</code> - Prometheus metrics</li>
</ul>
<div class="alert alert-info mt-4">
<h4>Getting Started with Grafana</h4>
<p>To visualize this data in Grafana:</p>
<ol>
<li>Add Prometheus as a data source pointing to this app's <code>/metrics</code> endpoint</li>
<li>Add Azure Monitor as a data source for Application Insights</li>
<li>Create dashboards to visualize your metrics and logs</li>
</ol>
</div>
<button class="btn btn-primary" @onclick="LogTestMessage">Generate Test Log</button>
@code {
private void LogTestMessage()
{
Logger.LogInformation("Test log message generated from Home page at {Timestamp}", DateTime.UtcNow);
Logger.LogWarning("This is a warning message for testing");
}
}

View File

@@ -0,0 +1,131 @@
@page "/logs"
@inject ILogger<Logs> Logger
<PageTitle>Logs</PageTitle>
<h1>Logs Demo</h1>
<p>This page helps you generate different types of log entries for testing your Grafana setup.</p>
<div class="row mt-4">
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Information</h5>
<p>Generate informational log entries.</p>
<button class="btn btn-info" @onclick="@(() => LogMessage(LogLevel.Information))">
Log Information
</button>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Warning</h5>
<p>Generate warning log entries.</p>
<button class="btn btn-warning" @onclick="@(() => LogMessage(LogLevel.Warning))">
Log Warning
</button>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Error</h5>
<p>Generate error log entries.</p>
<button class="btn btn-danger" @onclick="@(() => LogMessage(LogLevel.Error))">
Log Error
</button>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Structured Logging</h5>
<p>Generate structured log with custom properties.</p>
<button class="btn btn-primary" @onclick="LogStructuredMessage">
Log Structured Data
</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Bulk Logs</h5>
<p>Generate multiple log entries at once.</p>
<button class="btn btn-secondary" @onclick="GenerateBulkLogs">
Generate 10 Logs
</button>
</div>
</div>
</div>
</div>
<div class="alert alert-success mt-4">
<strong>Total logs generated this session:</strong> @logCount
</div>
@code {
private int logCount = 0;
private void LogMessage(LogLevel level)
{
var message = $"Test {level} message generated at {DateTime.UtcNow:O}";
switch (level)
{
case LogLevel.Information:
Logger.LogInformation("{Message}", message);
break;
case LogLevel.Warning:
Logger.LogWarning("{Message}", message);
break;
case LogLevel.Error:
Logger.LogError("{Message}", message);
break;
}
logCount++;
}
private void LogStructuredMessage()
{
var userId = Guid.NewGuid();
var operationId = Random.Shared.Next(1000, 9999);
Logger.LogInformation(
"User {UserId} performed operation {OperationId} with status {Status} at {Timestamp}",
userId,
operationId,
"Success",
DateTime.UtcNow
);
logCount++;
}
private void GenerateBulkLogs()
{
for (int i = 0; i < 10; i++)
{
var logLevel = i % 3 switch
{
0 => LogLevel.Information,
1 => LogLevel.Warning,
_ => LogLevel.Error
};
LogMessage(logLevel);
}
}
}

View File

@@ -0,0 +1,111 @@
@page "/metrics"
@inject ILogger<Metrics> Logger
@using System.Diagnostics
<PageTitle>Metrics</PageTitle>
<h1>Metrics Demo</h1>
<p>This page demonstrates various metrics that can be tracked and visualized in Grafana.</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Counter Metrics</h5>
<p>Counter: @counterValue</p>
<button class="btn btn-primary" @onclick="IncrementCounter">Increment Counter</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Timer Metrics</h5>
<p>Simulate a slow operation and track its duration.</p>
<button class="btn btn-warning" @onclick="SimulateSlowOperation" disabled="@isProcessing">
@(isProcessing ? "Processing..." : "Start Slow Operation")
</button>
@if (lastDuration > 0)
{
<p class="mt-2">Last operation took: @lastDuration ms</p>
}
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Error Simulation</h5>
<p>Generate different types of log entries for testing.</p>
<button class="btn btn-danger" @onclick="SimulateError">Generate Error</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Custom Metrics</h5>
<p>Page visits: @pageVisits</p>
<small class="text-muted">This counter increments each time you visit this page.</small>
</div>
</div>
</div>
</div>
@code {
private int counterValue = 0;
private int pageVisits = 0;
private bool isProcessing = false;
private long lastDuration = 0;
private static readonly ActivitySource ActivitySource = new("BlazorApp.Metrics");
protected override void OnInitialized()
{
pageVisits++;
Logger.LogInformation("Metrics page visited. Total visits: {PageVisits}", pageVisits);
}
private void IncrementCounter()
{
counterValue++;
Logger.LogInformation("Counter incremented to {CounterValue}", counterValue);
}
private async Task SimulateSlowOperation()
{
isProcessing = true;
var sw = Stopwatch.StartNew();
using var activity = ActivitySource.StartActivity("SlowOperation");
activity?.SetTag("operation.type", "simulated");
Logger.LogInformation("Starting slow operation");
try
{
await Task.Delay(Random.Shared.Next(1000, 3000));
sw.Stop();
lastDuration = sw.ElapsedMilliseconds;
Logger.LogInformation("Slow operation completed in {Duration}ms", lastDuration);
activity?.SetTag("duration.ms", lastDuration);
}
finally
{
isProcessing = false;
}
}
private void SimulateError()
{
var errorId = Guid.NewGuid();
Logger.LogError("Simulated error with ID: {ErrorId}", errorId);
Logger.LogWarning("This is a test warning associated with error {ErrorId}", errorId);
}
}