引入Jaeger——封装

2023-11-06 02:48
文章标签 封装 引入 jaeger

本文主要是介绍引入Jaeger——封装,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

随着微服务的普及,微服务间的调用全链路跟踪也火了起来,Jaeger(https://www.jaegertracing.io/)是CNCF孵化的全链路跟踪型项目,在.net core中,提供了一个Jaeger的Nuget(https://github.com/jaegertracing/jaeger-client-csharp)包来使用。

本例封装就是用这个Nuget包来做成asp.net core中间件和action过滤器:中间件可以把所有经过管道的请求都跟踪起来,如果觉得这样的跟踪太重,或者没有必要收集所有请求,只跟踪有链路关联的请求,那就可以用action过滤器。

定义一个Options,这是自定义跟踪收集数据的配置属性

namespace JaegerSharp
{/// <summary>/// Jaeger选项/// </summary>public class JaegerOptions{/// <summary>/// 是否启用Form数据转成Span/// </summary>public bool IsFormSpan { get; set; } = false;/// <summary>/// Form数据最大长度/// </summary>public int FormValueMaxLength { get; set; } = 100;/// <summary>/// 是否启用Query数据转成Span/// </summary>public bool IsQuerySpan { get; set; } = false;/// <summary>/// Query最大长度/// </summary>public int QueryValueMaxLength { get; set; } = 100;/// <summary>/// Form或Query中不作为Span的key集合/// </summary>public string[] NoSpanKeys { get; set; } = new string[] { "password", "pwd" };}
}

跟踪中间件,把所有的请求都收集起来

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using OpenTracing;
using OpenTracing.Propagation;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;namespace JaegerSharp
{/// <summary>/// Jaeger中间件/// </summary>public class JaegerSharpMiddleware{/// <summary>/// jaeger选项/// </summary>private readonly JaegerOptions _jaegerOptions;/// <summary>/// 日志/// </summary>private readonly ILogger<JaegerSharpMiddleware> _logger;/// <summary>/// 请求代理/// </summary>private readonly RequestDelegate _next;public JaegerSharpMiddleware(RequestDelegate next, ILogger<JaegerSharpMiddleware> logger, JaegerOptions jaegerOptions = null){_next = next;_jaegerOptions = jaegerOptions;_logger = logger;}/// <summary>/// 调用管道/// </summary>/// <param name="context">上下文</param>/// <param name="tracer">跟踪器</param>/// <returns></returns>public async Task InvokeAsync(HttpContext context, ITracer tracer){_logger.LogInformation("jaeger调用");var path = context.Request.Path;if (Path.HasExtension(path)){await _next(context);}else{//接收传入的Headersvar callingHeaders = new TextMapExtractAdapter(context.Request.Headers.ToDictionary(m => m.Key, m => m.Value.ToString()));var spanContex = tracer.Extract(BuiltinFormats.HttpHeaders, callingHeaders);ISpanBuilder builder = null;if (spanContex != null){builder = tracer.BuildSpan("中间件Span").AsChildOf(spanContex);}else{builder = tracer.BuildSpan("中间件Span");}//开始设置Spanusing (IScope scope = builder.StartActive(true)){scope.Span.SetOperationName(path);             // 记录请求信息到spanif (_jaegerOptions.IsQuerySpan){foreach (var query in context.Request.Query){//包含敏感词跳出if (_jaegerOptions.NoSpanKeys.Contains(query.Key)){continue;}var value = query.Value.ToString().Length > _jaegerOptions.QueryValueMaxLength ? query.Value.ToString()?.Substring(0, _jaegerOptions.QueryValueMaxLength) : query.Value.ToString();scope.Span.SetTag(query.Key, value);}}if (_jaegerOptions.IsFormSpan && context.Request.HasFormContentType){foreach (var form in context.Request.Form){//包含敏感词跳出if (_jaegerOptions.NoSpanKeys.Contains(form.Key)){continue;}var value = form.Value.ToString().Length > _jaegerOptions.FormValueMaxLength ? form.Value.ToString()?.Substring(0, _jaegerOptions.FormValueMaxLength) : form.Value.ToString();scope.Span.SetTag(form.Key, value);}}await _next(context);}}}}
}

扩展中间件

using Microsoft.AspNetCore.Builder;namespace JaegerSharp
{/// <summary>/// 使用JaegerSharp中间件/// </summary>public static class JaegerSharpMiddlewareExtensions{public static IApplicationBuilder UseJaegerSharp(this IApplicationBuilder builder){return builder.UseMiddleware<JaegerSharpMiddleware>(new JaegerOptions());}public static IApplicationBuilder UseJaegerSharp(this IApplicationBuilder builder, JaegerOptions jaegerOptions){return builder.UseMiddleware<JaegerSharpMiddleware>(jaegerOptions);}}
}

action过滤器,用来准确收集跟踪信息

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using OpenTracing;
using OpenTracing.Propagation;
using System.Linq;namespace JaegerSharp
{/// <summary>/// 使用Jaeger的Action过滤器添加Jaeger实列/// </summary>public class JaegerSharpAttribute : TypeFilterAttribute{public JaegerSharpAttribute() : base(typeof(JaegerFilterAttributeImpl)){}/// <summary>/// 真正实现Jaeger Scope的类/// </summary>private class JaegerFilterAttributeImpl : IActionFilter{private readonly ITracer _tracer;public JaegerFilterAttributeImpl(ITracer tracer){_tracer = tracer;}IScope _scope = null;/// <summary>/// 开始执行Action/// </summary>/// <param name="context"></param>public void OnActionExecuting(ActionExecutingContext context){var path = context.HttpContext.Request.Path;var callingHeaders = new TextMapExtractAdapter(context.HttpContext.Request.Headers.ToDictionary(m => m.Key, m => m.Value.ToString()));var spanContex = _tracer.Extract(BuiltinFormats.HttpHeaders, callingHeaders);ISpanBuilder builder = null;if (spanContex != null){builder = _tracer.BuildSpan("中间件Span").AsChildOf(spanContex);}else{builder = _tracer.BuildSpan("中间件Span");}_scope = builder.StartActive(true);_scope.Span.SetOperationName(path);// 记录请求信息到spanforeach (var query in context.HttpContext.Request.Query){_scope.Span.SetTag(query.Key, query.Value);}if (context.HttpContext.Request.HasFormContentType){foreach (var form in context.HttpContext.Request.Form){_scope.Span.SetTag(form.Key, form.Value);}}}/// <summary>/// Action结束执行/// </summary>/// <param name="context"></param>public void OnActionExecuted(ActionExecutedContext context){_scope?.Dispose();}}}
}

封装Jaeger在asp.net core中的注放步骤,使注入简单

using Jaeger;
using Jaeger.Reporters;
using Jaeger.Samplers;
using Jaeger.Senders.Thrift;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using OpenTracing;
using OpenTracing.Util;
using System.Reflection;namespace JaegerSharp
{public static class JaegerSharpExtensions{/// <summary>/// 注入Jaeger/// </summary>/// <param name="services">服务容器</param>/// <param name="host">Jaeger agent host</param>/// <param name="port">Jaeger agent port</param>/// <param name="maxPacketSize">Jaeger agent maxpacketsize</param>public static void AddJaegerSharp(this IServiceCollection services, string host, int port, int maxPacketSize){     services.AddSingleton<ITracer>(serviceProvider =>{var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();              var reporter = new RemoteReporter.Builder().WithLoggerFactory(loggerFactory).WithSender(new UdpSender(string.IsNullOrEmpty(host) ? UdpSender.DefaultAgentUdpHost : host,port <= 100 ? UdpSender.DefaultAgentUdpCompactPort : port,maxPacketSize <= 0 ? 0 : maxPacketSize)).Build();ITracer tracer = new Tracer.Builder(Assembly.GetEntryAssembly().GetName().Name).WithReporter(reporter).WithLoggerFactory(loggerFactory).WithSampler(new ConstSampler(true)).Build();GlobalTracer.Register(tracer);return tracer;});}}
}

这篇关于引入Jaeger——封装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/354044

相关文章

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

SW - 引入第三方dwg图纸后,修改坐标原点

文章目录 SW - 引入第三方dwg图纸后,修改坐标原点概述笔记设置图纸新原点END SW - 引入第三方dwg图纸后,修改坐标原点 概述 在solidworks中引入第三方的dwg格式图纸后,坐标原点大概率都不合适。 全图自动缩放后,引入的图纸离默认的原点位置差很多。 需要自己重新设置原点位置,才能自动缩放后,在工作区中间显示引入的图纸。 笔记 将dwg图纸拖到SW中

react笔记 8-17 属性绑定 class绑定 引入图片 循环遍历

1、绑定属性 constructor(){super()this.state={name:"张三",title:'我是一个title'}}render() {return (<div><div>aaaaaaa{this.state.name}<div title={this.state.title}>我是一个title</div></div></div>)} 绑定属性直接使用花括号{}   注

YOLOv8改进实战 | 注意力篇 | 引入CVPR2024 PKINet 上下文锚点注意力CAAttention

YOLOv8专栏导航:点击此处跳转 前言 YOLOv8 是由 YOLOv5 的发布者 Ultralytics 发布的最新版本的 YOLO。它可用于对象检测、分割、分类任务以及大型数据集的学习,并且可以在包括 CPU 和 GPU 在内的各种硬件上执行。 YOLOv8 是一种尖端的、最先进的 (SOTA) 模型,它建立在以前成功的 YOLO 版本的基础上,并引入了新的功能和改进,以

fetch-event-source 如何通过script全局引入

fetchEventSource源码中导出了两种类型的包cjs和esm。但是有个需求如何在原生是js中通过script标签引呢?需要加上type=module。今天介绍另一种方法 下载源码文件: https://github.com/Azure/fetch-event-source.git 安装: npm install --save-dev webpack webpack-cli ts

YOLOv8改进 | Conv篇 | YOLOv8引入DWR

1. DWR介绍 1.1  摘要:当前的许多工作直接采用多速率深度扩张卷积从一个输入特征图中同时捕获多尺度上下文信息,从而提高实时语义分割的特征提取效率。 然而,这种设计可能会因为结构和超参数的不合理而导致多尺度上下文信息的访问困难。 为了降低多尺度上下文信息的绘制难度,我们提出了一种高效的多尺度特征提取方法,将原始的单步方法分解为区域残差-语义残差两个步骤。 在该方法中,多速率深度扩张卷积

Java封装构造方法

private/public的分装 被public修饰的成员变量或者是成员方法,可以被类的调用对象直接使用 而private修饰的成员变量和方法,不能被类的调用对象使用 例如: 可以看到我们是不能在main方法中直接调用被private修饰的变量 当然我们可以在我们定义的TestMode类中可以定一个方法show,然后在调用show方法实现 这里我们可以清楚了解 private 不光可以修

C++数据结构重要知识点(5)(哈希表、unordered_map和unordered_set封装)

1.哈希思想和哈希表 (1)哈希思想和哈希表的区别 哈希(散列、hash)是一种映射思想,本质上是值和值建立映射关系,key-value就使用了这种思想。哈希表(散列表,数据结构),主要功能是值和存储位置建立映射关系,它通过key-value模型中的key来定位数组的下标,将value存进该位置。 哈希思想和哈希表数据结构这两个概念要分清,哈希是哈希表的核心思想。 (2)unordered