示例#1
0
        private static async Task <WebResponse> GetResponseAsyncInternal(WebRequest webRequest, Func <object, Task <WebResponse> > originalMethod)
        {
            if (!(webRequest is HttpWebRequest) || !IsTracingEnabled(webRequest))
            {
                return(await originalMethod(webRequest).ConfigureAwait(false));
            }

            using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, webRequest.Method, webRequest.RequestUri, IntegrationName, out var tags))
            {
                try
                {
                    if (scope != null)
                    {
                        // add distributed tracing headers to the HTTP request
                        SpanContextPropagator.Instance.Inject(scope.Span.Context, webRequest.Headers.Wrap());
                    }

                    WebResponse response = await originalMethod(webRequest).ConfigureAwait(false);

                    if (scope != null && response is HttpWebResponse webResponse)
                    {
                        tags.HttpStatusCode = HttpTags.ConvertStatusCodeToString((int)webResponse.StatusCode);
                    }

                    return(response);
                }
                catch (Exception ex)
                {
                    scope?.Span.SetException(ex);
                    throw;
                }
            }
        }
        private void OnHostingHttpRequestInStop(object arg)
        {
            var tracer = _tracer ?? Tracer.Instance;

            if (!tracer.Settings.IsIntegrationEnabled(IntegrationName))
            {
                return;
            }

            IScope scope = tracer.ActiveScope;

            if (scope != null)
            {
                var httpContext = HttpRequestInStopHttpContextFetcher.Fetch <HttpContext>(arg);

                var statusCode = HttpTags.ConvertStatusCodeToString(httpContext.Response.StatusCode);

                scope.Span.SetTag(Tags.HttpStatusCode, statusCode);

                if (httpContext.Response.StatusCode / 100 == 5)
                {
                    // 5xx codes are server-side errors
                    scope.Span.Error = true;
                }

                scope.Dispose();
            }
        }
示例#3
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <param name="traceId">The trace id - this id will be ignored if there's already an active trace</param>
        /// <param name="spanId">The span id</param>
        /// <param name="startTime">The start time that should be applied to the span</param>
        /// <param name="addToTraceContext">Set to false if the span is meant to be discarded. In that case, the span won't be added to the TraceContext.</param>
        /// <returns>A new pre-populated scope.</returns>
        internal static Span CreateInactiveOutboundHttpSpan(Tracer tracer, string httpMethod, Uri requestUri, IntegrationId integrationId, out HttpTags tags, TraceId?traceId, ulong?spanId, DateTimeOffset?startTime, bool addToTraceContext)
        {
            tags = null;

            if (!tracer.Settings.IsIntegrationEnabled(integrationId) || PlatformHelpers.PlatformStrategy.ShouldSkipClientSpan(tracer.InternalActiveScope) || HttpBypassHelper.UriContainsAnyOf(requestUri, tracer.Settings.HttpClientExcludedUrlSubstrings))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Span span = null;

            try
            {
                if (GetActiveHttpScope(tracer) != null)
                {
                    // we are already instrumenting this,
                    // don't instrument nested methods that belong to the same stacktrace
                    // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync()
                    return(null);
                }

                string resourceUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : true, tryRemoveIds : true) : null;

                string httpUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : false, tryRemoveIds : false) : null;

                tags = new HttpTags();

                // Upstream uses "http.request" for the span name but following legacy version and the
                // OpenTelemetry specification we use the capitalized method as the span name.
                string uppercaseHttpMethod = httpMethod?.ToUpperInvariant();

                string serviceName = tracer.Settings.GetServiceName(tracer, ServiceName);
                span = tracer.StartSpan(uppercaseHttpMethod, tags, serviceName: serviceName, traceId: traceId, spanId: spanId, startTime: startTime, addToTraceContext: addToTraceContext);

                span.Type         = SpanTypes.Http;
                span.ResourceName = $"{httpMethod} {resourceUrl}";
                span.LogicScope   = OperationName;

                tags.HttpMethod          = uppercaseHttpMethod;
                tags.HttpUrl             = httpUrl;
                tags.InstrumentationName = IntegrationRegistry.GetName(integrationId);

                tags.SetAnalyticsSampleRate(integrationId, tracer.Settings, enabledWithGlobalSetting: false);

                if (!addToTraceContext && span.Context.TraceContext.SamplingPriority == null)
                {
                    // If we don't add the span to the trace context, then we need to manually call the sampler
                    span.Context.TraceContext.SetSamplingPriority(tracer.TracerManager.Sampler?.GetSamplingPriority(span));
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating span.");
            }

            // always returns the span, even if it's null because we couldn't create it,
            // or we couldn't populate it completely (some tags is better than no tags)
            return(span);
        }
        internal static void SetServerStatusCode(this Span span, int statusCode)
        {
            span.SetTag(Tags.HttpStatusCode, HttpTags.ConvertStatusCodeToString(statusCode));

            // 5xx codes are server-side errors
            if (statusCode / 100 == 5)
            {
                span.Error = true;
            }
        }
