Beispiel #1
0
        internal static TelemetryItem GetTelemetryItem(Activity activity, ref TagEnumerationState monitorTags, Resource resource, string instrumentationKey)
        {
            TelemetryItem telemetryItem = new TelemetryItem(PartA_Name_Mapping[activity.GetTelemetryType()], FormatUtcTimestamp(activity.StartTimeUtc))
            {
                InstrumentationKey = instrumentationKey
            };

            InitRoleInfo(resource);

            if (activity.ParentSpanId != default)
            {
                telemetryItem.Tags[ContextTagKeys.AiOperationParentId.ToString()] = activity.ParentSpanId.ToHexString();
            }

            telemetryItem.Tags[ContextTagKeys.AiCloudRole.ToString()]         = RoleName;
            telemetryItem.Tags[ContextTagKeys.AiCloudRoleInstance.ToString()] = RoleInstance;
            telemetryItem.Tags[ContextTagKeys.AiOperationId.ToString()]       = activity.TraceId.ToHexString();
            // todo: update swagger to include this key.
            telemetryItem.Tags["ai.user.userAgent"] = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeHttpUserAgent)?.ToString();

            // we only have mapping for server spans
            // todo: non-server spans
            if (activity.Kind == ActivityKind.Server)
            {
                telemetryItem.Tags[ContextTagKeys.AiOperationName.ToString()] = GetOperationName(activity, ref monitorTags.PartBTags);
                telemetryItem.Tags[ContextTagKeys.AiLocationIp.ToString()]    = GetLocationIp(ref monitorTags.PartBTags);
            }

            telemetryItem.Tags[ContextTagKeys.AiInternalSdkVersion.ToString()] = SdkVersionUtils.SdkVersion;

            return(telemetryItem);
        }
        internal static RequestData GetRequestData(Activity activity)
        {
            string url          = null;
            string urlAuthority = null;
            var    monitorTags  = EnumerateActivityTags(activity);

            switch (monitorTags.activityType)
            {
            case PartBType.Http:
                monitorTags.PartBTags.GenerateUrlAndAuthority(out url, out urlAuthority);
                break;

            case PartBType.Messaging:
                url = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeMessagingUrl)?.ToString();
                break;
            }

            var statusCode = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeHttpStatusCode)?.ToString() ?? "0";
            var success    = activity.GetStatus() != Status.Error;
            var request    = new RequestData(2, activity.Context.SpanId.ToHexString(), activity.Duration.ToString("c", CultureInfo.InvariantCulture), success, statusCode)
            {
                Name   = activity.DisplayName,
                Url    = url,
                Source = urlAuthority
            };

            AddPropertiesToTelemetry(request.Properties, ref monitorTags.PartCTags);

            return(request);
        }
        internal static RequestData GetRequestData(Activity activity, ref TagEnumerationState monitorTags)
        {
            string url = null;

            AddActivityLinksToPartCTags(activity.Links, ref monitorTags.PartCTags);

            switch (monitorTags.activityType)
            {
            case PartBType.Http:
                url = monitorTags.PartBTags.GetRequestUrl();
                break;

            case PartBType.Messaging:
                url = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeMessagingUrl)?.ToString();
                break;
            }

            var requestName = TelemetryPartA.GetOperationName(activity, ref monitorTags.PartBTags);
            var statusCode  = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeHttpStatusCode)?.ToString() ?? "0";
            var success     = activity.GetStatus().StatusCode != StatusCode.Error;
            var request     = new RequestData(2, activity.Context.SpanId.ToHexString(), activity.Duration.ToString("c", CultureInfo.InvariantCulture), success, statusCode)
            {
                Name = requestName,
                Url  = url,
            };

            AddPropertiesToTelemetry(request.Properties, ref monitorTags.PartCTags);

            return(request);
        }
