引入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;});}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306093.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

临近年关,发生两起磁盘占满引发的服务下线故障

一口气说两个因为磁盘空间不足引发的应用故障。作为拿起键盘一把梭的Coder&#xff0c; 开发--->部署-->收工--->心旷神怡&#xff0c;滋一口82年的可乐.过了几个月&#xff0c;服务突然下线了&#xff01;CTO又有杀程序员祭天的理由了!事故1&#xff1a;Azure App Se…

c语言幼儿园积木游戏,幼儿园《积木游戏》课件【三篇】

【导语】课件制作本身就是作者综合素养的一种体现&#xff0c;它显现出制作者对教育、教学、教材改革方向的把握&#xff0c;对课堂教学的理解&#xff0c;对现代教育技术的领悟。因此教师在设计课件时一定要吃透教学内容&#xff0c;设计出符合教学的方案用于课件。下面是无忧…

蚂蚁调度AntJob-分布式任务调度系统

分布式任务调度系统&#xff0c;纯NET打造的重量级大数据实时计算平台&#xff0c;万亿级调度经验积累&#xff01;面向中小企业大数据分析场景。开源地址&#xff1a;https://github.com/NewLifeX/AntJob使用教程&#xff1a;https://www.yuque.com/smartstone/blood/antjob体…

c语言怎么让图形界面单独显示,「分享」C语言如何编写图形界面

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼贴吧内经常有人问C语言是不是只能用于字符终端界面开发&#xff0c;不能用于图形界面。大家也都有回答&#xff0c;需要其他的库。MFC&#xff0c;GTK&#xff0c;QT。本人近期刚用GTK库加上纯C写成了第一个LINUX实用程序。现在与大…

如何在 ASP.NET Core 中 自定义中间件

ASP.NET Core 是一个跨平台&#xff0c;开源的&#xff0c;轻量级&#xff0c;高性能 并且高度模块化的web框架&#xff0c;同时扩展性也是非常强&#xff0c;你可以在 request -> response 请求管道中安插各种中间件来根据自己的场景定制化&#xff0c;比如说&#xff1a;监…

ASP.NET Core Authentication and Authorization

最近把一个Asp .net core 2.0的项目迁移到Asp .net core 3.1&#xff0c;项目启动的时候直接报错:InvalidOperationException: Endpoint CoreAuthorization.Controllers.HomeController.Index (CoreAuthorization) contains authorization metadata, but a middleware was not …

android dialog 自定义布局,如何设置AlertDialog的自定义布局?