示例#5
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <returns>A new pre-populated scope.</returns>
        public static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, IntegrationInfo integrationId, out HttpTags tags)
        {
            tags = null;

            if (!tracer.Settings.IsIntegrationEnabled(integrationId))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Scope scope = null;

            try
            {
                Span parent = tracer.ActiveScope?.Span;

                if (parent != null &&
                    parent.Type == SpanTypes.Http &&
                    parent.GetTag(Tags.InstrumentationName) != null)
                {
                    // we are already instrumenting this,
                    // don't instrument nested methods that belong to the same stacktrace
                    // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync()
                    return(null);
                }

                string resourceUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : true, tryRemoveIds : true) : null;

                string httpUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : false, tryRemoveIds : false) : null;

                tags = new HttpTags();

                string serviceName = tracer.Settings.GetServiceName(tracer, ServiceName);
                scope = tracer.StartActiveWithTags(OperationName, tags: tags, serviceName: serviceName);
                var span = scope.Span;

                span.Type         = SpanTypes.Http;
                span.ResourceName = $"{httpMethod} {resourceUrl}";

                tags.HttpMethod          = httpMethod?.ToUpperInvariant();
                tags.HttpUrl             = httpUrl;
                tags.InstrumentationName = IntegrationRegistry.GetName(integrationId);

                tags.SetAnalyticsSampleRate(integrationId, tracer.Settings, enabledWithGlobalSetting: false);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            // always returns the scope, even if it's null because we couldn't create it,
            // or we couldn't populate it completely (some tags is better than no tags)
            return(scope);
        }
        private static async Task <object> SendAsyncInternal(
            Func <object, object, CancellationToken, object> sendAsync,
            Type reportedType,
            HttpRequestMessageStruct requestValue,
            object handler,
            object request,
            CancellationToken cancellationToken)
        {
            var httpMethod = requestValue.Method.Method;
            var requestUri = requestValue.RequestUri;

            using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, httpMethod, requestUri, IntegrationId, out var tags))
            {
                try
                {
                    if (scope != null)
                    {
                        tags.HttpClientHandlerType = reportedType.FullName;

                        // add distributed tracing headers to the HTTP request
                        SpanContextPropagator.Instance.Inject(scope.Span.Context, new HttpHeadersCollection(requestValue.Headers));
                    }

                    var task = (Task)sendAsync(handler, request, cancellationToken);
                    await task.ConfigureAwait(false);

                    var response = task.As <TaskObjectStruct>().Result;

                    // this tag can only be set after the response is returned
                    int statusCode = response.As <HttpResponseMessageStruct>().StatusCode;

                    if (scope != null)
                    {
                        tags.HttpStatusCode = HttpTags.ConvertStatusCodeToString(statusCode);
                    }

                    return(response);
                }
                catch (Exception ex)
                {
                    scope?.Span.SetException(ex);
                    throw;
                }
            }
        }