Beispiel #4
0
        ///<summary>
        /// Gets http request url from activity tag objects.
        ///</summary>
        internal static string GetRequestUrl(this AzMonList tagObjects)
        {
            // From spec: one of the following combinations is required in case of server spans:
            // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server-semantic-conventions
            // http.url
            // http.scheme, http.host, http.target
            // http.scheme, http.server_name, net.host.port, http.target
            // http.scheme, net.host.name, net.host.port, http.target
            string url = null;

            url = tagObjects.GetUrlUsingHttpUrl();
            if (url != null)
            {
                return(url);
            }

            var httpScheme = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpScheme)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpScheme))
            {
                var httpTarget = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpTarget)?.ToString();
                // http.target is required in other three possible combinations
                // If not available then do not proceed.
                if (string.IsNullOrWhiteSpace(httpTarget))
                {
                    return(null);
                }

                string defaultPort = GetDefaultHttpPort(httpScheme);
                url = tagObjects.GetUrlUsingHttpHost(httpScheme, defaultPort, httpTarget);
                if (url != null)
                {
                    return(url);
                }

                var    httpServerName = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpServerName)?.ToString();
                string host;
                if (!string.IsNullOrWhiteSpace(httpServerName))
                {
                    host = httpServerName;
                }
                else
                {
                    host = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetHostName)?.ToString();
                }
                if (!string.IsNullOrWhiteSpace(host))
                {
                    var netHostPort = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetHostPort)?.ToString();
                    if (!string.IsNullOrWhiteSpace(netHostPort))
                    {
                        url = tagObjects.GetUrlUsingHostAndPort(httpScheme, host, netHostPort, defaultPort, httpTarget);
                        return(url);
                    }
                }
            }

            return(url);
        }
Beispiel #5
0
        private static string GetLocationIp(ref AzMonList partBTags)
        {
            var httpClientIp = AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeHttpClientIP)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpClientIp))
            {
                return(httpClientIp);
            }

            return(AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeNetPeerIp)?.ToString());
        }
Beispiel #6
0
        internal static string GetOperationName(Activity activity, ref AzMonList partBTags)
        {
            var httpMethod = AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeHttpMethod)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpMethod))
            {
                return($"{httpMethod} {activity.DisplayName}");
            }

            return(activity.DisplayName);
        }
Beispiel #7
0
        internal static string GetUrlUsingHttpUrl(this AzMonList tagObjects)
        {
            string url     = null;
            var    httpUrl = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpUrl)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpUrl))
            {
                url = httpUrl;
            }

            return(url);
        }
        internal static RemoteDependencyData GetRemoteDependencyData(Activity activity, ref TagEnumerationState monitorTags)
        {
            AddActivityLinksToPartCTags(activity.Links, ref monitorTags.PartCTags);

            var dependency = new RemoteDependencyData(2, activity.DisplayName, activity.Duration.ToString("c", CultureInfo.InvariantCulture))
            {
                Id      = activity.Context.SpanId.ToHexString(),
                Success = activity.GetStatus().StatusCode != StatusCode.Error
            };

            switch (monitorTags.activityType)
            {
            case PartBType.Http:
                dependency.Data       = monitorTags.PartBTags.GetDependencyUrl();
                dependency.Target     = monitorTags.PartBTags.GetDependencyTarget(PartBType.Http);
                dependency.Type       = "Http";
                dependency.ResultCode = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeHttpStatusCode)?.ToString() ?? "0";
                break;

            case PartBType.Db:
                var depDataAndType = AzMonList.GetTagValues(ref monitorTags.PartBTags, SemanticConventions.AttributeDbStatement, SemanticConventions.AttributeDbSystem);
                dependency.Data   = depDataAndType[0]?.ToString();
                dependency.Target = monitorTags.PartBTags.GetDbDependencyTarget();
                dependency.Type   = SqlDbs.Contains(depDataAndType[1]?.ToString()) ? "SQL" : depDataAndType[1]?.ToString();
                break;

            case PartBType.Rpc:
                var depInfo = AzMonList.GetTagValues(ref monitorTags.PartBTags, SemanticConventions.AttributeRpcService, SemanticConventions.AttributeRpcSystem, SemanticConventions.AttributeRpcStatus);
                dependency.Data       = depInfo[0]?.ToString();
                dependency.Type       = depInfo[1]?.ToString();
                dependency.ResultCode = depInfo[2]?.ToString();
                break;

            case PartBType.Messaging:
                depDataAndType  = AzMonList.GetTagValues(ref monitorTags.PartBTags, SemanticConventions.AttributeMessagingUrl, SemanticConventions.AttributeMessagingSystem);
                dependency.Data = depDataAndType[0]?.ToString();
                dependency.Type = depDataAndType[1]?.ToString();
                break;
            }

            if (activity.Kind == ActivityKind.Internal && activity.Parent != null)
            {
                dependency.Type = "InProc";
            }

            AddPropertiesToTelemetry(dependency.Properties, ref monitorTags.PartCTags);

            return(dependency);
        }
