How does one profile a WCF Web Service?

rgelbrgelb Posts: 45 Bronze 4
I have Ants Performance Profiler 5.2 (I couldn't find a forum specific to that).

I have a WCF Service project. It has several .svc files in a Visual Studio 2010, .NET 4.0 project. I am having trouble figuring out how to actually profile it in the Ants Profiler.

I bring up the Ants Profiler, choose ASP.NET web application (hosted in web development server), then try to pick the path. I've tried picking the base directory, the bin directory, the individual files, etc...nothing worked. Each approach produces an error.

The structure of the project is here: http://imgur.com/tuvkU

Can you please specifically explain to me how to actually profile my WCF Service project, e.g. what files to pick, what project type to pick, etc...

Thank you.



[url][/url]

Comments

  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    I don't think ANTS Performance Profiler has changed much. Based on the information you have provided, I'd say that you are profiling WCF hosted in IIS. The instructions for that are here and they should be pretty much the same in v5.

    http://www.red-gate.com/supportcenter/c ... wcf_in_iis
  • rgelbrgelb Posts: 45 Bronze 4
    Based on the information you have provided, I'd say that you are profiling WCF hosted in IIS.

    I don't even have IIS installed on my box. I would like to profile WCF hosted in the Web Development Service. Do you have instructions for that for Profiler 5.2?

    Btw, I've downloaded Profiler 6 trial and was able to attach to the WebDev process, but it this method (e.g. attaching to process) produces almost worthless results (just method timings).

    The preferred method (e.g. profile WCF hosted in the WebDev) is alluding me.

    I created a video of the process: http://www.youtube.com/watch?v=rUq6u6f1qyk

    In the video (has no audio), I do the following:

    1. Start the project from VS2010 just to show that it works
    2. Attempt to profile from Ants Profiler 6.3 and see it fail.

    What am I missing here?
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    Looks okay to me - just try running ANTS Performance Profiler as administrator and disabling Internet Explorer's Protected Mode. From the video it looks like profiling started and stopped again - it'll do that if IE has a security wobbly because IE will exit and cause the web server to stop.
  • rgelbrgelb Posts: 45 Bronze 4
    Ok, this got me further than before.

    After starting, I get this screen (perfectly normal): http://imgur.com/oGxbk
    Then I click on CalculationService.svc and get the error: http://imgur.com/KlT8o

    Here is the text of the error.


    Server Error in '/' Application.

    The type 'CC.AP.Services.Services.CalculationService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found.
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidOperationException: The type 'CC.AP.Services.Services.CalculationService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:


    [InvalidOperationException: The type 'CC.AP.Services.Services.CalculationService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found.]
    System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses) +677
    System.ServiceModel.HostingManager.CreateService(String normalizedVirtualPath) +1473
    System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +55
    System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +655

    [ServiceActivationException: The service '/CalculationService.svc' cannot be activated due to an exception during compilation. The exception message is: The type 'CC.AP.Services.Services.CalculationService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found..]
    System.Runtime.AsyncResult.End(IAsyncResult result) +459
    System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +198
    System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, String routeServiceVirtualPath, Boolean flowContext, Boolean ensureWFService) +240
    System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +370
    System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +223
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +86
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    Looks like the configuration is not correct, but unfortunately I have to understand your service to know what's wrong. As a guess, I'd say ASP .NET can't find the dll specified in the svc file.

    Maybe you need to provide a virtual path (other than /) or maybe you are not running the appropriate version of the development webserver because you chose the wrong .net version from the dropdown.
  • rgelbrgelb Posts: 45 Bronze 4
    Brian,

    I am about to dump a lot of XML and code on you. If there is a better way, please let me know.

    Here is the Markup:
    <%@ ServiceHost Language="C#" Debug="true" Service="CC.AP.Services.Services.CalculationService" CodeBehind="CalculationService.svc.cs" %>


    Here is some of the code from the code behind of the service:
        &#91;OperationReportServiceBehavior&#93;
        public class CalculationService : ServiceBase, ICalculationService
        &#123;
            
            #region Constructors
    
    
            public CalculationService&#40;&#41; : base&#40;LogManager.GetLogger&#40;"CalculationServiceSystemLog"&#41;&#41;
            &#123;
    
            &#125;
    
           /// Public Methods
    &#125;
    
    

    I didn't include any of the public methods since they are immaterial to this.

    The interface ICalculationService simply contains public methods that need to be implemented.

    Here is the web.config:

    <?xml version="1.0"?>
    <!--
    Note: As an alternative to hand editing this file you can use the
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in
    machine.config.comments usually located in
    \Windows\Microsoft.Net\Framework\v2.x\Config
    -->
    <configuration>
    <configSections>
    <!-- For log4net. -->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false"/>

    </configSections>

    <appSettings>
    <add key="ApDbConnection" value="Data Source=lani-dev3;Initial Catalog=AP_RT_Dev;User ID=svc_fusion;Password=svc_fusion"/>
    <add key="TallyURL" value="http://lani-radio007:8080/ArbitronTallyWebServices/tally"/&gt;
    <add key="PreloadBooksOnStartup" value="true"/>

    <add key="WhatToLoadAtInterval" value="LastXMonths"/> <!-- Choices are LastXMonths or LastXBooksForMarket-->
    <add key="HowManyToLoadAtInterval" value="18"/> <!-- Indicates either how many months of
    books to load or how many books to load for each market-->

    <!-- The names of these variables/keys should be in the form of 'Monitor'<ServiceName>'Ops' for the OperationReportInspector to find them. -->
    <add key="MonitorCalculationServiceOps" value="true"/>
    <add key="MonitorMetadataServiceOps" value="true"/>

    </appSettings>
    <connectionStrings/>
    <log4net>
    <!-- Each service has its own system log file, and the corresponding operations logs which are controled by
    the above monitoring flags, 'MonitorCalculationServiceOps' and 'MonitorMetadataServiceOps'.
    The operations logs must be in the form of <ServiceName><OpsLog> for it to be picked up by the service. -->

    <!-- This is for the Calculation Service. -->
    <appender name="CalculationServiceSystemLog" type="log4net.Appender.RollingFileAppender">
    <file value="Logs\\CalculationServiceSystem.log"/>
    <appendToFile value="true"/>
    <rollingStyle value="Composite"/>
    <datePattern value="yyyyMMdd"/>
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="20MB"/>
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level - %message%newline"/>
    </layout>
    </appender>

    <!-- Here we reference the logger name to the appender. -->
    <logger name="CalculationServiceSystemLog">
    <level value="ALL"/>
    <appender-ref ref="CalculationServiceSystemLog"/>
    </logger>

    <!-- Calculation operations' log. -->
    <appender name="CalculationServiceOpsLog" type="log4net.Appender.RollingFileAppender">
    <file value="Logs\\ops\\CalculationServiceOps.log"/>
    <appendToFile value="true"/>
    <rollingStyle value="Composite"/>
    <datePattern value="yyyyMMdd"/>
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="20MB"/>
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level - %message%newline"/>
    </layout>
    </appender>

    <!-- Here we reference the logger name to the appender. -->
    <logger name="CalculationServiceOpsLog">
    <level value="ALL"/>
    <appender-ref ref="CalculationServiceOpsLog"/>
    </logger>

    <!-- This is for the Metadata Service. -->
    <appender name="MetadataServiceSystemLog" type="log4net.Appender.RollingFileAppender">
    <file value="Logs\\MetadataServiceSystem.log"/>
    <appendToFile value="true"/>
    <rollingStyle value="Composite"/>
    <datePattern value="yyyyMMdd"/>
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="20MB"/>
    <staticLogFileName value="true"/>
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level - %message%newline"/>
    </layout>
    </appender>

    <!-- Here we reference the logger name to the appender. -->
    <logger name="MetadataServiceSystemLog">
    <level value="ALL"/>
    <appender-ref ref="MetadataServiceSystemLog"/>
    </logger>

    <!-- Metada service operations' log. -->
    <appender name="MetadataServiceOpsLog" type="log4net.Appender.RollingFileAppender">
    <file value="Logs\\ops\\MetadataServiceOps.log"/>
    <appendToFile value="true"/>
    <rollingStyle value="Composite"/>
    <datePattern value="yyyyMMdd"/>
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="20MB"/>
    <staticLogFileName value="true"/>
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level - %message%newline"/>
    </layout>
    </appender>

    <!-- Here we reference the logger name to the appender. -->
    <logger name="MetadataServiceOpsLog">
    <level value="ALL"/>
    <appender-ref ref="MetadataServiceOpsLog"/>
    </logger>

    <!-- Utilized by the Cache Manager, since it is a Singleton it will write to its own file. -->
    <appender name="TallyCacheManagerSystemLog" type="log4net.Appender.RollingFileAppender">
    <file value="Logs\\TallyCacheManagerSystemLog.log"/>
    <appendToFile value="true"/>
    <rollingStyle value="Composite"/>
    <datePattern value="yyyyMMdd"/>
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="20MB"/>
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level - %message%newline"/>
    </layout>
    </appender>
    <logger name="TallyCacheManagerSystemLog">
    <level value="ALL"/>
    <appender-ref ref="TallyCacheManagerSystemLog"/>
    </logger>
    </log4net>
    <system.web>
    <!--
    Set compilation debug="true" to insert debugging
    symbols into the compiled page. Because this
    affects performance, set this value to true only
    during development.
    -->
    <compilation debug="true" targetFramework="4.0"/>
    <!--
    The <authentication> section enables configuration
    of the security authentication mode used by
    ASP.NET to identify an incoming user.
    -->
    <authentication mode="Windows"/>
    <!--
    The <customErrors> section enables configuration
    of what to do if/when an unhandled error occurs
    during the execution of a request. Specifically,
    it enables developers to configure html error pages
    to be displayed in place of a error stack trace.

    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
    <error statusCode="403" redirect="NoAccess.htm" />
    <error statusCode="404" redirect="FileNotFound.htm" />
    </customErrors>
    -->
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
    </system.web>
    <!--
    The system.webServer section is required for running ASP.NET AJAX under Internet
    Information Services 7.0. It is not necessary for previous version of IIS.
    -->
    <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <bindings>
    <basicHttpBinding>
    <binding name="XmlMessageBinding" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"
    maxBufferSize="2147483647" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
    <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
    <security mode="None"/>
    </binding>
    </basicHttpBinding>
    </bindings>

    <services>

    <service behaviorConfiguration="CC.AP.Services.Services.MetadataServiceBehavior" name="CC.AP.Services.Services.MetadataService">
    <endpoint address="" binding="basicHttpBinding" contract="CC.AP.WcfContracts.IMetadataService">
    <!--<identity>
    <dns value="localhost"/>
    </identity>-->
    </endpoint>

    <endpoint address="ws" binding="wsHttpBinding" contract="CC.AP.WcfContracts.IMetadataService"/>

    <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>-->
    </service>

    <service behaviorConfiguration="CC.AP.Services.Services.CalculationServiceBehavior" name="CC.AP.Services.Services.CalculationService">
    <endpoint address="" binding="basicHttpBinding" contract="CC.AP.WcfContracts.ICalculationService">
    <!--<identity>
    <dns value="localhost"/>
    </identity>-->
    </endpoint>

    <endpoint address="ws" binding="wsHttpBinding" contract="CC.AP.WcfContracts.ICalculationService"/>

    <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>-->
    </service>

    </services>
    <behaviors>
    <endpointBehaviors>
    <behavior name="webBehavior">
    <webHttp />
    <dataContractSerializer maxItemsInObjectGraph="2147483647" />
    </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
    <behavior name="CC.AP.Services.Services.MetadataServiceBehavior">
    <serviceMetadata httpGetEnabled="true" />
    <serviceDebug includeExceptionDetailInFaults="true" />
    <serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="200"
    maxConcurrentInstances="100" />
    </behavior>
    <behavior name="CC.AP.Services.Services.CalculationServiceBehavior">
    <serviceMetadata httpGetEnabled="true" />
    <serviceDebug includeExceptionDetailInFaults="true" />
    <serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="200"
    maxConcurrentInstances="100" />
    </behavior>
    <behavior name="">
    <serviceMetadata httpGetEnabled="true" />
    <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
    </serviceBehaviors>
    </behaviors>
    </system.serviceModel>
    </configuration>
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    Can you please try the following:
    • Start the website without profiling from Visual Studio
    • Use SysInternals Process Explorer to get the command line for the webserver exe
    • Stop the web server
    • Start the profiler as an administrator and run the webserver using the command line and arguments retrieved from Process Explorer
  • rgelbrgelb Posts: 45 Bronze 4
    Brian,

    That worked. In fact, it worked pretty great and it solves the problem for me.

    But why won't The WebDevServer profile work?
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    Without more data, this is impossible for me to answer. I guess you could compare the command-line generated by Visual Studio to the one generated by Profiler using Process Explorer. There are only three settings that you can pass to WebDev (excluding dotnet version, which actually has the effect of launching a different version of WebDev).

    More than likely, it's the virtual directory name. Visual Studio has an inside track on knowing what that should be.
Sign In or Register to comment.