示例#1
0
        private void DoConfigWork(Object state)
        {
            var list = AppConfig.FindAll();
            var next = DateTime.MinValue;

            foreach (var item in list)
            {
                if (!item.Enable || item.PublishTime.Year < 2000)
                {
                    continue;
                }

                using var span = _tracer?.NewSpan("AutoPublish", item);

                // 时间到了,发布,或者计算最近一个到期应用
                if (item.PublishTime <= DateTime.Now)
                {
                    item.Publish();
                }
                else if (item.PublishTime < next || next.Year < 2000)
                {
                    next = item.PublishTime;
                }
            }

            // 如果下一个到期应用时间很短,主动调整定时器
            if (next.Year > 2000)
            {
                var ts = next - DateTime.Now;
                if (ts.TotalMilliseconds < _timer.Period)
                {
                    _timer.SetNext((Int32)ts.TotalMilliseconds);
                }
            }
        }
示例#2
0
        Span BuildSpan()
        {
            if (!ignoreActiveSpan)
            {
                var parent = tracer.ScopeManager.Current?.Span;
                if (parent != null)
                {
                    AddReference(References.ChildOf, new OTSpanContext(parent.Context));
                }
            }
            Span span = null;

            if (references != null && references.Count > 0)
            {
                if (references[0].Context is OTSpanContext parentRef)
                {
                    span = tracer.NewSpan(operationName, parentRef.TraceContext);
                }
                else
                {
                    span = tracer.NewSpan(operationName);
                }
            }
            else
            {
                span = tracer.NewSpan(operationName);
            }
            span.Kind           = GetSpanKind();
            span.RemoteEndpoint = GetRemote();
            CombineTags(span);
            return(span);
        }