Beispiel #9
0
        internal static string GetHostUsingNetPeerAttributes(this AzMonList tagObjects)
        {
            var    netPeerName = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetPeerName)?.ToString();
            string host;

            if (!string.IsNullOrWhiteSpace(netPeerName))
            {
                host = netPeerName;
            }
            else
            {
                host = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetPeerIp)?.ToString();
            }

            return(host);
        }
        internal static RemoteDependencyData GetRemoteDependencyData(Activity activity)
        {
            var monitorTags = EnumerateActivityTags(activity);

            var dependency = new RemoteDependencyData(2, activity.DisplayName, activity.Duration.ToString("c", CultureInfo.InvariantCulture))
            {
                Id      = activity.Context.SpanId.ToHexString(),
                Success = activity.GetStatus() != Status.Error
            };

            switch (monitorTags.activityType)
            {
            case PartBType.Http:
                monitorTags.PartBTags.GenerateUrlAndAuthority(out var url, out var urlAuthority);
                dependency.Data       = url;
                dependency.Target     = urlAuthority;
                dependency.Type       = "Http";
                dependency.ResultCode = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeHttpStatusCode)?.ToString() ?? "0";
                break;

            case PartBType.Db:
                var depDataAndType = AzMonList.GetTagValues(ref monitorTags.PartBTags, SemanticConventions.AttributeDbStatement, SemanticConventions.AttributeDbSystem);
                dependency.Data = depDataAndType[0]?.ToString();
                dependency.Type = depDataAndType[1]?.ToString();
                break;

            case PartBType.Rpc:
                var depInfo = AzMonList.GetTagValues(ref monitorTags.PartBTags, SemanticConventions.AttributeRpcService, SemanticConventions.AttributeRpcSystem, SemanticConventions.AttributeRpcStatus);
                dependency.Data       = depInfo[0]?.ToString();
                dependency.Type       = depInfo[1]?.ToString();
                dependency.ResultCode = depInfo[2]?.ToString();
                break;

            case PartBType.Messaging:
                depDataAndType  = AzMonList.GetTagValues(ref monitorTags.PartBTags, SemanticConventions.AttributeMessagingUrl, SemanticConventions.AttributeMessagingSystem);
                dependency.Data = depDataAndType[0]?.ToString();
                dependency.Type = depDataAndType[1]?.ToString();
                break;
            }

            AddPropertiesToTelemetry(dependency.Properties, ref monitorTags.PartCTags);

            return(dependency);
        }
        internal static string GetHttpDependencyName(this AzMonList tagObjects, string httpUrl)
        {
            if (string.IsNullOrWhiteSpace(httpUrl))
            {
                return(null);
            }

            var httpMethod = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpMethod)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpMethod))
            {
                if (Uri.TryCreate(httpUrl.ToString(), UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri)
                {
                    return($"{httpMethod} {uri.AbsolutePath}");
                }
            }

            return(null);
        }
