当前位置: 首页 > news >正文

【APM】NET Traces, Metrics and Logs to OLTP

 系列文章目录

【APM】Observability Solution

【APM】Build an environment for Traces, Metrics and Logs of App by OpenTelemetry

【APM】NET Traces, Metrics and Logs to OLTP

【APM】How to enable Trace to Logs on Grafana?


前言

前一篇分享了Observability(可观测性)环境的安装,本篇继续分享其应用。


一、Create a new project by NET

ASP.Net Core WebApi


二、PackageReference installation

  • Npgsql
  • Npgsql.EntityFrameworkCore.PostgreSQL
  • Npgsql.OpenTelemetry
  • OpenTelemetry.Exporter.Console
  • OpenTelemetry.Exporter.OpenTelemetryProtocol
  • OpenTelemetry.Extensions.Hosting
  • OpenTelemetry.Instrumentation.AspNetCore
  • OpenTelemetry.Instrumentation.Http
  • OpenTelemetry.Instrumentation.Runtime

三、Configure OpenTelemetry logging, metrics, & tracing

1.Program.cs

代码如下(示例):

        private static readonly string ServiceName = typeof(Program).Namespace ?? "NetLog2Otlp";private static readonly string ServiceVersion = typeof(Program).Assembly.GetName().Version?.ToString() ?? "unknown";public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);#region Configure OpenTelemetry logging, metrics, & tracingstring otlpEndpoint = builder.Configuration.GetValue("Otlp:Endpoint", defaultValue: "http://localhost:4317");// Configure OpenTelemetry logging, metrics, & tracing with auto-start using the// AddOpenTelemetry extension from OpenTelemetry.Extensions.Hosting.builder.Services.AddOpenTelemetry().ConfigureResource(r => r.AddService(serviceName: ServiceName,serviceVersion: ServiceVersion,serviceInstanceId: Environment.MachineName)).WithTracing(_builder =>{// Tracing// Ensure the TracerProvider subscribes to any custom ActivitySources._builder.AddSource(InstrumentationSource.ActivitySourceName).SetSampler(new AlwaysOnSampler()).AddHttpClientInstrumentation()  // 监控 HttpClient 请求.AddAspNetCoreInstrumentation()  // 监控 ASP.NET Core 请求.AddNpgsql();                      // 监控 SQL 查询// Use IConfiguration binding for AspNetCore instrumentation options.builder.Services.Configure<AspNetCoreTraceInstrumentationOptions>(builder.Configuration.GetSection("AspNetCoreInstrumentation"));_builder.AddOtlpExporter(otlpOptions =>{// Use IConfiguration directly for Otlp exporter endpoint option.otlpOptions.Endpoint = new Uri(otlpEndpoint);});}).WithMetrics(_builder =>{// Metrics// Ensure the MeterProvider subscribes to any custom Meters._builder.AddMeter(InstrumentationSource.MeterName).SetExemplarFilter(ExemplarFilterType.TraceBased).AddRuntimeInstrumentation()     // 监控 .NET 运行时指标.AddHttpClientInstrumentation()  // 监控 HttpClient 请求.AddAspNetCoreInstrumentation(); // 监控 ASP.NET Core 请求_builder.AddOtlpExporter(otlpOptions =>{// Use IConfiguration directly for Otlp exporter endpoint option.otlpOptions.Endpoint = new Uri(otlpEndpoint);});}).WithLogging(_builder =>{// Note: See appsettings.json Logging:OpenTelemetry section for configuration._builder.AddOtlpExporter(otlpOptions =>{// Use IConfiguration directly for Otlp exporter endpoint option.otlpOptions.Endpoint = new Uri(otlpEndpoint);}).AddConsoleExporter();});#endregion// Add services to the container....

2.appsettings.json

代码如下(示例):