调用我的对话框:alertDialog showInfoDialog(message "$wrongPasscodeMessage\n$retryMessage")方法如下:fun FragmentActivity.showInfoDialog(message: String?): AlertDialog? {return try {val customLayout layoutInflater.inflate(R.layout.custom_layout…

android 打开谷歌导航,国内开启google位置记录功能/android版google maps 7+上,恢复位置记录功能在国内使用(需root)...

android版google 地图在 7以后的版本上&#xff0c;位置记录功能在国内不能用了&#xff0c;提示本功能不能在中国使用。至少对本人&#xff0c;“位置记录”功能是非常有用的功能&#xff0c;尤其是骑车出行时记录自己的路线。目前还没找到替代产品。之前一段时间内恢复回旧版…

程序员过关斩将--少年派登录安全的奇幻遐想

“据说&#xff0c;这篇也是快餐&#xff0c;完全符合年轻人口味说到登录&#xff0c;无人不知无人不晓。每一个有用户体系的相关系统都会有登录的入口&#xff0c;登录是为了确认操作人的正确性。说到登录安全&#xff0c;其实是一个很伟大的命题&#xff0c;不过常用的手段也…

C# 9 新特性 —— 增强的 foreach

C# 9 新特性 —— 增强的 foreachIntro在 C# 9 中增强了 foreach 的使用&#xff0c;使得一切对象都有 foreach 的可能我们来看一段代码&#xff0c;这里我们试图遍历一个 int 类型的值思考一下&#xff0c;我们可以怎么做使得上面的代码编译通过呢&#xff1f;迭代器模式迭代器…

android系统休眠发广播,Android - BroadcastReceiver

BroadcastReceiverBroadcastReceiver&#xff0c;广播接收者&#xff0c;用来接收系统和应用的广播&#xff0c;并做出相应的处理&#xff0c;如电量过低时提示用户充电等&#xff1b;BroadcastReceiver 是 Android 的四大组件之一&#xff0c;分为 普通广播、有序广播、粘性广…

开源·共享·创新|2020年中国.NET开发者大会圆满收官!

“疫情无限续费”的2020年&#xff0c;对于14亿中国人而言&#xff0c;是必须习惯口罩长在来脸上的一年&#xff1b;是各种线下聚会&#xff0c;被迫数次延期、滞后、云上举办的一年&#xff1b;……而对于潜心修行&#xff0c;静蓄能量的中国.NET开发者而言&#xff0c;2020绝…

android+百度lbs云,百度——LBS.云 v2.0——云存储扩展字段——Android

今天要解决两个问题&#xff1a;1云存储扩展字段2上传的数据是乱码3android版本上传数据到云端使用了一段时间LBS云功能之后&#xff0c;随着对系统的熟悉&#xff0c;默认提供的字段&#xff0c;肯定无法满足需要。比如增加注释&#xff0c;价格&#xff0c;档次等字段的时候。…

年终将至,回顾我们一起走过的 2020

又到了年终末尾匆匆忙忙的 2020 似乎按下了倍速键一晃眼我们就从夏天走到了冬天在这不平凡的一年中我们同途共进也笑着成长让我们跟随着六大年度词条重温这一年我们共同经历的值得骄傲的瞬间吧&#xff01;点击文内高亮部分&#xff0c;阅读文章了解更多人才“倍”出星桥计划出…

灵魂拷问:你和大佬,技术差距有多大?

今天咱们聊点技术以外的内容。前几天&#xff0c;有程序员在某个坛子上发帖吐槽&#xff0c;新来的应届生张嘴就是分布式&#xff0c;一堆框架&#xff0c;可代码根本不会写。马上有人跟贴说自己也遇到过这种情况&#xff0c;说之前自己遇到过一个应届生&#xff0c;开口闭口动…

达梦数据查询编码_查询数据库的编码方式

在Mysql中(1)查看Mysql数据库编码show variables like character_set_database 或者 show create database 数据库名称(2)查看Mysql中某张表的编码show create table 表名show create database 数据库名称、show create table 表名 &#xff0c;还能够显示建库和建表语句。(3)…

玩转git-flow工作流-分支解析

概述搞开发的相信大部分人git天天都在用&#xff0c;那么一般我们在实际工程当中&#xff0c;遵循一个合理、清晰的Git使用流程&#xff0c;是非常重要的。否则&#xff0c;每个人都提交一堆杂乱无章的commit&#xff0c;项目很快就会变得难以协调和维护。那么是如何来规范整个…

android中的帧动画,[Android开发] Android中的帧动画

MainActivity文件&#xff1a;public class MainActivity extends Activity implements OnClickListener{AnimationDrawable anim_draw;SuppressLint("NewApi")Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);set…

ksu7对讲机调频软件_数字对讲机的群呼功能原理是什么?你了解多少?

大家都明白数字对讲机能够达到组呼、群呼、选呼的用途&#xff0c;但对数字对讲机的群呼功能原理可能操作方并不是太熟悉&#xff0c;下面我们就和大家来谈谈有关数字对讲机的群呼功能原理&#xff1a;无线对讲机群呼是为了更好地达到1个数字对讲机能够同一时间跟多个数字对讲机…

引入Jaeger——使用

上一篇定义了两种使用Jaeger的方式&#xff1a;中间件和action过滤器&#xff0c;下面这个例子定义了两个服务 WebAPI01&#xff0c;请求WebAPI02&#xff0c;采用的是中间件的请求方式。引入JaegerSharp包&#xff08;或发布到自己的Nuget库里引用&#xff09;WebAPI01的Start…