Beispiel #12
0
        internal static string GetUrlUsingHttpHost(this AzMonList tagObjects, string httpScheme, string defaultPort, string httpTarget)
        {
            string url      = null;
            var    httpHost = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpHost)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpHost))
            {
                string portSection = $":{defaultPort}";
                if (httpHost.EndsWith(portSection, StringComparison.OrdinalIgnoreCase))
                {
                    var truncatedHost = httpHost.Substring(0, httpHost.IndexOf(portSection, StringComparison.OrdinalIgnoreCase));
                    url = $"{httpScheme}://{truncatedHost}{httpTarget}";
                }
                else
                {
                    url = $"{httpScheme}://{httpHost}{httpTarget}";
                }
            }

            return(url);
        }
Beispiel #13
0
        internal static string GetOperationName(Activity activity, ref AzMonList partBTags)
        {
            var httpMethod = AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeHttpMethod)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpMethod))
            {
                var httpRoute = AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeHttpRoute)?.ToString();
                // ASP.NET instrumentation assigns route as {controller}/{action}/{id} which would result in the same name for different operations.
                // To work around that we will use path from httpUrl.
                if (!string.IsNullOrWhiteSpace(httpRoute) && !httpRoute.Contains("{controller}"))
                {
                    return($"{httpMethod} {httpRoute}");
                }
                var httpUrl = AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeHttpUrl)?.ToString();
                if (!string.IsNullOrWhiteSpace(httpUrl) && Uri.TryCreate(httpUrl.ToString(), UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri)
                {
                    return($"{httpMethod} {uri.AbsolutePath}");
                }
            }

            return(activity.DisplayName);
        }
Beispiel #14
0
        ///<summary>
        /// Gets Database dependency target from activity tag objects.
        ///</summary>
        internal static string GetDbDependencyTarget(this AzMonList tagObjects)
        {
            string target        = tagObjects.GetDependencyTarget(PartBType.Db);
            string dbName        = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeDbName)?.ToString();
            bool   isTargetEmpty = string.IsNullOrEmpty(target);
            bool   isDbNameEmpty = string.IsNullOrEmpty(dbName);

            if (!isTargetEmpty && !isDbNameEmpty)
            {
                target = $"{target}/{dbName}";
            }
            else if (isTargetEmpty && !isDbNameEmpty)
            {
                target = dbName;
            }
            else if (isTargetEmpty && isDbNameEmpty)
            {
                target = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeDbSystem)?.ToString();
            }

            return(target);
        }
