init
This commit is contained in:
23
GrafanaBlazor/BlazorApp/Components/Layout/MainLayout.razor
Normal file
23
GrafanaBlazor/BlazorApp/Components/Layout/MainLayout.razor
Normal 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>
|
||||
21
GrafanaBlazor/BlazorApp/Components/Layout/NavMenu.razor
Normal file
21
GrafanaBlazor/BlazorApp/Components/Layout/NavMenu.razor
Normal 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>
|
||||
42
GrafanaBlazor/BlazorApp/Components/Pages/Home.razor
Normal file
42
GrafanaBlazor/BlazorApp/Components/Pages/Home.razor
Normal 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");
|
||||
}
|
||||
}
|
||||
131
GrafanaBlazor/BlazorApp/Components/Pages/Logs.razor
Normal file
131
GrafanaBlazor/BlazorApp/Components/Pages/Logs.razor
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
111
GrafanaBlazor/BlazorApp/Components/Pages/Metrics.razor
Normal file
111
GrafanaBlazor/BlazorApp/Components/Pages/Metrics.razor
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user