示例#7
0
        internal static void SetServerStatusCode(this Span span, int statusCode)
        {
            string statusCodeString = HttpTags.ConvertStatusCodeToString(statusCode);

            span.SetTag(Tags.HttpStatusCode, statusCodeString);

            // 5xx codes are server-side errors
            if (statusCode / 100 == 5)
            {
                span.Error = true;

                // if an error message already exists (e.g. from a previous exception), don't replace it
                if (string.IsNullOrEmpty(span.GetTag(Tags.ErrorMsg)))
                {
                    span.SetTag(Tags.ErrorMsg, $"The HTTP response has status code {statusCodeString}.");
                }
            }
        }
        public Scope CreateScope(OutboundHttpArgs args, out HttpTags tags)
        {
            var otelTags = new OtelHttpTags();

            tags = otelTags;

            string operationName = "HTTP " + args.HttpMethod;
            string serviceName   = _tracer.Settings.GetServiceName(_tracer, "http-client");
            var    scope         = _tracer.StartActiveWithTags(operationName, tags: tags, serviceName: serviceName, spanId: args.SpanId);

            scope.Span.Type = SpanTypes.Http;

            var uri = args.RequestUri;

            otelTags.HttpMethod          = args.HttpMethod;
            otelTags.HttpUrl             = string.Concat(uri.Scheme, Uri.SchemeDelimiter, uri.Authority, uri.PathAndQuery, uri.Fragment);
            otelTags.InstrumentationName = IntegrationRegistry.GetName(args.IntegrationInfo);
            return(scope);
        }
示例#9
0
 private HttpTags GetTags(int siteId)
 {
     HttpTags _tags = null;
     if (!tags.Keys.Contains(siteId))
     {
         string dirPath = String.Concat(Cms.PyhicPath, "config/s", siteId.ToString(), "/");
         if (!Directory.Exists(dirPath))
         {
             Directory.CreateDirectory(dirPath).Create();
         }
         _tags = new HttpTags(String.Concat(dirPath, "tags.conf"));
         tags.Add(siteId, _tags);
     }
     else
     {
         _tags = tags[siteId];
     }
     return _tags;
 }
        /// <summary>
        /// OnMethodBegin callback
        /// </summary>
        /// <typeparam name="TTarget">Type of the target</typeparam>
        /// <typeparam name="TRequest">Type of the request</typeparam>
        /// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
        /// <param name="requestMessage">HttpRequest message instance</param>
        /// <param name="cancellationToken">CancellationToken value</param>
        /// <returns>Calltarget state value</returns>
        public static CallTargetState OnMethodBegin <TTarget, TRequest>(TTarget instance, TRequest requestMessage, CancellationToken cancellationToken)
            where TRequest : IHttpRequestMessage
        {
            Scope    scope = null;
            HttpTags tags  = null;

            if (IsTracingEnabled(requestMessage.Headers))
            {
                scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, requestMessage.Method.Method, requestMessage.RequestUri, IntegrationId, out tags);
                if (scope != null)
                {
                    tags.HttpClientHandlerType = instance.GetType().FullName;

                    // add distributed tracing headers to the HTTP request
                    SpanContextPropagator.Instance.Inject(scope.Span.Context, new HttpHeadersCollection(requestMessage.Headers));
                }
            }

            return(new CallTargetState(new IntegrationState(scope, tags)));
        }
示例#11
0
        public Scope CreateScope(OutboundHttpArgs args, out HttpTags tags)
        {
            tags = new DatadogHttpTags();
            var requestUri = args.RequestUri;
            var httpMethod = args.HttpMethod;

            string serviceName = _tracer.Settings.GetServiceName(_tracer, "http-client");
            var    scope       = _tracer.StartActiveWithTags("http.request", tags: tags, serviceName: serviceName, spanId: args.SpanId);

            scope.Span.Type = SpanTypes.Http;

            tags.HttpMethod = httpMethod;
            tags.HttpUrl    = UriHelpers.CleanUri(requestUri, removeScheme: false, tryRemoveIds: false);
            string resourceUrl = UriHelpers.CleanUri(requestUri, removeScheme: true, tryRemoveIds: true);

            scope.Span.ResourceName = $"{httpMethod} {resourceUrl}";

            var integrationId = args.IntegrationInfo;

            tags.InstrumentationName = IntegrationRegistry.GetName(integrationId);
            tags.SetAnalyticsSampleRate(integrationId, _tracer.Settings, enabledWithGlobalSetting: false);
            return(scope);
        }
