Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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,
            });
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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];
Ejemplo n.º 7
0
        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);
                }
            }
        }
Ejemplo n.º 8
0
        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;
            }
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        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);
        }
Ejemplo n.º 14
0
        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);
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        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();
                }
            }
        }