private void ProcessData(AppTracer app, String ip, ISpanBuilder[] builders) { //var traces = new List<TraceData>(); var samples = new List <SampleData>(); foreach (var item in builders) { var td = TraceData.Create(item); td.AppId = app.ID; td.ClientId = ip; td.CreateIP = ip; td.CreateTime = DateTime.Now; td.Insert(); //traces.Add(td); samples.AddRange(SampleData.Create(td, item.Samples)); samples.AddRange(SampleData.Create(td, item.ErrorSamples)); //if (samples.Count > 0) samples.Insert(true); } //traces.Insert(true); samples.Insert(true); }
public ActionResult Index(String id, Pager pager) { if (id.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(id)); } var list = Search(id, pager); if (list.Count > 0) { var appId = list[0].AppId; var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}调用链"; } } var model = new TraceViewModel { Page = pager, Data = list }; return(View("Index", model)); }
protected override IEnumerable <AppDayStat> Search(Pager p) { var appId = p["appId"].ToInt(-1); var start = p["dtStart"].ToDateTime(); var end = p["dtEnd"].ToDateTime(); // 默认排序 if (appId >= 0 && start.Year < 2000 && p.Sort.IsNullOrEmpty()) { start = DateTime.Today.AddDays(-30); p["dtStart"] = start.ToString("yyyy-MM-dd"); p.Sort = __.StatDate; p.Desc = false; p.PageSize = 100; } p.RetrieveState = true; var list = AppDayStat.Search(appId, start, end, p["Q"], p); if (list.Count > 0) { // 绘制日期曲线图 var ar = AppTracer.FindByID(appId); if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("调用次数"); chart.AddLine(list, _.Total, null, true); chart.Add(list, _.Errors); chart.SetTooltip(); ViewBag.Charts = new[] { chart }; } if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("耗时"); chart.AddLine(list, _.Cost, null, true); chart.Add(list, _.MaxCost); chart.Add(list, _.MinCost); chart.SetTooltip(); ViewBag.Charts2 = new[] { chart }; } } return(list); }
public TraceResponse Report([FromBody] MyTraceModel model) { var builders = model?.Builders.Cast <ISpanBuilder>().ToArray(); //var builders = new ISpanBuilder[0]; if (model == null || model.AppId.IsNullOrEmpty() || builders == null || builders.Length == 0) { return(null); } // 校验应用 var app = AppTracer.FindByName(model.AppId); if (app == null) { app = new AppTracer { Name = model.AppId, DisplayName = model.AppName, Enable = Setting.Current.AutoRegister, }; app.Save(); } if (!app.Enable) { throw new Exception($"无效应用[{model.AppId}/{model.AppName}]"); } // 插入数据 var ip = HttpContext.GetUserHost(); if (ip.IsNullOrEmpty()) { ip = ManageProvider.UserHost; } Task.Run(() => ProcessData(app, ip, builders)); _stat.Add(app.ID); _appStat.Add(app.ID); // 构造响应 return(new TraceResponse { Period = app.Period, MaxSamples = app.MaxSamples, MaxErrors = app.MaxErrors, }); }
protected override IEnumerable <TraceDayStat> Search(Pager p) { var appId = p["appId"].ToInt(-1); var name = p["name"]; var start = p["dtStart"].ToDateTime(); var end = p["dtEnd"].ToDateTime(); // 默认排序 if (appId >= 0 && start.Year < 2000 && p.Sort.IsNullOrEmpty()) { start = DateTime.Today.AddDays(-30); p["dtStart"] = start.ToString("yyyy-MM-dd"); p.Sort = TraceDayStat.__.StatDate; p.Desc = false; p.PageSize = 100; } var list = TraceDayStat.Search(appId, name, start, end, p["Q"], p); if (list.Count > 0) { var hasDate = start.Year > 2000 || end.Year > 2000; // 绘制日期曲线图 var ar = AppTracer.FindByID(appId); if (appId >= 0) { var chart = new ECharts { Title = new ChartTitle { Text = ar + "" }, Height = 400, }; chart.SetX(list, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("数量"); chart.AddLine(list, _.Total, null, true); chart.Add(list, _.Total); chart.Add(list, _.Errors); chart.Add(list, _.Cost); chart.SetTooltip(); ViewBag.Charts = new[] { chart }; } } return(list); }
private static String GetMarkdown(AppTracer app, AppMinuteStat st, Boolean includeTitle) { var sb = new StringBuilder(); if (includeTitle) { sb.AppendLine($"### [{app}]系统告警"); } sb.AppendLine($">**总数:**<font color=\"red\">{st.Errors}</font>"); var url = Setting.Current.WebUrl; var appUrl = ""; var traceUrl = ""; if (!url.IsNullOrEmpty()) { appUrl = url.EnsureEnd("/") + "Monitors/appMinuteStat?appId=" + st.AppId + "&minError=1"; traceUrl = url.EnsureEnd("/") + "Monitors/traceMinuteStat?appId=" + st.AppId + "&minError=1"; } // 找找具体接口错误 var names = new List <String>(); var sts = TraceMinuteStat.FindAllByAppIdAndTime(st.AppId, st.StatTime).OrderByDescending(e => e.Errors).ToList(); foreach (var item in sts) { if (item.Errors > 0) { sb.AppendLine($">**错误:**<font color=\"red\">{item.StatTime.ToFullString()} 埋点[{item.Name}]共报错[{item.Errors:n0}]次</font>[更多]({traceUrl}&name={HttpUtility.UrlEncode(item.Name)})"); // 相同接口的错误,不要报多次 if (!names.Contains(item.Name)) { var ds = TraceData.Search(st.AppId, item.Name, "minute", item.StatTime, 20); if (ds.Count > 0) { var sms = SampleData.FindAllByDataIds(ds.Select(e => e.Id).ToArray(), item.StatTime).Where(e => !e.Error.IsNullOrEmpty()).ToList(); if (sms.Count > 0) { var msg = sms[0].Error?.Trim(); if (!msg.IsNullOrEmpty()) { // 错误内容取第一行,详情看更多 var p = msg.IndexOfAny(new[] { '\r', '\n' }); if (p > 0) { msg = msg[..p];
private void ProcessAppTracer(AppTracer app) { // 应用是否需要告警 if (app == null || !app.Enable || app.AlarmThreshold <= 0) { return; } var appId = app.ID; if (!RobotHelper.CanAlarm(app.Category, app.AlarmRobot)) { return; } using var span = _tracer?.NewSpan($"Alarm:{nameof(AppTracer)}"); // 最近一段时间的5分钟级数据 var time = DateTime.Now; var minute = time.Date.AddHours(time.Hour).AddMinutes(time.Minute / 5 * 5); var st = AppMinuteStat.FindByAppIdAndTime(appId, minute); if (st == null) { return; } // 判断告警 if (st.Errors >= app.AlarmThreshold) { // 一定时间内不要重复报错,除非错误翻倍 var error2 = _cache.Get <Int32>("alarm:AppTracer:" + appId); if (error2 == 0 || st.Errors > error2 * 2) { _cache.Set("alarm:AppTracer:" + appId, st.Errors, 5 * 60); var msg = GetMarkdown(app, st, true); RobotHelper.SendAlarm(app.Category, app.AlarmRobot, "系统告警", msg); } } }
private void DoAlarm(Object state) { while (_bag.TryTake(out var appId)) { //Process(appId); } // 应用告警 var list = AppTracer.FindAllWithCache(); foreach (var item in list) { ProcessAppTracer(item); } // 节点告警 var nodes = Node.FindAllWithCache(); foreach (var item in nodes) { ProcessNode(item); } // Redis告警 var rnodes = RedisNode.FindAllWithCache(); foreach (var item in rnodes) { ProcessRedisNode(item); } if (Period > 0) { _timer.Period = Period * 1000; } }
protected override IEnumerable <TraceDayStat> Search(Pager p) { var appId = p["appId"].ToInt(-1); var name = p["name"]; var type = p["type"]; var start = p["dtStart"].ToDateTime(); var end = p["dtEnd"].ToDateTime(); var date = p["date"].ToDateTime(); if (start.Year < 2000 && end.Year < 2000) { start = end = date; } // 选了应用,没有选时间,按照统计日期升序 if (appId >= 0 && start.Year < 2000 && p.Sort.IsNullOrEmpty()) { p.Sort = __.StatDate; p.Desc = true; p.PageSize = 90; } // 选了应用和时间,按照接口调用次数降序 else if (appId >= 0 && start.Year > 2000 && p.Sort.IsNullOrEmpty()) { p.Sort = __.Total; p.Desc = true; p.PageSize = 100; } p.RetrieveState = true; var list = TraceDayStat.Search(appId, name, type, start, end, p["Q"], p); if (list.Count > 0 && appId >= 0 && !name.IsNullOrEmpty()) { var list2 = list.OrderBy(e => e.StatDate).ToList(); // 绘制日期曲线图 if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list2, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("调用次数"); chart.AddLine(list2, _.Total, null, true); chart.Add(list2, _.Errors); chart.SetTooltip(); ViewBag.Charts = new[] { chart }; } if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list2, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("耗时"); chart.AddLine(list2, _.Cost, null, true); chart.Add(list2, _.MaxCost); chart.Add(list2, _.MinCost); chart.SetTooltip(); ViewBag.Charts2 = new[] { chart }; } } var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}每日统计"; } return(list); }
protected override IEnumerable <SampleData> Search(Pager p) { var dataId = p["dataId"].ToLong(-1); var appId = p["appId"].ToInt(-1); var name = p["name"] + ""; var traceId = p["traceId"]; var spanId = p["spanId"]; var parentId = p["parentId"]; var success = p["success"]?.ToBoolean(); //var start = p["dtStart"].ToDateTime(); //var end = p["dtEnd"].ToDateTime(); var start = p["start"].ToLong(-1); var end = p["end"].ToLong(-1); // 指定跟踪标识后,分页500 if (!traceId.IsNullOrEmpty()) { if (p.PageSize == 20) { p.PageSize = 500; } } if (p.Sort.IsNullOrEmpty()) { p.OrderBy = SampleData._.Id.Desc(); } var list = SampleData.Search(dataId, appId, name, traceId, spanId, parentId, success, start, end, p["Q"], p); if (list.Count == 0) { return(list); } // 如果有traceId,则按照要求排序,深度搜索算法 if (!traceId.IsNullOrEmpty() && list.Count > 0) { var rs = new List <SampleData>(); var stack = new Stack <SampleData>(); // 有些数据有pid,但是pid对应的span实际不存在 var pids = list.Where(e => !e.ParentId.IsNullOrEmpty()).OrderByDescending(e => e.StartTime).Select(e => e.ParentId).Distinct().ToArray(); foreach (var item in pids.Where(e => !list.Any(y => y.SpanId == e))) { foreach (var elm in list.Where(e => e.ParentId == item)) { stack.Push(elm); } } foreach (var item in stack) { list.Remove(item); } var pid = ""; while (true) { // 降序入栈 var ps = list.Where(e => e.ParentId + "" == pid).OrderByDescending(e => e.StartTime).ToList(); foreach (var item in ps) { stack.Push(item); list.Remove(item); } // 没有数据,跳出 if (stack.Count == 0) { break; } // 出栈,加入结果,处理它的下级 if (stack.TryPop(out var sd)) { rs.Add(sd); pid = sd.SpanId; } } // 残留的异常数据 rs.AddRange(list); //return rs; list = rs; } if (appId <= 0 && list.Count > 0) { appId = list[0].AppId; } var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}采样"; } return(list); }
public TraceResponse Report([FromBody] TraceModel model, String token) { var builders = model?.Builders; if (model == null || model.AppId.IsNullOrEmpty()) { return(null); } var ip = HttpContext.GetUserHost(); if (ip.IsNullOrEmpty()) { ip = ManageProvider.UserHost; } var set = Setting.Current; // 新版验证方式,访问令牌 App ap = null; if (!token.IsNullOrEmpty() && token.Split(".").Length == 3) { ap = _service.DecodeToken(token, set); //if (ap == null || ap.Name != model.AppId) throw new InvalidOperationException($"授权不匹配[{model.AppId}]!=[{ap?.Name}]!"); if (ap == null) { throw new InvalidOperationException($"授权不匹配[{model.AppId}]!=[{ap?.Name}]!"); } } App.UpdateInfo(model, ip); var clientId = model.ClientId; if (clientId.IsNullOrEmpty()) { var(jwt, ex) = _service.DecodeToken(token, set.TokenSecret); clientId = jwt?.Id; } AppOnline.UpdateOnline(ap, clientId, ip, token, model.Info); // 该应用的追踪配置信息 var app = AppTracer.FindByName(model.AppId); if (app == null) { app = new AppTracer { Name = model.AppId, DisplayName = model.AppName, Enable = set.AutoRegister, }; app.Save(); } // 校验应用 if (app == null || !app.Enable) { throw new Exception($"无效应用[{model.AppId}/{model.AppName}]"); } // 插入数据 if (builders != null && builders.Length > 0) { Task.Run(() => ProcessData(app, model, ip, builders)); } // 构造响应 var rs = new TraceResponse { Period = app.Period, MaxSamples = app.MaxSamples, MaxErrors = app.MaxErrors, Timeout = app.Timeout, //Excludes = app.Excludes?.Split(",", ";"), }; // Vip客户端。高频次大样本采样,10秒100次,逗号分割,支持*模糊匹配 if (app.IsVip(model.ClientId)) { rs.Period = 10; rs.MaxSamples = 100; } // 新版本才返回Excludes,老版本客户端在处理Excludes时有BUG,错误处理/ if (!model.Version.IsNullOrEmpty()) { rs.Excludes = app.Excludes?.Split(",", ";"); } return(rs); }
protected override IEnumerable <AppMinuteStat> Search(Pager p) { var appId = p["appId"].ToInt(-1); var minError = p["minError"].ToInt(-1); var start = p["dtStart"].ToDateTime(); var end = p["dtEnd"].ToDateTime(); // 选了应用,没有选时间,按照统计日期升序 if (appId >= 0 && start.Year < 2000 && p.Sort.IsNullOrEmpty()) { p.Sort = __.StatTime; p.Desc = true; p.PageSize = 2 * 60 / 5; } // 选了应用和时间,按照接口调用次数降序 else if (appId >= 0 && start.Year > 2000 && p.Sort.IsNullOrEmpty()) { p.Sort = __.Total; p.Desc = true; p.PageSize = 24 * 60 / 5; } // 监控视图,没有选应用 else if (appId < 0 && p["t"] == "dash") { // 最近一段时间,5~10分钟 if (start.Year < 2000) { var time = DateTime.Now; var minute = time.Date.AddHours(time.Hour).AddMinutes(time.Minute / 5 * 5); start = minute.AddMinutes(-5); } p.OrderBy = $"{__.Errors} desc, {__.Total} desc"; p.PageSize = 20; PageSetting.EnableNavbar = false; PageSetting.EnableAdd = false; PageSetting.EnableKey = false; PageSetting.EnableSelect = false; } p.RetrieveState = true; var list = AppMinuteStat.Search(appId, minError, start, end, p["Q"], p); if (list.Count > 0 && appId >= 0) { var list2 = list.OrderBy(e => e.StatTime).ToList(); // 绘制日期曲线图 if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list2, _.StatTime, e => e.StatTime.ToString("HH:mm")); chart.SetY("调用次数"); chart.AddLine(list2, _.Total, null, true); chart.Add(list2, _.Errors); chart.SetTooltip(); ViewBag.Charts = new[] { chart }; } if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list2, _.StatTime, e => e.StatTime.ToString("HH:mm")); chart.SetY("耗时"); chart.AddLine(list2, _.Cost, null, true); chart.Add(list2, _.MaxCost); chart.Add(list2, _.MinCost); chart.SetTooltip(); ViewBag.Charts2 = new[] { chart }; } } else if (list.Count > 0 && appId < 0 && p["t"] == "dash") { var list2 = new List <AppMinuteStat>(); foreach (var item in list) { var st = list2.FirstOrDefault(e => e.AppId == item.AppId); if (st == null) { list2.Add(st = new AppMinuteStat { AppId = item.AppId }); } st.Total += item.Total; st.Errors += item.Errors; } list2 = list2.OrderBy(e => e.Errors).ThenBy(e => e.Total).ToList(); // 绘制柱状图 var chart = new ECharts { Height = 800, }; chart.SetTooltip("axis", "shadow"); chart.Legend = new { data = new[] { "总数", "错误数" } }; chart["grid"] = new { left = "3%", right = "4%", bottom = "3%", containLabel = true }; chart.XAxis = new[] { new { type = "value" } }; chart.YAxis = new[] { new { type = "category", axisTick = new { show = false }, data = list2.Select(e => e.AppName).ToArray() } }; //chart.Add(list2, _.Total, "bar"); //chart.Add(list2, _.Errors, "bar"); chart.Add(new Series { Name = "错误数", Type = "bar", ["stack"] = "总量", ["label"] = new { show = true, position = "left" }, Data = list2.Select(e => - e.Errors).ToArray(), }); chart.Add(new Series { Name = "总数", Type = "bar", ["stack"] = "总量", ["label"] = new { show = true }, Data = list2.Select(e => e.Total).ToArray(), }); ViewBag.Charts = new[] { chart }; } var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}分钟统计"; } return(list); }
protected override IEnumerable <AppDayStat> Search(Pager p) { var appId = p["appId"].ToInt(-1); var start = p["dtStart"].ToDateTime(); var end = p["dtEnd"].ToDateTime(); // 默认排序 if (appId >= 0 && start.Year < 2000 && p.Sort.IsNullOrEmpty()) { p.Sort = __.StatDate; p.Desc = true; p.PageSize = 100; } p.RetrieveState = true; var list = AppDayStat.Search(appId, start, end, p["Q"], p); if (list.Count > 0 && appId > 0) { var list2 = list.OrderBy(e => e.StatDate).ToList(); // 绘制日期曲线图 if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list2, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("调用次数"); chart.AddLine(list2, _.Total, null, true); chart.Add(list2, _.Errors); chart.Add(list2, _.Apis); chart.Add(list2, _.Https); chart.Add(list2, _.Dbs); chart.Add(list2, _.Mqs); chart.Add(list2, _.Redis); chart.Add(list2, _.Others); chart.SetTooltip(); ViewBag.Charts = new[] { chart }; } if (appId >= 0) { var chart = new ECharts { Height = 400, }; chart.SetX(list2, _.StatDate, e => e.StatDate.ToString("MM-dd")); chart.SetY("耗时"); chart.AddLine(list2, _.Cost, null, true); chart.Add(list2, _.MaxCost); chart.Add(list2, _.MinCost); chart.SetTooltip(); ViewBag.Charts2 = new[] { chart }; } } var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}每日统计"; } return(list); }
protected override IEnumerable <TraceData> Search(Pager p) { var appId = p["appId"].ToInt(-1); var name = p["name"]; var start = p["dtStart"].ToDateTime(); var end = p["dtEnd"].ToDateTime(); var kind = p["kind"]; var date = p["date"].ToDateTime(); if (start.Year < 2000 && end.Year < 2000) { start = end = date; } var time = p["time"].ToDateTime(); if (start.Year < 2000 && end.Year < 2000) { start = end = time; } if (appId > 0 && p.PageSize == 20) { p.PageSize = 100; } if (p.Sort.IsNullOrEmpty()) { p.OrderBy = _.Id.Desc(); } var list = TraceData.Search(appId, name, kind, start, end, p["Q"], p); if (list.Count > 0 && appId > 0 && !name.IsNullOrEmpty()) { var list2 = list.OrderBy(e => e.Id).ToList(); // 绘制日期曲线图 var app = AppTracer.FindByID(appId); if (appId >= 0) { var chart = new ECharts { Title = new ChartTitle { Text = "调用次数" }, Height = 400, }; chart.SetX(list2, _.StartTime, e => e.StartTime.ToDateTime().ToLocalTime().ToString("HH:mm:ss")); chart.SetY("次数"); chart.AddLine(list2, _.Total, null, true); chart.Add(list2, _.Errors); chart.SetTooltip(); ViewBag.Charts = new[] { chart }; } if (appId >= 0) { var chart = new ECharts { Title = new ChartTitle { Text = "耗时" }, Height = 400, }; chart.SetX(list2, _.StartTime, e => e.StartTime.ToDateTime().ToLocalTime().ToString("HH:mm:ss")); chart.SetY("耗时"); chart.AddLine(list2, _.Cost, null, true); chart.Add(list2, _.MaxCost); chart.Add(list2, _.MinCost); chart.SetTooltip(); ViewBag.Charts2 = new[] { chart }; } } var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}跟踪"; } return(list); }
protected override IEnumerable <SampleData> Search(Pager p) { var dataId = p["dataId"].ToLong(-1); var traceId = p["traceId"]; // 指定跟踪标识后,分页500 if (!traceId.IsNullOrEmpty()) { if (p.PageSize == 20) { p.PageSize = 500; } if (p.Sort.IsNullOrEmpty()) { p.OrderBy = SampleData._.StartTime.Asc(); } } else { if (p.Sort.IsNullOrEmpty()) { p.OrderBy = SampleData._.Id.Desc(); } } var list = SampleData.Search(dataId, traceId, p); if (list.Count == 0) { // 如果是查看调用链,去备份表查一下 if (!traceId.IsNullOrEmpty()) { var list2 = SampleData2.Search(traceId, null, p); if (list2.Count > 0) { foreach (var item in list2) { var entity = new SampleData(); entity.CopyFrom(item); list.Add(entity); } } } if (list.Count == 0) { return(list); } } else { if (!traceId.IsNullOrEmpty() && list.Count < p.PageSize) { var user = ManageProvider.User; // 备份调用链,用于将来查询 SampleData2.Backup(traceId, list, user?.ID ?? 0, user + ""); } } // 如果有traceId,则按照要求排序,深度搜索算法 if (!traceId.IsNullOrEmpty() && list.Count > 0) { var rs = new List <SampleData>(); var stack = new Stack <SampleData>(); // 有些数据有pid,但是pid对应的span实际不存在 var pids = list.Where(e => !e.ParentId.IsNullOrEmpty()).OrderByDescending(e => e.StartTime).Select(e => e.ParentId).Distinct().ToArray(); foreach (var item in pids.Where(e => !list.Any(y => y.SpanId == e))) { foreach (var elm in list.Where(e => e.ParentId == item)) { stack.Push(elm); } } foreach (var item in stack) { list.Remove(item); } var pid = ""; while (true) { // 降序入栈 var ps = list.Where(e => e.ParentId + "" == pid).OrderByDescending(e => e.StartTime).ToList(); foreach (var item in ps) { stack.Push(item); list.Remove(item); } // 没有数据,跳出 if (stack.Count == 0) { break; } // 出栈,加入结果,处理它的下级 if (stack.TryPop(out var sd)) { rs.Add(sd); pid = sd.SpanId; } } // 残留的异常数据 rs.AddRange(list); //return rs; list = rs; } if (list.Count > 0) { var appId = list[0].AppId; var ar = AppTracer.FindByID(appId); if (ar != null) { ViewBag.Title = $"{ar}采样"; } } return(list); }
public TraceResponse Report([FromBody] TraceModel model, String token) { var builders = model?.Builders.Cast <ISpanBuilder>().ToArray(); //var builders = new ISpanBuilder[0]; if (model == null || model.AppId.IsNullOrEmpty() || builders == null || builders.Length == 0) { return(null); } var ip = HttpContext.GetUserHost(); if (ip.IsNullOrEmpty()) { ip = ManageProvider.UserHost; } var set = Setting.Current; // 新版验证方式,访问令牌 Data.App ap = null; if (!token.IsNullOrEmpty() && token.Split(".").Length == 3) { ap = _service.DecodeToken(token, set); if (ap == null || ap.Name != model.AppId) { throw new InvalidOperationException($"授权不匹配[{model.AppId}]!=[{ap.Name}]!"); } } Data.App.UpdateInfo(model, ip); // 该应用的跟踪配置信息 var app = AppTracer.FindByName(model.AppId); if (app == null) { app = new AppTracer { Name = model.AppId, DisplayName = model.AppName, Enable = set.AutoRegister, }; app.Save(); } // 校验应用 if (app == null || !app.Enable) { throw new Exception($"无效应用[{model.AppId}/{model.AppName}]"); } // 插入数据 Task.Run(() => ProcessData(app, model, ip, builders)); // 构造响应 var rs = new TraceResponse { Period = app.Period, MaxSamples = app.MaxSamples, MaxErrors = app.MaxErrors, Timeout = app.Timeout, //Excludes = app.Excludes?.Split(",", ";"), }; // 新版本才返回Excludes,老版本客户端在处理Excludes时有BUG,错误处理/ if (!model.Version.IsNullOrEmpty()) { rs.Excludes = app.Excludes?.Split(",", ";"); } return(rs); }
private void ProcessData(AppTracer app, TraceModel model, String ip, ISpanBuilder[] builders) { // 排除项 var excludes = app.Excludes.Split(",", ";") ?? new String[0]; var now = DateTime.Now; var traces = new List <TraceData>(); var samples = new List <SampleData>(); foreach (var item in builders) { // 剔除指定项 if (item.Name.IsNullOrEmpty()) { continue; } if (excludes != null && excludes.Any(e => e.IsMatch(item.Name))) { continue; } if (item.Name.EndsWithIgnoreCase("/Trace/Report")) { continue; } // 拒收超长项 if (item.Name.Length > TraceData._.Name.Length) { continue; } var td = TraceData.Create(item); td.AppId = app.ID; td.ClientId = model.ClientId ?? ip; td.CreateIP = ip; td.CreateTime = now; traces.Add(td); samples.AddRange(SampleData.Create(td, item.Samples, true)); samples.AddRange(SampleData.Create(td, item.ErrorSamples, false)); } traces.Insert(true); samples.Insert(true); // 更新统计 _stat.Add(traces); _appStat.Add(now.Date); if (now.Hour == 0 && now.Minute <= 10) { _appStat.Add(now.Date.AddDays(-1)); } if (!ip.IsNullOrEmpty() && ip.Length >= 3) { // 应用节点数 var nodes = app.Nodes?.Split(",").ToList() ?? new List <String>(); if (!nodes.Contains(ip)) { // 如果超过一定时间没有更新,则刷新它 if (_cache.Add("appNodes:" + app.ID, 1, 3600)) { nodes.Clear(); } nodes.Insert(0, ip); if (nodes.Count > 32) { nodes = nodes.Take(32).ToList(); } // 排序,避免Nodes字段频繁更新 app.Nodes = nodes.OrderBy(e => e).Join(); app.SaveAsync(); } } }