引入Jaeger——擴展

引入Jaeger——擴展
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();
            }
        }
    }   
}

請求結果:
引入Jaeger——擴展
收集到數據後,就能夠應用到報警平臺上,若是報警平臺有api,能夠進行調用處理;還能夠把這些數據推送到時序數據庫中,如InfluxDB,再經過Grafana展現出來,進行實時展時跟蹤,關於跟蹤的細節和業務規則有關係,若是之後工做中遇到這類處理,到時再追加一篇博文進行細說。ide

相關文章
相關標籤/搜索