void DoWork(Object state) { var set = Setting.Current; if (set.DataRetention <= 0) { return; } // 保留数据的起点 var time = DateTime.Now.AddDays(-set.DataRetention); // 删除节点数据 var rs = NodeData.DeleteBefore(time); XTrace.WriteLine("删除[{0}]之前的NodeData共:{1:n0}", time.ToFullString(), rs); // 删除应用性能数据 rs = AppMeter.DeleteBefore(time); XTrace.WriteLine("删除[{0}]之前的AppMeter共:{1:n0}", time.ToFullString(), rs); // 删除监控明细数据 rs = TraceData.DeleteBefore(time); XTrace.WriteLine("删除[{0}]之前的TraceData共:{1:n0}", time.ToFullString(), rs); rs = SampleData.DeleteBefore(time); XTrace.WriteLine("删除[{0}]之前的SampleData共:{1:n0}", time.ToFullString(), rs); // 删除跟踪分钟统计数据 rs = TraceMinuteStat.DeleteBefore(time); XTrace.WriteLine("删除[{0}]之前的TraceMinuteStat共:{1:n0}", time.ToFullString(), rs); }
public TraceMinuteStat GetOrAdd(DateTime date, Int32 appId, String name, out String key) { var model = new TraceStatModel { Time = date, AppId = appId, Name = name }; key = model.Key; return(GetOrAdd(key, k => TraceMinuteStat.FindOrAdd(model))); }
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 ProcessDay(Int32 appId, DateTime time) { if (appId <= 0 || time.Year < 2000) { return; } var date = time.Date; // 统计数据 var list = TraceMinuteStat.FindAllByAppIdWithCache(appId, date); if (list.Count == 0) { return; } // 聚合 // 分组聚合,这里包含了每个接口在该日内的所有分钟统计,需要求和 foreach (var item in list.GroupBy(e => e.Name)) { var name = item.Key; if (name.IsNullOrEmpty()) { continue; } var st = _dayQueue.GetOrAdd(date, appId, name, out var key); var vs = item.ToList(); st.Total = vs.Sum(e => e.Total); st.Errors = vs.Sum(e => e.Errors); st.TotalCost = vs.Sum(e => e.TotalCost); st.MaxCost = vs.Max(e => e.MaxCost); var vs2 = vs.Where(e => e.MinCost > 0).ToList(); if (vs2.Count > 0) { st.MinCost = vs2.Min(e => e.MinCost); } // 强制触发种类计算 st.Valid(false); _dayQueue.Commit(key); } }
private void ProcessHour(Int32 appId, DateTime time) { if (appId <= 0 || time.Year < 2000) { return; } time = time.Date.AddHours(time.Hour); // 统计数据 var list = TraceMinuteStat.FindAllByAppIdWithCache(appId, time.Date); list = list.Where(e => e.StatTime >= time & e.StatTime < time.AddHours(1)).ToList(); if (list.Count == 0) { return; } // 分组聚合,这里包含了每个接口在该小时内的所有分钟统计,需要求和 foreach (var item in list.GroupBy(e => e.Name)) { var name = item.Key; if (name.IsNullOrEmpty()) { continue; } var st = _hourQueue.GetOrAdd(time, appId, name, out var key); var vs = item.ToList(); st.Total = vs.Sum(e => e.Total); st.Errors = vs.Sum(e => e.Errors); st.TotalCost = vs.Sum(e => e.TotalCost); st.MaxCost = vs.Max(e => e.MaxCost); var vs2 = vs.Where(e => e.MinCost > 0).ToList(); if (vs2.Count > 0) { st.MinCost = vs2.Min(e => e.MinCost); } _hourQueue.Commit(key); } }