示例#3
0
        /// <summary>打开</summary>
        /// <returns>是否成功</returns>
        public virtual Boolean Open()
        {
            if (Disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            if (Active)
            {
                return(true);
            }
            lock (this)
            {
                if (Active)
                {
                    return(true);
                }

                using var span = Tracer?.NewSpan($"net:{Name}:Open", Remote);
                try
                {
                    _RecvCount = 0;

                    var rs = OnOpen();
                    if (!rs)
                    {
                        return(false);
                    }

                    var timeout = Timeout;
                    if (timeout > 0)
                    {
                        Client.SendTimeout    = timeout;
                        Client.ReceiveTimeout = timeout;
                    }

                    // Tcp需要初始化管道
                    if (Local.IsTcp)
                    {
                        Pipeline?.Open(CreateContext(this));
                    }

                    Active = true;

                    ReceiveAsync();

                    // 触发打开完成的事件
                    Opened?.Invoke(this, EventArgs.Empty);
                }
                catch (Exception ex)
                {
                    span?.SetError(ex, null);
                    throw;
                }
            }

            return(true);
        }
示例#4
0
        /// <summary>调用</summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext ctx)
        {
            // APM跟踪
            //var span = Tracer?.NewSpan(ctx.Request.Path);
            ISpan span = null;

            if (Tracer != null)
            {
                var action = GetAction(ctx);
                if (!action.IsNullOrEmpty())
                {
                    span     = Tracer.NewSpan(action);
                    span.Tag = ctx.Request.GetRawUrl() + "";
                    span.Detach(ctx.Request.Headers.ToDictionary(e => e.Key, e => (Object)e.Value));
                }
            }

            try
            {
                await _next.Invoke(ctx);
            }
            catch (Exception ex)
            {
                span?.SetError(ex, null);

                throw;
            }
            finally
            {
                span?.Dispose();
            }
        }
示例#5
0
        /// <summary>调用</summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext ctx)
        {
            // APM追踪
            //var span = Tracer?.NewSpan(ctx.Request.Path);
            ISpan span = null;

            if (Tracer != null)
            {
                var action = GetAction(ctx);
                if (!action.IsNullOrEmpty())
                {
                    span = Tracer.NewSpan(action);
                    span.Detach(ctx.Request.Headers.ToDictionary(e => e.Key, e => (Object)e.Value));
                }
            }

            ManageProvider.UserHost = ctx.GetUserHost();
            try
            {
                await _next.Invoke(ctx);
            }
            catch (Exception ex)
            {
                span?.SetError(ex, ctx.Request.QueryString + "");

                throw;
            }
            finally
            {
                ManageProvider.UserHost = null;
                span?.Dispose();
            }
        }
示例#6
0
        void OnInit(Object sender, EventArgs e)
        {
            var app = sender as HttpApplication;
            var ctx = app?.Context;

            if (ctx != null && Tracer != null)
            {
#if NET45_OR_GREATER
                if (ctx.IsWebSocketRequest)
                {
                    return;
                }
#endif
                var action = GetAction(ctx);
                if (!action.IsNullOrEmpty())
                {
                    var span = Tracer.NewSpan(action);
                    ctx.Items["__span"] = span;

                    // 聚合请求头作为强制采样的数据标签
                    var req = ctx.Request;
                    var vs  = new Dictionary <String, String>(StringComparer.OrdinalIgnoreCase);
                    foreach (var item in req.Headers.AllKeys)
                    {
                        vs[item] = req.Headers[item];
                    }
                    span.Tag = $"{req.UserHostAddress} {req.HttpMethod} {req.RawUrl}";
                    if (span is DefaultSpan ds && ds.TraceFlag > 0)
                    {
                        span.Tag += Environment.NewLine + vs.Join(Environment.NewLine, e => $"{e.Key}:{e.Value}");
                    }
                    span.Detach(vs);
                }
            }
        }
        /// <summary>队列消费大循环,处理消息后自动确认</summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="queue">队列</param>
        /// <param name="onMessage">消息处理。如果处理消息时抛出异常,消息将延迟后回到队列</param>
        /// <param name="onException">异常处理</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <param name="tracer">性能跟踪</param>
        /// <returns></returns>
        public static async Task RunLoopAsync <T>(this IProducerConsumer <String> queue, Func <T, Task> onMessage, Action <Exception> onException = null, CancellationToken cancellationToken = default, ITracer tracer = null)
        {
            // 主题
            var topic = (queue as RedisBase).Key;

            if (topic.IsNullOrEmpty())
            {
                topic = queue.GetType().Name;
            }

            // 超时时间,用于阻塞等待
            var timeout = 2;

            if (queue is RedisBase rb && rb.Redis != null)
            {
                timeout = rb.Redis.Timeout / 1000 - 1;
            }

            while (!cancellationToken.IsCancellationRequested)
            {
                ISpan span = null;
                try
                {
                    // 异步阻塞消费
                    var msg = await queue.TakeOneAsync(timeout);

                    if (msg != null)
                    {
                        // 反序列化消息
                        var message = msg.ToJsonEntity <T>();
                        span = tracer?.NewSpan($"mq:{topic}", msg);

                        // 处理消息
                        await onMessage(message);

                        // 确认消息
                        queue.Acknowledge(msg);
                    }
                    else
                    {
                        // 没有消息,歇一会
                        await TaskEx.Delay(1000);
                    }
                }
                catch (ThreadAbortException) { break; }
                catch (ThreadInterruptedException) { break; }
                catch (Exception ex)
                {
                    span?.SetError(ex, null);

                    onException?.Invoke(ex);
                }
                finally
                {
                    span?.Dispose();
                }
            }
        }
示例#8
0
        /// <summary>读取线圈,0x01</summary>
        /// <param name="host">主机。一般是1</param>
        /// <param name="address">地址。例如0x0002</param>
        /// <param name="count">线圈个数</param>
        /// <returns></returns>
        public Byte[] ReadCoil(Byte host, UInt16 address, UInt16 count)
        {
            using var span = Tracer?.NewSpan("modbus:ReadCoil", $"{host} {address:X4} {count:X4}");

            var rs = SendCommand(host, FunctionCodes.ReadCoil, address, count);

            if (rs == null || rs.Length <= 0)
            {
                return(null);
            }

            return(rs);
        }
示例#9
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);
                }
            }
        }
示例#10
0
        void OnInit(Object sender, EventArgs e)
        {
            var app = sender as HttpApplication;
            var ctx = app?.Context;

            if (ctx != null && Tracer != null)
            {
                var action = GetAction(ctx);
                if (!action.IsNullOrEmpty())
                {
                    var span = Tracer.NewSpan(action);
                    ctx.Items["__span"] = span;
                }
            }
        }
示例#11
0
        /// <summary>为Http请求创建Span</summary>
        /// <param name="tracer">跟踪器</param>
        /// <param name="request">Http请求</param>
        /// <returns></returns>
        public static ISpan NewSpan(this ITracer tracer, HttpRequestMessage request)
        {
            if (tracer == null)
            {
                return(null);
            }

            var uri  = request.RequestUri;
            var span = tracer.NewSpan(uri.ToString().TrimEnd(uri.Query));

            span.Tag = uri.PathAndQuery;
            //span.Tag = request.Headers.UserAgent + "";
            span.Attach(request);

            return(span);
        }