示例#12
0
        public static object GetResponse(object webRequest, int opCode, int mdToken, long moduleVersionPtr)
        {
            if (webRequest == null)
            {
                throw new ArgumentNullException(nameof(webRequest));
            }

            const string methodName = nameof(GetResponse);

            Func <object, WebResponse> callGetResponse;

            try
            {
                var instrumentedType = webRequest.GetInstrumentedType("System.Net.WebRequest");
                callGetResponse =
                    MethodBuilder <Func <object, WebResponse> >
                    .Start(moduleVersionPtr, mdToken, opCode, methodName)
                    .WithConcreteType(instrumentedType)
                    .WithNamespaceAndNameFilters("System.Net.WebResponse")
                    .Build();
            }
            catch (Exception ex)
            {
                Log.ErrorRetrievingMethod(
                    exception: ex,
                    moduleVersionPointer: moduleVersionPtr,
                    mdToken: mdToken,
                    opCode: opCode,
                    instrumentedType: WebRequestTypeName,
                    methodName: methodName,
                    instanceType: webRequest.GetType().AssemblyQualifiedName);
                throw;
            }

            var request = (WebRequest)webRequest;

            if (!(request is HttpWebRequest) || !IsTracingEnabled(request))
            {
                return(callGetResponse(webRequest));
            }

            using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, request.Method, request.RequestUri, IntegrationName, out var tags))
            {
                try
                {
                    if (scope != null)
                    {
                        // add distributed tracing headers to the HTTP request
                        SpanContextPropagator.Instance.Inject(scope.Span.Context, request.Headers.Wrap());
                    }

                    WebResponse response = callGetResponse(webRequest);

                    if (scope != null && response is HttpWebResponse webResponse)
                    {
                        tags.HttpStatusCode = HttpTags.ConvertStatusCodeToString((int)webResponse.StatusCode);
                    }

                    return(response);
                }
                catch (Exception ex)
                {
                    scope?.Span.SetException(ex);
                    throw;
                }
            }
        }
示例#13
0
        private ArchiveDto GetFormCopyedArchive(int siteId, NameValueCollection form, ArchiveDto archive, string alias)
        {
            string content = form["Content"];

            //自动替换Tags
            if (form["autotag"] == "on")
            {
                //todo:顺序调换了下
                HttpTags _tags = this.GetTags(siteId);
                content = _tags.Tags.RemoveAutoTags(content);
                content = _tags.Tags.ReplaceSingleTag(content);
            }
            archive.Flag = 0;
            if (form["IsVisible"] == "on")
            {
                archive.Flag |= (int)BuiltInArchiveFlags.Visible;
            }
            if (form["AsPage"] == "on")
            {
                archive.Flag |= (int)BuiltInArchiveFlags.AsPage;
            }
            if (form["IsSpecial"] == "on")
            {
                archive.Flag |= (int)BuiltInArchiveFlags.IsSpecial;
            }
            if (form["IsSystem"] == "on")
            {
                archive.Flag |= (int)BuiltInArchiveFlags.IsSystem;
            }
            archive.UpdateTime = DateTime.Now;
            archive.Title      = form["Title"].Trim();
            archive.SmallTitle = form["SmallTitle"].Trim();
            archive.Location   = form["location"].Trim();
            archive.Source     = form["Source"];
            archive.Outline    = form["Outline"];
            archive.Alias      = alias;
            archive.Tags       = form["Tags"].Replace(",", ",");
            archive.Content    = content;
            archive.Thumbnail  = form["Thumbnail"];

            //分类
            int categoryId = int.Parse(form["categoryid"]);

            archive.Category = new CategoryDto {
                ID = categoryId
            };

            //检测图片是否为默认图片
            if (archive.Thumbnail == CmsVariables.FRAMEWORK_ARCHIVE_NoPhoto)
            {
                archive.Thumbnail = String.Empty;
            }

            archive.ExtendValues = new List <IExtendValue>();

            //=============== 更新扩展字段 ===================

            IExtendField field;
            string       extendValue;

            foreach (string key in form.Keys)
            {
                if (key.StartsWith("extend_"))
                {
                    extendValue = form[key];
                    field       = new ExtendField(int.Parse(key.Substring(7)), null);
                    archive.ExtendValues.Add(new ExtendValue(-1, field, extendValue));
                }
            }

            //更新模板设置
            archive.TemplatePath = form["TemplatePath"];
            if (archive.TemplatePath != String.Empty)
            {
                archive.IsSelfTemplate = true;
            }
            return(archive);
        }
 public IntegrationState(Scope scope, HttpTags tags)
 {
     Scope = scope;
     Tags  = tags;
 }