{"Logging": {"LogLevel": {"Default": "Warning","Microsoft": "Warning","Microsoft.AspNetCore": "Warning","Microsoft.Hosting.Lifetime": "Warning","System": "Warning","NetLog2Otlp": "Information"},"OpenTelemetry": {"IncludeFormattedMessage": true,"IncludeScopes": true,"ParseStateValues": true}},"Otlp": {"Endpoint": "http://localhost:4317"},"AspNetCoreInstrumentation": {"RecordException": "true"},"AllowedHosts": "*"
}

 3.InstrumentationSource.cs

namespace NetLog2Otlp.AspNetCore;using System.Diagnostics;
using System.Diagnostics.Metrics;/// <summary>
/// It is recommended to use a custom type to hold references for
/// ActivitySource and Instruments. This avoids possible type collisions
/// with other components in the DI container.
/// </summary>
public sealed class InstrumentationSource : IDisposable
{internal const string ActivitySourceName = "NetLog2Otlp.AspNetCore";internal const string MeterName = "NetLog2Otlp.AspNetCore";private readonly Meter meter;public InstrumentationSource(){string? version = typeof(InstrumentationSource).Assembly.GetName().Version?.ToString();this.ActivitySource = new ActivitySource(ActivitySourceName, version);this.meter = new Meter(MeterName, version);this.FreezingDaysCounter = this.meter.CreateCounter<long>("weather.days.freezing", description: "The number of days where the temperature is below freezing");}public ActivitySource ActivitySource { get; }public Counter<long> FreezingDaysCounter { get; }public void Dispose(){this.ActivitySource.Dispose();this.meter.Dispose();}
}

4.OtlpController.cs

