Click here to Skip to main content
15,883,959 members
Articles / DevOps / Load Testing

Measuring and Monitoring WCF Web Service Performance

Rate me:
Please Sign up or sign in to vote.
5.00/5 (17 votes)
4 Oct 2012GPL310 min read 55.3K   2.2K   47  
Using ServiceMon to obtain performance statistics for web services
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Framework;
using Kaleida.ServiceMonitor.Model.StructuredSource;

namespace Kaleida.ServiceMonitor.Model.Runtime
{
    public class DirectiveProcessor
    {
        private readonly CompiledScript script;
        private readonly IList<Type> directiveTypes;
        private readonly IList<Assembly> searchAssemblies;

        public DirectiveProcessor([NotNull] CompiledScript script)
        {
            if (script == null) throw new ArgumentNullException("script");
            this.script = script;

            searchAssemblies = new[]{Assembly.GetExecutingAssembly()};
            directiveTypes = GetDirectiveTypes();
        }

        private static IScriptDirective CreateInstance(Type type, IEnumerable<string> arguments)
        {
            try
            {
                return (IScriptDirective) Activator.CreateInstance(type, arguments.Select(i=>(object)i).ToArray());
            }
            catch (TargetInvocationException exception)
            {
                throw exception.InnerException;
            }
        }

        public void ApplyToScript(IEnumerable<DirectiveDefinition> directiveDefinitions)
        {
            foreach (var definition in directiveDefinitions)
            {
                var directiveType = GetDirectiveType(definition);
                var directive = CreateInstance(directiveType, definition.Arguments);

                directive.Apply(script); // TODO: rather than 'apply' the directive to the script why not simply add a reference from the script to the directive. This will avoid unnecesary duplication
            }
        }

        private Type GetDirectiveType(DirectiveDefinition directiveDefinition)
        {
            var dotNetClassName = directiveDefinition.Text.ToPascalCase() + "Directive";
            var argumentCount = directiveDefinition.Arguments.Count();

            var withMatchingName = new HashSet<Type>(directiveTypes.Where(i => i.Name == dotNetClassName));
            var withMatchingConstructor = new HashSet<Type>(directiveTypes.Where(i => i.HasPublicFullyStringParameterisedConstructor(argumentCount)));

            var candidateTypes = withMatchingName.Intersect(withMatchingConstructor);
            var directiveType = candidateTypes.FirstOrDefault();

            if (directiveType == null)
            {
                var message = new StringBuilder();
                message.AppendFormat("Cannot find a IScriptDirective implementation for '{0}' within these search assemblies:\r\n", directiveDefinition.Text);
                message.Append(searchAssemblies.Select(i => i.FullName).ToBulletedList());
                message.Append("\r\n\r\n");
                message.AppendFormat("The .NET implementation must be named '{0}', ", dotNetClassName);
                message.AppendFormat("derive from {0}, ", typeof (IScriptDirective).Name);
                message.AppendFormat("have public visibility and a public constructor containing all string parameters.\r\n\r\n");

                throw new InvalidOperationException(message.ToString());
            }
            return directiveType;
        }

        private IList<Type> GetDirectiveTypes()
        {
            var searchTypes = searchAssemblies.SelectMany(i => i.GetTypes()).ToList();

            var withCorrectBase = new HashSet<Type>(searchTypes.Where(i => i.DerivesFrom(typeof(IScriptDirective))));
            var withPublicVisibility = new HashSet<Type>(searchTypes.Where(i => i.IsVisible));
            var withMatchingConstructor = new HashSet<Type>(searchTypes.Where(i => i.HasPublicFullyStringParameterisedConstructor()));

            return withCorrectBase.Intersect(withPublicVisibility).Intersect(withMatchingConstructor).ToList();
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect BlackJet Software Ltd
United Kingdom United Kingdom
Stuart Wheelwright is the Principal Architect and Software Developer at BlackJet Software Ltd.

He has over 16 years commercial experience producing robust, maintainable, web-based solutions and bespoke systems for Microsoft platforms.

His latest project is Shopping UK, an elegantly simple shopping list for iPhone.

Comments and Discussions