Performance category information for an individual set of counters.
Exemplo n.º 1
0
        /// <summary>
        /// Adds or updates a performance counter categories information.
        /// </summary>
        /// <param name="categoryName">Name of the category.</param>
        /// <param name="typeReference">The type reference.</param>
        /// <param name="assembly">The assembly.</param>
        /// <param name="categoryHelp">The category help.</param>
        public static void Set(
            [NotNull] string categoryName,
            [NotNull] TypeReference typeReference,
            [NotNull] string assembly,
            string categoryHelp)
        {
            if (categoryName == null)
            {
                throw new ArgumentNullException("categoryName");
            }
            if (typeReference == null)
            {
                throw new ArgumentNullException("typeReference");
            }
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }
            try
            {
                PerformanceType performanceType = PerformanceType.Get(typeReference);
                PerfCategory    category        = _categories.GetOrAdd(
                    categoryName,
                    // ReSharper disable once AssignNullToNotNullAttribute
                    n => new PerfCategory(assembly, performanceType, n));
                Debug.Assert(category != null);

                // Type cannot change.
                if (category.PerformanceType != performanceType)
                {
                    Logger.Add(
                        Level.Error,
                        "The '{0}' performance counter category was declared more than once with different types ('{1}' and '{2}') in assembly '{3}'.",
                        categoryName,
                        category.PerformanceType,
                        performanceType,
                        assembly);
                    return;
                }

                // Only update category help if not already set.
                if (!string.IsNullOrWhiteSpace(categoryHelp) &&
                    string.IsNullOrWhiteSpace(category.CategoryHelp))
                {
                    category.CategoryHelp = categoryHelp;
                }

                // Add assembly if not seen before
                if (!category._assemblies.Contains(assembly))
                {
                    category._assemblies.Add(assembly);
                }
            }
            catch (Exception e)
            {
                Logger.Add(
                    Level.Error,
                    "Failed to set performance category information for category '{0}' in assembly '{1}'. {2}",
                    categoryName,
                    assembly,
                    e.Message);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Loads the specified assembly and checks for performance counter use.
        /// </summary>
        /// <param name="assemblyPath">The assembly path.</param>
        private static void Load(string assemblyPath)
        {
            AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, ReaderParameters);

            Debug.Assert(assembly != null);
            Debug.Assert(assembly.Name != null);
            if (assembly.Name.Name == "WebApplications.Utilities.Performance")
            {
                return;
            }

            // Find any modules that reference logging.
            // ReSharper disable once AssignNullToNotNullAttribute
            ModuleDefinition[] referencingModules = assembly.Modules
                                                    .Where(
                // ReSharper disable PossibleNullReferenceException, AssignNullToNotNullAttribute
                m => m.AssemblyReferences
                .FirstOrDefault(
                    ar => ar.Name == "WebApplications.Utilities.Performance") !=
                null)
                                                    // ReSharper restore PossibleNullReferenceException, AssignNullToNotNullAttribute
                                                    .ToArray();

            if (referencingModules.Length < 1)
            {
                return;
            }

            Queue <string> lastStrings = new Queue <string>(2);

            foreach (ModuleDefinition module in referencingModules)
            {
                Debug.Assert(module != null);
                Debug.Assert(module.Types != null);
                foreach (TypeDefinition type in module.Types)
                {
                    Debug.Assert(type != null);
                    Debug.Assert(type.Methods != null);
                    foreach (MethodDefinition method in type.Methods)
                    {
                        Debug.Assert(method != null);

                        if (!method.HasBody)
                        {
                            continue;
                        }

                        lastStrings.Clear();

                        Debug.Assert(method.Body != null);
                        Debug.Assert(method.Body.Instructions != null);
                        foreach (Instruction instr in method.Body.Instructions)
                        {
                            Debug.Assert(instr != null);

                            // Detect string literals loaded onto evaluation stack
                            if (instr.OpCode.Code == Code.Ldstr)
                            {
                                // We track last two load strings.
                                if (lastStrings.Count > 1)
                                {
                                    lastStrings.Dequeue();
                                }

                                lastStrings.Enqueue(instr.Operand as string);
                                continue;
                            }

                            // Detect nulls being loaded onto evaluation stack
                            if (instr.OpCode.Code == Code.Ldnull)
                            {
                                // We track last two load strings.
                                if (lastStrings.Count > 1)
                                {
                                    lastStrings.Dequeue();
                                }

                                lastStrings.Enqueue(null);
                                continue;
                            }

                            if (instr.OpCode.Code != Code.Call)
                            {
                                // If we have any ops other than NewObj after our loads then the loads aren't for us.
                                lastStrings.Clear();
                                continue;
                            }

                            // Make sure we have the right method signature.
                            GenericInstanceMethod methodReference = instr.Operand as GenericInstanceMethod;
                            if ((methodReference == null) ||
                                (methodReference.Name != "GetOrAdd") ||
                                !methodReference.HasGenericArguments ||
                                !methodReference.IsGenericInstance ||
                                // ReSharper disable PossibleNullReferenceException
                                (methodReference.GenericArguments.Count != 1) ||
                                (methodReference.Parameters.Count != 2) ||
                                (methodReference.Parameters[0].ParameterType.FullName != "System.String") ||
                                (methodReference.Parameters[1].ParameterType.FullName != "System.String"))
                            {
                                // ReSharper restore PossibleNullReferenceException
                                continue;
                            }

                            // Make sure it's on the right type.
                            TypeReference typeReference = methodReference.DeclaringType;
                            if ((typeReference == null) ||
                                (typeReference.FullName !=
                                 "WebApplications.Utilities.Performance.PerfCategory"))
                            {
                                continue;
                            }

                            TypeReference perfCategoryType = methodReference.GenericArguments.First();
                            Debug.Assert(perfCategoryType != null);

                            if (lastStrings.Count > 1)
                            {
                                int  pCount  = methodReference.Parameters.Count();
                                bool isTimer = pCount == 4;
                                Debug.Assert(isTimer || (pCount == 2));
                                string categoryName = lastStrings.Dequeue();
                                string categoryHelp = lastStrings.Dequeue();

                                // We have a constructor set performance information.
                                if (!String.IsNullOrWhiteSpace(categoryName))
                                {
                                    Logger.Add(
                                        Level.Low,
                                        "The '{0}' assembly calls PerfCategory.GetOrAdd<{1}>(\"{2}\", {3}).",
                                        assemblyPath,
                                        perfCategoryType.Name,
                                        categoryName,
                                        categoryHelp == null ? "null" : "\"" + categoryHelp + "\"");

                                    PerfCategory.Set(
                                        categoryName,
                                        perfCategoryType,
                                        // ReSharper disable once AssignNullToNotNullAttribute
                                        assembly.Name.Name,
                                        categoryHelp);
                                }
                                else
                                {
                                    Logger.Add(
                                        Level.Error,
                                        "Performance counter creation found in '{0}' but category name was null or empty - make sure you use inline strings as constructor parameters.  Press any key to continue",
                                        assemblyPath);
                                }
                            }
                            else
                            {
                                Logger.Add(
                                    Level.Error,
                                    "Performance counter creation found in '{0}' but could not find category name and or category help - make sure you use inline strings as constructor parameters.  Press any key to continue",
                                    assemblyPath);
                            }
                            lastStrings.Clear();
                        }
                    }
                }
            }
        }