From 34d5bbbd6f6a18c3a01e93143cafd906eae25072 Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Tue, 22 Oct 2024 15:35:33 +0300
Subject: [PATCH 1/7] added serilog
---
Observability.Homework/Homework.http | 8 ++++++++
Observability.Homework/Observability.Homework.csproj | 7 +++++++
2 files changed, 15 insertions(+)
create mode 100644 Observability.Homework/Homework.http
diff --git a/Observability.Homework/Homework.http b/Observability.Homework/Homework.http
new file mode 100644
index 0000000..f4c0462
--- /dev/null
+++ b/Observability.Homework/Homework.http
@@ -0,0 +1,8 @@
+@HomeWorkToDoList_HostAddress = http://localhost:5216
+
+POST {{HomeWorkToDoList_HostAddress}}/order/
+Accept: application/json
+Content-Type: application/json
+
+{"product":{"type":0},"client":{"id":"rgerg"}}
+###
\ No newline at end of file
diff --git a/Observability.Homework/Observability.Homework.csproj b/Observability.Homework/Observability.Homework.csproj
index c150414..3137923 100644
--- a/Observability.Homework/Observability.Homework.csproj
+++ b/Observability.Homework/Observability.Homework.csproj
@@ -6,4 +6,11 @@
enable
+
+
+
+
+
+
+
From 6ab2afa222dbe63f7785ff5a9c8f4e1c4cffcdf0 Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Tue, 22 Oct 2024 15:39:40 +0300
Subject: [PATCH 2/7] add logging
---
Observability.Homework/Program.cs | 9 ++++++---
.../Services/PizzaBakeryService.cs | 15 +++++++++++++++
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/Observability.Homework/Program.cs b/Observability.Homework/Program.cs
index 6c4ba0e..5beaf93 100644
--- a/Observability.Homework/Program.cs
+++ b/Observability.Homework/Program.cs
@@ -38,9 +38,12 @@
app.MapPost("/order", async ([FromBody] Order order, IPizzaBakeryService pizzaBakeryService, CancellationToken cancellationToken) =>
{
- if (order.Product.Type is ProductType.Pizza)
- await pizzaBakeryService.DoPizza(order.Product, cancellationToken);
-
+ using (app.Logger.BeginScope(new Dictionary { { "ClientId", order.Client.Id } }))
+ {
+ app.Logger.LogInformation("request");
+ if (order.Product.Type is ProductType.Pizza)
+ await pizzaBakeryService.DoPizza(order.Product, cancellationToken);
+ }
return Results.Ok(order.Product);
});
diff --git a/Observability.Homework/Services/PizzaBakeryService.cs b/Observability.Homework/Services/PizzaBakeryService.cs
index 15529f1..86a16d4 100644
--- a/Observability.Homework/Services/PizzaBakeryService.cs
+++ b/Observability.Homework/Services/PizzaBakeryService.cs
@@ -11,10 +11,17 @@ public interface IPizzaBakeryService
public class PizzaBakeryService : IPizzaBakeryService
{
+ private readonly ILogger _logger;
private readonly ConcurrentDictionary _bake = new();
+ public PizzaBakeryService(ILogger logger)
+ {
+ _logger = logger;
+ }
+
public async Task DoPizza(Product product, CancellationToken cancellationToken = default)
{
+ _logger.LogInformation("DoPizza id:{productId} type:{productType}",product.Id, product.Type);
try
{
await MakePizza(product, cancellationToken);
@@ -24,17 +31,20 @@ public async Task DoPizza(Product product, CancellationToken cancellati
}
catch (OperationCanceledException)
{
+ _logger.LogError("PizzaBakeryService cancel do pizza");
DropPizza(product);
throw;
}
catch (BurntPizzaException)
{
+ _logger.LogError("PizzaBakeryService burnt pizza");
return await DoPizza(product, cancellationToken);
}
}
private async Task BakePizza(Product product, CancellationToken cancellationToken = default)
{
+ _logger.LogInformation("BakePizza id:{productId} type:{productType}",product.Id, product.Type);
PushToBake(product);
var bakeForSeconds = new Random().Next(3, 9);
await Task.Delay(TimeSpan.FromSeconds(bakeForSeconds), cancellationToken);
@@ -48,29 +58,34 @@ private async Task BakePizza(Product product, CancellationToken cancell
private async Task MakePizza(Product product, CancellationToken cancellationToken = default)
{
+ _logger.LogInformation("MakePizza id:{productId} type:{productType}",product.Id, product.Type);
await Task.Delay(new Random().Next(1, 3) * 1000, cancellationToken);
return product;
}
private async Task PackPizza(Product product, CancellationToken cancellationToken = default)
{
+ _logger.LogInformation("PackPizza id:{productId} type:{productType}",product.Id, product.Type);
await Task.Delay(new Random().Next(1, 2) * 1000, cancellationToken);
return product;
}
private void PushToBake(Product product)
{
+ _logger.LogInformation("PushToBake id:{productId} type:{productType}",product.Id, product.Type);
_bake[product.Id] = product;
}
private Product PopFromBake(Product product)
{
+ _logger.LogInformation("PopFromBake id:{productId} type:{productType}",product.Id, product.Type);
_bake.Remove(product.Id, out var pizza);
return pizza!; //пусть у нас всегда есть пицца
}
private void DropPizza(Product product)
{
+ _logger.LogInformation("DropPizza id:{productId} type:{productType}",product.Id, product.Type);
_bake.Remove(product.Id, out _);
}
}
\ No newline at end of file
From c23695118c4b56ff80e534708be9d77464200118 Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Tue, 22 Oct 2024 16:37:09 +0300
Subject: [PATCH 3/7] added logging config
---
.../Extensions/LoggingConfig.cs | 41 +++++++++++++++++++
.../Observability.Homework.csproj | 4 ++
Observability.Homework/Program.cs | 3 +-
3 files changed, 47 insertions(+), 1 deletion(-)
create mode 100644 Observability.Homework/Extensions/LoggingConfig.cs
diff --git a/Observability.Homework/Extensions/LoggingConfig.cs b/Observability.Homework/Extensions/LoggingConfig.cs
new file mode 100644
index 0000000..e011409
--- /dev/null
+++ b/Observability.Homework/Extensions/LoggingConfig.cs
@@ -0,0 +1,41 @@
+using System.Globalization;
+using Serilog;
+using Serilog.Events;
+using Serilog.Formatting.Elasticsearch;
+
+namespace Observability.Homework.Extensions;
+
+public static class LoggingConfig
+{
+ public static void AppLogging(this WebApplicationBuilder builder)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.Host.UseSerilog(
+ (context, configuration) =>
+ {
+ configuration
+ .ReadFrom.Configuration(context.Configuration);
+
+
+ if (builder.Environment.EnvironmentName == "Development")
+ configuration
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
+ .WriteTo.Console(formatProvider: CultureInfo.DefaultThreadCurrentCulture,
+ outputTemplate:
+ "[{Level:u3} {Timestamp:HH:mm:ss} {ScopePath}] {ClientId} {Message:lj}{NewLine}{Exception}");
+
+ else
+ configuration
+ .MinimumLevel.Warning()
+ .WriteTo.Async(
+ to => to.Console(
+ new ExceptionAsObjectJsonFormatter(
+ renderMessage: true,
+ inlineFields: true),
+ standardErrorFromLevel: LogEventLevel.Warning));
+ }
+ );
+ }
+}
\ No newline at end of file
diff --git a/Observability.Homework/Observability.Homework.csproj b/Observability.Homework/Observability.Homework.csproj
index 3137923..e43bf48 100644
--- a/Observability.Homework/Observability.Homework.csproj
+++ b/Observability.Homework/Observability.Homework.csproj
@@ -8,8 +8,12 @@
+
+
+
+
diff --git a/Observability.Homework/Program.cs b/Observability.Homework/Program.cs
index 5beaf93..6b38bc5 100644
--- a/Observability.Homework/Program.cs
+++ b/Observability.Homework/Program.cs
@@ -27,13 +27,14 @@
*/
using Microsoft.AspNetCore.Mvc;
+using Observability.Homework.Extensions;
using Observability.Homework.Models;
using Observability.Homework.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton();
-
+builder.AppLogging();
var app = builder.Build();
app.MapPost("/order", async ([FromBody] Order order, IPizzaBakeryService pizzaBakeryService, CancellationToken cancellationToken) =>
From 14e36bb8150bc6a9378039ad9ca368f8c8b6bced Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Thu, 24 Oct 2024 16:56:35 +0300
Subject: [PATCH 4/7] add new project
---
.../Models/Client.cs | 6 +++
.../Models/Order.cs | 23 +++++++++
.../Models/Product.cs | 15 ++++++
...servability.Homework.Tracing.Client.csproj | 16 ++++++
.../Program.cs | 27 ++++++++++
Observability.Homework.sln | 6 +++
.../Observability.Homework.csproj | 6 +++
Observability.Homework/Program.cs | 25 ++++++++--
.../Services/PizzaBakeryService.cs | 50 ++++++++++++-------
9 files changed, 153 insertions(+), 21 deletions(-)
create mode 100644 Observability.Homework.Tracing.Client/Models/Client.cs
create mode 100644 Observability.Homework.Tracing.Client/Models/Order.cs
create mode 100644 Observability.Homework.Tracing.Client/Models/Product.cs
create mode 100644 Observability.Homework.Tracing.Client/Observability.Homework.Tracing.Client.csproj
create mode 100644 Observability.Homework.Tracing.Client/Program.cs
diff --git a/Observability.Homework.Tracing.Client/Models/Client.cs b/Observability.Homework.Tracing.Client/Models/Client.cs
new file mode 100644
index 0000000..4200a70
--- /dev/null
+++ b/Observability.Homework.Tracing.Client/Models/Client.cs
@@ -0,0 +1,6 @@
+namespace Observability.Homework.Models;
+
+public class Client
+{
+ public required string Id { get; set; }
+}
\ No newline at end of file
diff --git a/Observability.Homework.Tracing.Client/Models/Order.cs b/Observability.Homework.Tracing.Client/Models/Order.cs
new file mode 100644
index 0000000..00049d0
--- /dev/null
+++ b/Observability.Homework.Tracing.Client/Models/Order.cs
@@ -0,0 +1,23 @@
+namespace Observability.Homework.Models;
+
+public class Order
+{
+ public required Client Client { get; set; }
+
+ public required Product Product { get; set; }
+
+ public static Order Create(ProductType type)
+ {
+ return new Order
+ {
+ Client = new()
+ {
+ Id = Guid.NewGuid().ToString()
+ },
+ Product = new Product
+ {
+ Type = type
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/Observability.Homework.Tracing.Client/Models/Product.cs b/Observability.Homework.Tracing.Client/Models/Product.cs
new file mode 100644
index 0000000..661ea4c
--- /dev/null
+++ b/Observability.Homework.Tracing.Client/Models/Product.cs
@@ -0,0 +1,15 @@
+namespace Observability.Homework.Models;
+
+public class Product
+{
+ public Guid Id { get; } = Guid.NewGuid();
+
+ public required ProductType Type { get; set; }
+}
+
+public enum ProductType
+{
+ Pizza = 0,
+ Desert = 1,
+ Beverage = 2
+}
\ No newline at end of file
diff --git a/Observability.Homework.Tracing.Client/Observability.Homework.Tracing.Client.csproj b/Observability.Homework.Tracing.Client/Observability.Homework.Tracing.Client.csproj
new file mode 100644
index 0000000..b5b9bcf
--- /dev/null
+++ b/Observability.Homework.Tracing.Client/Observability.Homework.Tracing.Client.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/Observability.Homework.Tracing.Client/Program.cs b/Observability.Homework.Tracing.Client/Program.cs
new file mode 100644
index 0000000..e0591d7
--- /dev/null
+++ b/Observability.Homework.Tracing.Client/Program.cs
@@ -0,0 +1,27 @@
+// See https://aka.ms/new-console-template for more information
+
+using System.Net.Http.Json;
+using Observability.Homework.Models;
+using OpenTelemetry;
+using OpenTelemetry.Resources;
+using OpenTelemetry.Trace;
+
+var serviceName = "Observability.Homework.Tracing.Client";
+
+using var tracerProvider = Sdk.CreateTracerProviderBuilder()
+ .AddSource(serviceName)
+ .AddHttpClientInstrumentation()
+ .SetResourceBuilder(
+ ResourceBuilder.CreateDefault()
+ .AddService(serviceName: serviceName))
+ .AddJaegerExporter()
+ .Build();
+Random random = new Random();
+while (true)
+{
+ using var httpClient = new HttpClient();
+ var response = await httpClient.PostAsync("http://localhost:5216/order/", JsonContent.Create(Order.Create((ProductType)random.Next(0,2))));
+ response.EnsureSuccessStatusCode();
+ Console.WriteLine("Response received successfully.");
+}
+
diff --git a/Observability.Homework.sln b/Observability.Homework.sln
index cd11401..2388734 100644
--- a/Observability.Homework.sln
+++ b/Observability.Homework.sln
@@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Observability.Homework", "Observability.Homework\Observability.Homework.csproj", "{FA51BFEE-F62F-4D80-A43A-3C384C62D1AB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Observability.Homework.Tracing.Client", "Observability.Homework.Tracing.Client\Observability.Homework.Tracing.Client.csproj", "{ED0F7FFB-2DD2-429F-B389-76680F8825C8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,5 +14,9 @@ Global
{FA51BFEE-F62F-4D80-A43A-3C384C62D1AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA51BFEE-F62F-4D80-A43A-3C384C62D1AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA51BFEE-F62F-4D80-A43A-3C384C62D1AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ED0F7FFB-2DD2-429F-B389-76680F8825C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ED0F7FFB-2DD2-429F-B389-76680F8825C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ED0F7FFB-2DD2-429F-B389-76680F8825C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ED0F7FFB-2DD2-429F-B389-76680F8825C8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/Observability.Homework/Observability.Homework.csproj b/Observability.Homework/Observability.Homework.csproj
index e43bf48..18a651e 100644
--- a/Observability.Homework/Observability.Homework.csproj
+++ b/Observability.Homework/Observability.Homework.csproj
@@ -7,6 +7,12 @@
+
+
+
+
+
+
diff --git a/Observability.Homework/Program.cs b/Observability.Homework/Program.cs
index 6b38bc5..d1545e6 100644
--- a/Observability.Homework/Program.cs
+++ b/Observability.Homework/Program.cs
@@ -30,15 +30,34 @@
using Observability.Homework.Extensions;
using Observability.Homework.Models;
using Observability.Homework.Services;
+using OpenTelemetry.Resources;
+using OpenTelemetry.Trace;
+var serviceName = "Observability.Homework";
var builder = WebApplication.CreateBuilder(args);
-
+//builder.AppLogging();
+//Trace don,t work with logging=(
+builder.Logging.ClearProviders();
+builder.Services.AddOpenTelemetry().WithTracing(tcb =>
+{
+ tcb
+ .AddSource(serviceName)
+ .SetResourceBuilder(
+ ResourceBuilder.CreateDefault()
+ .AddService(serviceName: serviceName))
+ .AddAspNetCoreInstrumentation()
+ .AddJaegerExporter();
+});
+builder.Services.AddSingleton(TracerProvider.Default.GetTracer(serviceName));
builder.Services.AddSingleton();
-builder.AppLogging();
+
var app = builder.Build();
-app.MapPost("/order", async ([FromBody] Order order, IPizzaBakeryService pizzaBakeryService, CancellationToken cancellationToken) =>
+app.MapPost("/order", async ([FromServices] Tracer tracer, [FromBody] Order order, IPizzaBakeryService pizzaBakeryService, CancellationToken cancellationToken) =>
{
+ using var span = tracer.StartActiveSpan("Request DoPizza");
+ span.SetAttribute("userId", order.Client.Id);
+ span.SetAttribute("productId", order.Product.Id.ToString());
using (app.Logger.BeginScope(new Dictionary { { "ClientId", order.Client.Id } }))
{
app.Logger.LogInformation("request");
diff --git a/Observability.Homework/Services/PizzaBakeryService.cs b/Observability.Homework/Services/PizzaBakeryService.cs
index 86a16d4..62fe3e9 100644
--- a/Observability.Homework/Services/PizzaBakeryService.cs
+++ b/Observability.Homework/Services/PizzaBakeryService.cs
@@ -1,6 +1,8 @@
using System.Collections.Concurrent;
using Observability.Homework.Exceptions;
using Observability.Homework.Models;
+using OpenTelemetry.Trace;
+
namespace Observability.Homework.Services;
@@ -9,19 +11,15 @@ public interface IPizzaBakeryService
Task DoPizza(Product product, CancellationToken cancellationToken = default);
}
-public class PizzaBakeryService : IPizzaBakeryService
+public class PizzaBakeryService(Tracer tracer, ILogger logger) : IPizzaBakeryService
{
- private readonly ILogger _logger;
+ private readonly Tracer _tracer = tracer;
private readonly ConcurrentDictionary _bake = new();
- public PizzaBakeryService(ILogger logger)
- {
- _logger = logger;
- }
-
public async Task DoPizza(Product product, CancellationToken cancellationToken = default)
{
- _logger.LogInformation("DoPizza id:{productId} type:{productType}",product.Id, product.Type);
+ logger.LogInformation("DoPizza id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("DoPizza");
try
{
await MakePizza(product, cancellationToken);
@@ -29,22 +27,28 @@ public async Task DoPizza(Product product, CancellationToken cancellati
await PackPizza(product, cancellationToken);
return product;
}
- catch (OperationCanceledException)
+ catch (OperationCanceledException ex)
{
- _logger.LogError("PizzaBakeryService cancel do pizza");
+ logger.LogError("PizzaBakeryService cancel do pizza");
+ span.SetStatus(Status.Error.WithDescription("PizzaBakeryService cancel do pizza"));
+ span.RecordException(ex);
DropPizza(product);
throw;
}
- catch (BurntPizzaException)
+ catch (BurntPizzaException ex)
{
- _logger.LogError("PizzaBakeryService burnt pizza");
+ logger.LogError("PizzaBakeryService burnt pizza");
+ span.SetStatus(Status.Error.WithDescription("PizzaBakeryService burnt pizza"));
+ span.RecordException(ex);
return await DoPizza(product, cancellationToken);
}
}
private async Task BakePizza(Product product, CancellationToken cancellationToken = default)
{
- _logger.LogInformation("BakePizza id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("BakePizza");
+ logger.LogInformation("BakePizza id:{productId} type:{productType}",product.Id, product.Type);
+
PushToBake(product);
var bakeForSeconds = new Random().Next(3, 9);
await Task.Delay(TimeSpan.FromSeconds(bakeForSeconds), cancellationToken);
@@ -58,34 +62,44 @@ private async Task BakePizza(Product product, CancellationToken cancell
private async Task MakePizza(Product product, CancellationToken cancellationToken = default)
{
- _logger.LogInformation("MakePizza id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("MakePizza");
+ logger.LogInformation("MakePizza id:{productId} type:{productType}",product.Id, product.Type);
+
await Task.Delay(new Random().Next(1, 3) * 1000, cancellationToken);
return product;
}
private async Task PackPizza(Product product, CancellationToken cancellationToken = default)
{
- _logger.LogInformation("PackPizza id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("PackPizza");
+ logger.LogInformation("PackPizza id:{productId} type:{productType}",product.Id, product.Type);
+
await Task.Delay(new Random().Next(1, 2) * 1000, cancellationToken);
return product;
}
private void PushToBake(Product product)
{
- _logger.LogInformation("PushToBake id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("PushToBake");
+ logger.LogInformation("PushToBake id:{productId} type:{productType}",product.Id, product.Type);
+
_bake[product.Id] = product;
}
private Product PopFromBake(Product product)
{
- _logger.LogInformation("PopFromBake id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("PopFromBake");
+ logger.LogInformation("PopFromBake id:{productId} type:{productType}",product.Id, product.Type);
+
_bake.Remove(product.Id, out var pizza);
return pizza!; //пусть у нас всегда есть пицца
}
private void DropPizza(Product product)
{
- _logger.LogInformation("DropPizza id:{productId} type:{productType}",product.Id, product.Type);
+ using var span = tracer.StartActiveSpan("DropPizza");
+ logger.LogInformation("DropPizza id:{productId} type:{productType}",product.Id, product.Type);
+
_bake.Remove(product.Id, out _);
}
}
\ No newline at end of file
From 1fe4e87ca60637a36763f985bd243ab4d25da43e Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Fri, 25 Oct 2024 13:44:03 +0300
Subject: [PATCH 5/7] added metrics
---
.../Program.cs | 5 +-
.../Observability.Homework.csproj | 2 +
Observability.Homework/Program.cs | 36 ++++++++-----
.../Properties/launchSettings.json | 2 +-
.../Services/PizzaBakeryService.cs | 5 +-
.../Services/PizzeriaMetricsService.cs | 50 +++++++++++++++++++
6 files changed, 84 insertions(+), 16 deletions(-)
create mode 100644 Observability.Homework/Services/PizzeriaMetricsService.cs
diff --git a/Observability.Homework.Tracing.Client/Program.cs b/Observability.Homework.Tracing.Client/Program.cs
index e0591d7..c049cf0 100644
--- a/Observability.Homework.Tracing.Client/Program.cs
+++ b/Observability.Homework.Tracing.Client/Program.cs
@@ -20,8 +20,9 @@
while (true)
{
using var httpClient = new HttpClient();
- var response = await httpClient.PostAsync("http://localhost:5216/order/", JsonContent.Create(Order.Create((ProductType)random.Next(0,2))));
+ var order = Order.Create((ProductType)random.Next(0, 3));
+ var response = await httpClient.PostAsync("http://localhost:5216/order/", JsonContent.Create(order));
response.EnsureSuccessStatusCode();
- Console.WriteLine("Response received successfully.");
+ Console.WriteLine("Response received successfully.{0}",order.Product.Type);
}
diff --git a/Observability.Homework/Observability.Homework.csproj b/Observability.Homework/Observability.Homework.csproj
index 18a651e..b00ff6d 100644
--- a/Observability.Homework/Observability.Homework.csproj
+++ b/Observability.Homework/Observability.Homework.csproj
@@ -11,6 +11,8 @@
+
+
diff --git a/Observability.Homework/Program.cs b/Observability.Homework/Program.cs
index d1545e6..54a2081 100644
--- a/Observability.Homework/Program.cs
+++ b/Observability.Homework/Program.cs
@@ -30,6 +30,7 @@
using Observability.Homework.Extensions;
using Observability.Homework.Models;
using Observability.Homework.Services;
+using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
@@ -38,26 +39,37 @@
//builder.AppLogging();
//Trace don,t work with logging=(
builder.Logging.ClearProviders();
-builder.Services.AddOpenTelemetry().WithTracing(tcb =>
-{
- tcb
- .AddSource(serviceName)
- .SetResourceBuilder(
- ResourceBuilder.CreateDefault()
- .AddService(serviceName: serviceName))
- .AddAspNetCoreInstrumentation()
- .AddJaegerExporter();
-});
+builder.Services
+ .AddOpenTelemetry()
+ // .WithTracing(tcb =>
+ // {
+ // tcb
+ // .AddSource(serviceName)
+ // .SetResourceBuilder(
+ // ResourceBuilder.CreateDefault()
+ // .AddService(serviceName: serviceName))
+ // .AddAspNetCoreInstrumentation()
+ // .AddJaegerExporter();
+ // })
+ .WithMetrics(mpb => mpb
+ .AddAspNetCoreInstrumentation()
+ //.AddRuntimeInstrumentation()
+ //.AddProcessInstrumentation()
+ .AddPrometheusExporter()
+ .AddMeter(PizzeriaMetricsService.MeterName)
+ );
builder.Services.AddSingleton(TracerProvider.Default.GetTracer(serviceName));
builder.Services.AddSingleton();
+builder.Services.AddSingleton();
var app = builder.Build();
-
-app.MapPost("/order", async ([FromServices] Tracer tracer, [FromBody] Order order, IPizzaBakeryService pizzaBakeryService, CancellationToken cancellationToken) =>
+app.MapPrometheusScrapingEndpoint();
+app.MapPost("/order", async ([FromServices] Tracer tracer,PizzeriaMetricsService metric, [FromBody] Order order, IPizzaBakeryService pizzaBakeryService, CancellationToken cancellationToken) =>
{
using var span = tracer.StartActiveSpan("Request DoPizza");
span.SetAttribute("userId", order.Client.Id);
span.SetAttribute("productId", order.Product.Id.ToString());
+ metric.ProductType(order.Product);
using (app.Logger.BeginScope(new Dictionary { { "ClientId", order.Client.Id } }))
{
app.Logger.LogInformation("request");
diff --git a/Observability.Homework/Properties/launchSettings.json b/Observability.Homework/Properties/launchSettings.json
index 5ccdcce..9a7f4fa 100644
--- a/Observability.Homework/Properties/launchSettings.json
+++ b/Observability.Homework/Properties/launchSettings.json
@@ -22,7 +22,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "applicationUrl": "https://localhost:7205;http://localhost:5216",
+ "applicationUrl": "https://localhost:7242;http://localhost:5216",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/Observability.Homework/Services/PizzaBakeryService.cs b/Observability.Homework/Services/PizzaBakeryService.cs
index 62fe3e9..5e0c513 100644
--- a/Observability.Homework/Services/PizzaBakeryService.cs
+++ b/Observability.Homework/Services/PizzaBakeryService.cs
@@ -11,8 +11,9 @@ public interface IPizzaBakeryService
Task DoPizza(Product product, CancellationToken cancellationToken = default);
}
-public class PizzaBakeryService(Tracer tracer, ILogger logger) : IPizzaBakeryService
+public class PizzaBakeryService(Tracer tracer, ILogger logger, PizzeriaMetricsService pizzeriaMetricsService) : IPizzaBakeryService
{
+ private readonly PizzeriaMetricsService _metrics = pizzeriaMetricsService;
private readonly Tracer _tracer = tracer;
private readonly ConcurrentDictionary _bake = new();
@@ -29,6 +30,7 @@ public async Task DoPizza(Product product, CancellationToken cancellati
}
catch (OperationCanceledException ex)
{
+ _metrics.ProductCancel();
logger.LogError("PizzaBakeryService cancel do pizza");
span.SetStatus(Status.Error.WithDescription("PizzaBakeryService cancel do pizza"));
span.RecordException(ex);
@@ -37,6 +39,7 @@ public async Task DoPizza(Product product, CancellationToken cancellati
}
catch (BurntPizzaException ex)
{
+ _metrics.ProductBurnt();
logger.LogError("PizzaBakeryService burnt pizza");
span.SetStatus(Status.Error.WithDescription("PizzaBakeryService burnt pizza"));
span.RecordException(ex);
diff --git a/Observability.Homework/Services/PizzeriaMetricsService.cs b/Observability.Homework/Services/PizzeriaMetricsService.cs
new file mode 100644
index 0000000..1093723
--- /dev/null
+++ b/Observability.Homework/Services/PizzeriaMetricsService.cs
@@ -0,0 +1,50 @@
+using System.Diagnostics.Metrics;
+using Observability.Homework.Models;
+
+namespace Observability.Homework.Services;
+
+public class PizzeriaMetricsService
+{
+ public static readonly string MeterName = "Observability.Metrics.Pizzeria";
+
+ private const string ProductTypeMetricName = "pizzeria.product.type";
+ private const string ProductBurntMetricName = "pizzeria.product.burnt";
+ private const string ProductCancelMetricName = "pizzeria.product.cancel";
+ private const string ProductCookingTimeMetricName = "pizzeria.product.cooking.time";
+ private const string ProductCookingCountMetricName = "pizzeria.product.cooking.count";
+
+ private readonly Counter _productTypeCounter;
+ private readonly Counter _productBurntCounter;
+ private readonly Counter _productCancelCounter;
+
+ public PizzeriaMetricsService(IMeterFactory meterFactory)
+ {
+ var meter = meterFactory.Create(MeterName);
+ _productTypeCounter = meter.CreateCounter(ProductTypeMetricName);
+ _productBurntCounter = meter.CreateCounter(ProductBurntMetricName);
+ _productCancelCounter = meter.CreateCounter(ProductCancelMetricName);
+ }
+
+ public void ProductType(Product product)
+ {
+ _productTypeCounter.Add(1, new KeyValuePair[]
+ {
+ new("product.type", product.Type.ToString()),
+ });
+ }
+
+ public void ProductBurnt()
+ {
+ _productBurntCounter.Add(1);
+ }
+
+ public void ProductCancel()
+ {
+ _productCancelCounter.Add(1);
+ }
+
+ public void RecordProductCooking(Product product, double cookingTime)
+ {
+
+ }
+}
\ No newline at end of file
From 5f07623241338042ccb66053eedd9be096f7a914 Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Fri, 25 Oct 2024 14:42:10 +0300
Subject: [PATCH 6/7] added baking counter and cooking time
---
Observability.Homework.Tracing.Client/Program.cs | 14 +++++++++-----
Observability.Homework/Program.cs | 2 ++
.../Services/PizzaBakeryService.cs | 1 +
.../Services/PizzeriaMetricsService.cs | 13 +++++++++++--
4 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/Observability.Homework.Tracing.Client/Program.cs b/Observability.Homework.Tracing.Client/Program.cs
index c049cf0..f9f25f8 100644
--- a/Observability.Homework.Tracing.Client/Program.cs
+++ b/Observability.Homework.Tracing.Client/Program.cs
@@ -19,10 +19,14 @@
Random random = new Random();
while (true)
{
- using var httpClient = new HttpClient();
- var order = Order.Create((ProductType)random.Next(0, 3));
- var response = await httpClient.PostAsync("http://localhost:5216/order/", JsonContent.Create(order));
- response.EnsureSuccessStatusCode();
- Console.WriteLine("Response received successfully.{0}",order.Product.Type);
+ Parallel.For(0, 30, _ =>
+ {
+ using var httpClient = new HttpClient();
+ var order = Order.Create((ProductType)random.Next(0, 3));
+ var response = httpClient.PostAsync("http://localhost:5216/order/", JsonContent.Create(order)).Result;
+ response.EnsureSuccessStatusCode();
+ Console.WriteLine("Response received successfully.{0}", order.Product.Type);
+ });
+
}
diff --git a/Observability.Homework/Program.cs b/Observability.Homework/Program.cs
index 54a2081..59a8fbf 100644
--- a/Observability.Homework/Program.cs
+++ b/Observability.Homework/Program.cs
@@ -70,12 +70,14 @@
span.SetAttribute("userId", order.Client.Id);
span.SetAttribute("productId", order.Product.Id.ToString());
metric.ProductType(order.Product);
+ DateTime start = DateTime.Now;
using (app.Logger.BeginScope(new Dictionary { { "ClientId", order.Client.Id } }))
{
app.Logger.LogInformation("request");
if (order.Product.Type is ProductType.Pizza)
await pizzaBakeryService.DoPizza(order.Product, cancellationToken);
}
+ metric.RecordProductCooking((DateTime.Now-start).Microseconds);
return Results.Ok(order.Product);
});
diff --git a/Observability.Homework/Services/PizzaBakeryService.cs b/Observability.Homework/Services/PizzaBakeryService.cs
index 5e0c513..4ad7069 100644
--- a/Observability.Homework/Services/PizzaBakeryService.cs
+++ b/Observability.Homework/Services/PizzaBakeryService.cs
@@ -20,6 +20,7 @@ public class PizzaBakeryService(Tracer tracer, ILogger logge
public async Task DoPizza(Product product, CancellationToken cancellationToken = default)
{
logger.LogInformation("DoPizza id:{productId} type:{productType}",product.Id, product.Type);
+ _metrics.ProductBakingCount(_bake.Count);
using var span = tracer.StartActiveSpan("DoPizza");
try
{
diff --git a/Observability.Homework/Services/PizzeriaMetricsService.cs b/Observability.Homework/Services/PizzeriaMetricsService.cs
index 1093723..e8f26f5 100644
--- a/Observability.Homework/Services/PizzeriaMetricsService.cs
+++ b/Observability.Homework/Services/PizzeriaMetricsService.cs
@@ -16,6 +16,8 @@ public class PizzeriaMetricsService
private readonly Counter _productTypeCounter;
private readonly Counter _productBurntCounter;
private readonly Counter _productCancelCounter;
+ private readonly Histogram _productCookingTime;
+ private readonly Histogram _productBakingCounter;
public PizzeriaMetricsService(IMeterFactory meterFactory)
{
@@ -23,6 +25,8 @@ public PizzeriaMetricsService(IMeterFactory meterFactory)
_productTypeCounter = meter.CreateCounter(ProductTypeMetricName);
_productBurntCounter = meter.CreateCounter(ProductBurntMetricName);
_productCancelCounter = meter.CreateCounter(ProductCancelMetricName);
+ _productCookingTime = meter.CreateHistogram(ProductCookingTimeMetricName);
+ _productBakingCounter = meter.CreateHistogram(ProductCookingCountMetricName);
}
public void ProductType(Product product)
@@ -43,8 +47,13 @@ public void ProductCancel()
_productCancelCounter.Add(1);
}
- public void RecordProductCooking(Product product, double cookingTime)
+ public void RecordProductCooking(double cookingTime)
{
-
+ _productCookingTime.Record(cookingTime);
+ }
+
+ public void ProductBakingCount(int bakingCount)
+ {
+ _productBakingCounter.Record(bakingCount);
}
}
\ No newline at end of file
From 62c674433fc824aaed3bf097cfe56d0baa2dbd40 Mon Sep 17 00:00:00 2001
From: Pavel <98314322+PavelRnD@users.noreply.github.com>
Date: Fri, 25 Oct 2024 14:53:35 +0300
Subject: [PATCH 7/7] With tracing
---
Observability.Homework/Program.cs | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/Observability.Homework/Program.cs b/Observability.Homework/Program.cs
index 59a8fbf..d1a2804 100644
--- a/Observability.Homework/Program.cs
+++ b/Observability.Homework/Program.cs
@@ -41,16 +41,16 @@
builder.Logging.ClearProviders();
builder.Services
.AddOpenTelemetry()
- // .WithTracing(tcb =>
- // {
- // tcb
- // .AddSource(serviceName)
- // .SetResourceBuilder(
- // ResourceBuilder.CreateDefault()
- // .AddService(serviceName: serviceName))
- // .AddAspNetCoreInstrumentation()
- // .AddJaegerExporter();
- // })
+ .WithTracing(tcb =>
+ {
+ tcb
+ .AddSource(serviceName)
+ .SetResourceBuilder(
+ ResourceBuilder.CreateDefault()
+ .AddService(serviceName: serviceName))
+ .AddAspNetCoreInstrumentation()
+ .AddJaegerExporter();
+ })
.WithMetrics(mpb => mpb
.AddAspNetCoreInstrumentation()
//.AddRuntimeInstrumentation()