示例#12
0
文件: ITracer.cs 项目: zanpy/X
        /// <summary>为Http请求创建Span</summary>
        /// <param name="tracer">跟踪器</param>
        /// <param name="request">Http请求</param>
        /// <returns></returns>
        public static ISpan NewSpan(this ITracer tracer, WebRequest request)
        {
            if (tracer == null)
            {
                return(null);
            }

            var url  = request.RequestUri.ToString();
            var p1   = url.IndexOf('?');
            var p2   = url.IndexOf('/', "https://".Length);
            var span = tracer.NewSpan(p1 < 0 ? url : url.Substring(0, p1));

            span.Tag = p2 < 0 ? url : url.Substring(p2);
            span.Attach(request);

            return(span);
        }
示例#13
0
文件: ApiHelper.cs 项目: xiaoyaoju/X
        /// <summary>异步调用,等待返回结果</summary>
        /// <param name="client">Http客户端</param>
        /// <param name="method">请求方法</param>
        /// <param name="action">服务操作</param>
        /// <param name="args">参数</param>
        /// <param name="onRequest">请求头回调</param>
        /// <param name="dataName">数据字段名称,默认data。同一套rpc体系不同接口的code/message一致,但data可能不同</param>
        /// <returns></returns>
        public static async Task <TResult> InvokeAsync <TResult>(this HttpClient client, HttpMethod method, String action, Object args = null, Action <HttpRequestMessage> onRequest = null, String dataName = "data")
        {
            //if (client?.BaseAddress == null) throw new ArgumentNullException(nameof(client.BaseAddress));

            var returnType = typeof(TResult);

            // 构建请求
            var request = BuildRequest(method, action, args);

            // 指定返回类型
            if (returnType == typeof(Byte[]) || returnType == typeof(Packet))
            {
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
            }
            else
            {
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            }

            // 可能附加头部
            onRequest?.Invoke(request);

            // 开始跟踪,注入TraceId
            var span = action.IsNullOrEmpty() ? null : Tracer?.NewSpan(action.EnsureStart("/"));

            span.Attach(request);
            try
            {
                // 发起请求
                var msg = await client.SendAsync(request);

                return(await ProcessResponse <TResult>(msg, dataName));
            }
            catch (Exception ex)
            {
                // 跟踪异常
                span?.SetError(ex, args);

                throw;
            }
            finally
            {
                span?.Dispose();
            }
        }
示例#14
0
        private ProxyBase CreateProxy(ProxyItem item, Boolean debug)
        {
            var xs   = ProxyHelper.GetAll();
            var type = xs.FirstOrDefault(e => item.Provider.EqualIgnoreCase(e.Name, e.FullName, e.Name.TrimEnd("Proxy")));

            if (type == null)
            {
                return(null);
            }

            if (type.CreateInstance() is not ProxyBase proxy)
            {
                return(null);
            }

            using var span = _tracer?.NewSpan("CreateProxy", item);

            proxy.Name   = item.Name;
            proxy.Tracer = _tracer;

            XTrace.WriteLine("创建代理 {0}", item.ToJson());

            proxy.Init(item.Config);

            // 配置本地、远程参数。高级参数直接修改这里,解析item.Value
            proxy.Local = new NetUri(item.Local);
            if (proxy is NATProxy nat && !item.Remote.IsNullOrEmpty())
            {
                nat.RemoteServer = new NetUri(item.Remote);
            }

            // 配置日志
            proxy.Log = XTrace.Log;
            if (debug)
            {
                proxy.SessionLog = XTrace.Log;
            }

            // 启动服务
            proxy.Start();

            return(proxy);
        }
示例#15
0
        /// <summary>调用</summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext ctx)
        {
            // APM跟踪
            //var span = Tracer?.NewSpan(ctx.Request.Path);
            ISpan span = null;

            if (Tracer != null)
            {
                var action = GetAction(ctx);
                if (!action.IsNullOrEmpty())
                {
                    span     = Tracer.NewSpan(action);
                    span.Tag = ctx.GetUserHost() + " " + ctx.Request.GetRawUrl();
                    span.Detach(ctx.Request.Headers.ToDictionary(e => e.Key, e => (Object)e.Value));
                }
            }

            try
            {
                await _next.Invoke(ctx);

                // 根据状态码识别异常
                if (span != null)
                {
                    var code = ctx.Response.StatusCode;
                    if (code >= 400)
                    {
                        span.SetError(new HttpRequestException($"Http Error {code} {(HttpStatusCode)code}"), null);
                    }
                }
            }
            catch (Exception ex)
            {
                span?.SetError(ex, null);

                throw;
            }
            finally
            {
                span?.Dispose();
            }
        }