示例#15
0
 private HttpTags GetTags(int siteId)
 {
     HttpTags _tags = null;
     if (!tags.Keys.Contains(siteId))
     {
         string dirPath = String.Concat(Cms.PyhicPath, "config/s", siteId.ToString(), "/");
         if (!Directory.Exists(dirPath))
         {
             Directory.CreateDirectory(dirPath).Create();
         }
         _tags = new HttpTags(String.Concat(dirPath, "tags.conf"));
         tags.Add(siteId, _tags);
     }
     else
     {
         _tags = tags[siteId];
     }
     return _tags;
 }
示例#16
0
        private DataPackFunc GetDataPackHandler(int categoryId)
        {
            int    publisherId;
            string flag;
            bool   isAutoTag;
            bool   removeLink;
            bool   dlPic;

            publisherId = UserState.Administrator.Current.Id;

            flag = ArchiveFlag.GetFlagString(
                false,
                false,
                request.Form["visible"] == "on",
                false,
                null);

            isAutoTag  = request.Form["autotag"] == "on";
            removeLink = request.Form["removelink"] == "on";
            dlPic      = request.Form["dlpic"] == "on";
            string   domain = null;
            HttpTags _tags  = this.GetTags(siteId);

            return(data =>
            {
                string content = data["content"];
                string thumbnail = data["thumbnail"] ?? (data["image"] ?? "");
                bool thumbIsNull = String.IsNullOrEmpty(thumbnail);

                if (domain == null)
                {
                    Match m = Regex.Match(data.ReferenceUrl, "((http|https)://[^/]+)/(.+?)"
                                          , RegexOptions.IgnoreCase);
                    domain = m.Groups[1].Value;
                }

                //替换src
                content = srcRegex.Replace(content, "$1" + domain + "/");
                if (!thumbIsNull && thumbnail[0] == '/')
                {
                    thumbnail = domain + thumbnail;
                }

                //移除链接
                if (removeLink)
                {
                    content = linkRegex.Replace(content, "$1");
                }

                //远程下载
                if (dlPic)
                {
                    content = AutoUpload(content);
                    if (!thumbIsNull)
                    {
                        thumbnail = downloadThumbnail(thumbnail);
                    }
                }


                //自动替换Tags
                if (isAutoTag)
                {
                    // content = _tags.Tags.RemoveAutoTags(content);
                    content = _tags.Tags.ReplaceSingleTag(content);
                }

                this.CreateNewArchive(categoryId, content, thumbnail, publisherId, flag, data);
            });
        }
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <param name="spanId">The span ID</param>
        /// <returns>A new pre-populated scope.</returns>
        public static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, IntegrationInfo integrationId, out HttpTags tags, ulong?spanId = null)
        {
            tags = null;

            if (!tracer.Settings.IsIntegrationEnabled(integrationId))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            try
            {
                if (GetActiveHttpScope(tracer) != null)
                {
                    // we are already instrumenting this,
                    // don't instrument nested methods that belong to the same stacktrace
                    // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync()
                    return(null);
                }

                var args  = new OutboundHttpArgs(spanId, httpMethod, requestUri, integrationId);
                var scope = tracer.OutboundHttpConvention.CreateScope(args, out tags);
                return(scope);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
                return(null);
            }
        }
示例#18
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <param name="traceId">The trace id - this id will be ignored if there's already an active trace</param>
        /// <param name="spanId">The span id</param>
        /// <param name="startTime">The start time that should be applied to the span</param>
        /// <returns>A new pre-populated scope.</returns>
        internal static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, IntegrationId integrationId, out HttpTags tags, ulong?traceId = null, ulong?spanId = null, DateTimeOffset?startTime = null)
        {
            var span = CreateInactiveOutboundHttpSpan(tracer, httpMethod, requestUri, integrationId, out tags, traceId, spanId, startTime, addToTraceContext: true);

            if (span != null)
            {
                return(tracer.ActivateSpan(span));
            }

            return(null);
        }