Beispiel #15
0
        ///<summary>
        /// Gets Http dependency target from activity tag objects.
        ///</summary>
        internal static string GetDependencyTarget(this AzMonList tagObjects, PartBType type)
        {
            string target;
            string defaultPort;

            switch (type)
            {
            case PartBType.Http:
                defaultPort = GetDefaultHttpPort(AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpScheme)?.ToString());
                break;

            case PartBType.Db:
                defaultPort = GetDefaultDbPort(AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeDbSystem)?.ToString());
                break;

            default:
                defaultPort = "0";
                break;
            }

            var peerService = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributePeerService)?.ToString();

            if (!string.IsNullOrEmpty(peerService))
            {
                target = peerService;
                return(target);
            }

            if (type == PartBType.Http)
            {
                var httpHost = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpHost)?.ToString();
                if (!string.IsNullOrEmpty(httpHost))
                {
                    string portSection = $":{defaultPort}";
                    if (httpHost.EndsWith(portSection, StringComparison.OrdinalIgnoreCase))
                    {
                        var truncatedHost = httpHost.Substring(0, httpHost.IndexOf(portSection, StringComparison.OrdinalIgnoreCase));
                        target = truncatedHost;
                    }
                    else
                    {
                        target = httpHost;
                    }
                    return(target);
                }
                var httpUrl = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpUrl)?.ToString();
                if (!string.IsNullOrEmpty(httpUrl) && Uri.TryCreate(httpUrl.ToString(), UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri)
                {
                    target = uri.Authority;
                    if (!string.IsNullOrEmpty(target))
                    {
                        return(target);
                    }
                }
            }

            target = tagObjects.GetHostUsingNetPeerAttributes();
            if (!string.IsNullOrEmpty(target))
            {
                var netPeerPort = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetPeerPort)?.ToString();
                if (!string.IsNullOrEmpty(netPeerPort) && netPeerPort != defaultPort)
                {
                    target = $"{target}:{netPeerPort}";
                }
                return(target);
            }

            return(target);
        }
        /// <summary>
        /// This method follows OpenTelemetry specification to retrieve http URL.
        /// Reference: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#http-client.
        /// </summary>
        /// <param name="tagObjects">Activity Tags</param>
        /// <param name="url">URL</param>
        /// <param name="urlAuthority">Host name or IP address and the port number </param>
        internal static void GenerateUrlAndAuthority(this AzMonList tagObjects, out string url, out string urlAuthority)
        {
            urlAuthority = null;
            url          = null;

            var httpurl = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpUrl);

            if (httpurl != null && Uri.TryCreate(httpurl.ToString(), UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri)
            {
                url          = uri.AbsoluteUri;
                urlAuthority = uri.Authority;
                return;
            }

            var httpScheme = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpScheme)?.ToString();

            if (!string.IsNullOrWhiteSpace(httpScheme))
            {
                var httpHost = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpHost)?.ToString();

                if (!string.IsNullOrWhiteSpace(httpHost))
                {
                    var httpPortAndTarget = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributeHttpHostPort, SemanticConventions.AttributeHttpTarget);

                    if (httpPortAndTarget[0] != null && httpPortAndTarget[0].ToString() != "80" && httpPortAndTarget[0].ToString() != "443")
                    {
                        var IsColon = (string.IsNullOrWhiteSpace(httpPortAndTarget[0].ToString()) ? null : Colon);
                        url          = $"{httpScheme}://{httpHost}{IsColon}{httpPortAndTarget[0]}{httpPortAndTarget[1]}";
                        urlAuthority = $"{httpHost}{IsColon}{httpPortAndTarget[0]}";
                    }
                    else
                    {
                        url          = $"{httpScheme}://{httpHost}{httpPortAndTarget[1]}";
                        urlAuthority = $"{httpHost}";
                    }

                    return;
                }

                var netPeerName = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetPeerName)?.ToString();

                if (!string.IsNullOrWhiteSpace(netPeerName))
                {
                    var netPeerPortAndTarget = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributeNetPeerPort, SemanticConventions.AttributeHttpTarget);
                    var IsColon = (string.IsNullOrWhiteSpace(netPeerPortAndTarget[0]?.ToString()) ? null : Colon);
                    url          = $"{httpScheme}{SchemePostfix}{netPeerName}{IsColon}{netPeerPortAndTarget[0]}{netPeerPortAndTarget[1]}";
                    urlAuthority = $"{netPeerName}{IsColon}{netPeerPortAndTarget[0]}";
                    return;
                }

                var netPeerIP = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetPeerIp)?.ToString();

                if (!string.IsNullOrWhiteSpace(netPeerIP))
                {
                    var netPeerPortAndTarget = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributeNetPeerPort, SemanticConventions.AttributeHttpTarget);
                    var IsColon = (string.IsNullOrWhiteSpace(netPeerPortAndTarget[0]?.ToString()) ? null : Colon);
                    url          = $"{httpScheme}{SchemePostfix}{netPeerIP}{IsColon}{netPeerPortAndTarget[0]}{netPeerPortAndTarget[1]}";
                    urlAuthority = $"{netPeerIP}{IsColon}{netPeerPortAndTarget[0]}";
                    return;
                }
            }

            var host = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeHttpHost)?.ToString();

            if (!string.IsNullOrWhiteSpace(host))
            {
                var httpPortAndTarget = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributeHttpHostPort, SemanticConventions.AttributeHttpTarget);
                var IsColon           = (string.IsNullOrWhiteSpace(httpPortAndTarget[0]?.ToString()) ? null : Colon);
                url          = $"{host}{IsColon}{httpPortAndTarget[0]}{httpPortAndTarget[1]}";
                urlAuthority = $"{host}{IsColon}{httpPortAndTarget[0]}";
                return;
            }

            url = string.IsNullOrWhiteSpace(url) ? null : url;
        }