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(); } }
/// <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; } }
/// <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; } } }
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); }
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))); }
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); }
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; } } }
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; }
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); } }
/// <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); }