using Microsoft.AspNetCore.Mvc;
using Npgsql;
using System.Collections.Generic;
using System.Reflection.Emit;
using Microsoft.EntityFrameworkCore;// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860namespace NetLog2Otlp.Controllers
{[Route("api/[controller]")][ApiController]public class OtlpController : ControllerBase{private readonly ILogger<OtlpController> _logger;// 使用依赖注入获取 Loggerpublic OtlpController(ILogger<OtlpController> logger){_logger = logger;}// GET: api/<OtlpController>[HttpGet]public IEnumerable<string> Get(){_logger.LogInformation("Start logging at {time}", DateTime.Now);try{ExecuteSql();_logger.LogInformation(" ExecuteSql finished at {time}", DateTime.Now);ExecuteEF();_logger.LogInformation(" ExecuteEF finished at {time}", DateTime.Now);HttpRequest();_logger.LogInformation(" Test API called at {time}", DateTime.Now);int i = 0;var j = i / 0; // This will throw a divide by zero exception}catch (Exception ex){_logger.LogError(ex, " An error occurred during the logging process.");}finally{_logger.LogInformation("End logging at {time}", DateTime.Now);}return new string[] { "value1", "value2", DateTime.Now.ToString() };}// GET api/<OtlpController>/5[HttpGet("{id}")]public string Get(int id = 0){_logger.LogDebug("LogDebug");_logger.LogInformation("LogInformation");_logger.LogWarning("LogWarning");_logger.LogError("LogError");_logger.LogInformation("Get by id API called at {time}, id: {id}", DateTime.Now, id.ToString());return string.Format("value: {0}", id.ToString());}void ExecuteSql(){// PostgreSQL 连接字符串var connectionString = "Host=192.168.1.1;Port=5432;Username=user;Password=user;Database=TestDB";// 使用 Npgsql 连接到 PostgreSQL 数据库using (var connection = new NpgsqlConnection(connectionString)){connection.Open();// 创建查询命令using (var command = new NpgsqlCommand("SELECT * FROM test1", connection)){// 执行查询并读取结果using (var reader = command.ExecuteReader()){while (reader.Read()){// 假设你的表中有列 "id" 和 "name"string id = reader.GetString(0); // 获取第一列的值string name = reader.GetString(1); // 获取第二列的值Console.WriteLine($"ID: {id}, Name: {name}");}}}}}void ExecuteEF(){using (var context = new MyDbContext()){// Read all entriesvar entities = context.MyEntities.ToList();// Create a new entryvar newEntity = new MyEntity { apid = "ExecuteEF", name = "New Entity", site = "*", url = "*" };context.MyEntities.Add(newEntity);context.SaveChanges();// Update an entryvar entity = context.MyEntities.Where(o => o.apid == "ExecuteEF").FirstOrDefault();if (entity.apid != null){entity.name = "Updated Name";context.SaveChanges();}// Delete an entrycontext.MyEntities.Remove(entity);context.SaveChanges();}}async void HttpRequest(){try{// 這裡替換成你要請求的 URLstring url = "https://www.baidu.com";using (var client = new HttpClient()){HttpResponseMessage response = await client.GetAsync(url);response.EnsureSuccessStatusCode();  // 會拋出異常如果 HTTP 請求不成功string responseBody = await response.Content.ReadAsStringAsync();Console.WriteLine(responseBody);}}catch (HttpRequestException e){Console.WriteLine("Request error: {0}", e.Message);}}}public class MyDbContext : DbContext{public MyDbContext(){}public MyDbContext(DbContextOptions<MyDbContext> options): base(options){}// Define DbSet for each entity in your database schemapublic DbSet<MyEntity> MyEntities { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){// PostgreSQL 连接字符串var connectionString = "Host=192.168.1.1;Port=5432;Username=user;Password=user;Database=TestDB";// Configure PostgreSQL as the database provideroptionsBuilder.UseNpgsql(connectionString);}protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<MyEntity>().HasKey(e => e.apid);  // 指定主鍵是 apid 屬性modelBuilder.Entity<MyEntity>().ToTable("test1"); // 將 MyEntity 對應到名為 "test1" 的資料庫表}}public class MyEntity{public string apid { get; set; }public string name { get; set; }public string url { get; set; }public string site { get; set; }}}

四、项目文件结构及运行结果

1.项目文件结构

2.运行结果

Traces

Trace to Logs


总结

本文介绍了 NET Traces, Metrics and Logs to OLTP,以及如何在Grafana呈现 Traces 和 Trace to Logs。下篇文章将介绍 Trace to Logs 是如何实现?

相关文章:

  • 期货数据API对接实战指南
  • win11改回win10
  • 每日一题(小白)暴力娱乐篇31
  • Electricity Market Optimization(VI) - 机组组合问题的 GAMS 求解
  • 论文研读: LLaVA, 微调大模型以理解图像内容
  • pycharm配置python编译器,安装第三方库 (通俗易懂)
  • 【web考试系统的设计】
  • 前端开发 + Vue 2 + 卡片拖拽(带坐标系、左右互拖、多卡同容器)+ 学习参考
  • QT日历控件重写美化
  • T113S3学习记录—软件说明(三)
  • Linux:初学者的简单指令
  • CST仿真天线流程
  • 【Linux】第十章 配置和保护SSH
  • 探索Adobe软件的冷门技巧
  • Spring DI 详解
  • @Autowird 注解与存在多个相同类型对象的解方案
  • 【英语语法】基本句型
  • 大模型如何改变我们的日常生活
  • vue3 el-dialog新增弹窗,不希望一进去就校验名称没有填写
  • LeetCode hot 100—单词搜索
  • 国家核准10台核电新机组,四大核电央企披露新项目进展
  • 日月谭天丨赖清德强推“脱中入北”是把台湾带向死路
  • 国家卫健委:工作相关肌肉骨骼疾病、精神和行为障碍成职业健康新挑战
  • 持续更新丨伊朗港口爆炸事件已致561人受伤
  • 苏迪曼杯即将在厦门打响,国羽向创纪录的14冠进军
  • 广西给出最后期限:6月30日之前主动交代问题可从宽处理