Jaeger是收集全鏈路跟蹤的信息,在Jaeger收集的信息中,有請求的url信息,有每一個請求的時間間隔,藉助這些信息能夠進行報警,好比一次較長的請求,或者是某些請求的次數和前後等。無論報警的業務規則是什麼,首先得收集Jaeger中的信息。
Jaeger有api能夠提供這些信息,好比數據庫
/api/services,獲取全部服務
/api/traces?service={servicename}獲取該服務下的全部跟蹤
/api/traces/{traceid}獲取某個跟蹤的信息等
/api/traces?end={endtime}&limit={20}&lookback={1h}&service={servicename}&start={starttime}按條件查詢跟蹤信息等apijson
下面代碼定義Jaeger中的實體類,類中的屬性能夠根據本身的型業務規則收集,這裏定義不完整api
using System.Collections.Generic; namespace JaegerAlert { /// <summary> /// 服務報警 /// </summary> public class AlertList { public string ServiceName { get; set; } public List<AlertItem> Alerts { get; set; } } /// <summary> /// 報警條目 /// </summary> public class AlertItem { public string TraceID { get; set; } public long StartTime { get; set; } public long Duration { get; set; } public string Method { get; set; } public string Operation { get; set; } } /// <summary> /// 服務數據 /// </summary> public class ServicesData { public string[] Data { get; set; } public int Total { get; set; } public int Limit { get; set; } public int Offset { get; set; } } /// <summary> /// 跟蹤數據 /// </summary> public class TracesData { public TracesItem[] Data { get; set; } public int Total { get; set; } public int Limit { get; set; } public int Offset { get; set; } } /// <summary> /// 跟蹤條目 /// </summary> public class TracesItem { public string TraceID { get; set; } public Span[] Spans { get; set; } } /// <summary> /// Span /// </summary> public class Span { public string TraceID { get; set; } public string SpanID { get; set; } public bool IsAlertMark => TraceID == SpanID; public int Flags { get; set; } public string OperationName { get; set; } public long StartTime { get; set; } public long Duration { get; set; } public Tag[] Tags { get; set; } } /// <summary> /// Tag /// </summary> public class Tag { public string Key { get; set; } public string Type { get; set; } public string Value { get; set; } } }
這裏簡單進行了收集,轉換成了本身的數據集合,方便對接本身的報警平臺:async
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace JaegerAlert.Controllers { [ApiController] [Route("[controller]")] public class HomeController : ControllerBase { private readonly IHttpClientFactory _clientFactory; private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger, IHttpClientFactory clientFactory) { _clientFactory = clientFactory; _logger = logger; } [HttpGet] public async Task<IEnumerable<AlertList>> Get() { _logger.LogInformation("獲取警報列表"); return await GetServices(); } /// <summary> /// 獲取全部服務 /// </summary> /// <returns></returns> async Task<IEnumerable<AlertList>> GetServices() { var service = await GetJaegerServices(); var services = new List<AlertList>(); foreach (var serviceName in service.Data) { if (serviceName == "jaeger-query") { continue; } var alerts = new List<AlertItem>(); var tracesModels = await GetJaegerTraces(serviceName); foreach (var traces in tracesModels.Data) { foreach (var span in traces.Spans) { if (span.IsAlertMark) { var method = span.Tags.SingleOrDefault(s => s.Key == "http.method")?.Value; var operation = span.Tags.SingleOrDefault(s => s.Key == "http.url")?.Value; alerts.Add(new AlertItem { TraceID = traces.TraceID, Duration = span.Duration, Method = method, Operation = operation, StartTime = span.StartTime }); } } } services.Add(new AlertList() { ServiceName = serviceName, Alerts = alerts }); } return services; } /// <summary> /// 獲取服務下的跟蹤條目 /// </summary> /// <param name="serviceName"></param> /// <returns></returns> async Task<TracesData> GetJaegerTraces(string serviceName) { using var client = _clientFactory.CreateClient("Jaeger"); var request = new HttpRequestMessage(HttpMethod.Get, $"/api/traces?service={serviceName}"); using var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var jsonString = await response.Content.ReadAsStringAsync(); var traces = Newtonsoft.Json.JsonConvert.DeserializeObject<TracesData>(jsonString); return traces; } else { return new TracesData(); } } /// <summary> /// 獲取服務 /// </summary> /// <returns></returns> async Task<ServicesData> GetJaegerServices() { using var client = _clientFactory.CreateClient("Jaeger"); var request = new HttpRequestMessage(HttpMethod.Get, "/api/services"); using var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var jsonString = await response.Content.ReadAsStringAsync(); var service = Newtonsoft.Json.JsonConvert.DeserializeObject<ServicesData>(jsonString); return service; } else { return new ServicesData(); } } } }
請求結果:
收集到數據後,就能夠應用到報警平臺上,若是報警平臺有api,能夠進行調用處理;還能夠把這些數據推送到時序數據庫中,如InfluxDB,再經過Grafana展現出來,進行實時展時跟蹤,關於跟蹤的細節和業務規則有關係,若是之後工做中遇到這類處理,到時再追加一篇博文進行細說。ide