Issue with Semantic logging application block

Topics: Semantic Logging Application Block
Jun 12, 2013 at 8:27 PM
I am trying to run the sample Logging app code that is published in the documentation in azure.
The only difference is that my app hosts multiple web sites and I register the listener in all these web sites.

The error I see in the azure role is:

Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 6/12/2013 7:07:22 PM
Event time (UTC): 6/12/2013 7:07:22 PM
Event ID: a52effe9357d4988956243f048a08a50
Event sequence: 2
Event occurrence: 1
Event detail code: 0

Application information:
Application domain: /LM/W3SVC/1273337584/ROOT/WebAPI-2-130155376415491005 
Trust level: Full 
Application Virtual Path: /WebAPI 
Application Path: E:\sitesroot\1\ 
Machine name: RD00155DA9A03F 
Process information:
Process ID: 3248 
Process name: w3wp.exe 
Account name: NT AUTHORITY\NETWORK SERVICE 
Exception information:
Exception type: HttpException 
Exception message: Unsupported type ServiceContext in event source.
at System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app)
at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)
at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context)
at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)

Unsupported type ServiceContext in event source.
at System.Diagnostics.Tracing.ManifestBuilder.GetTypeName(Type type)
at System.Diagnostics.Tracing.ManifestBuilder.AddEventParameter(Type type, String name)
at System.Diagnostics.Tracing.EventSource.CreateManifestAndDescriptors(Type eventSourceType, String eventSourceDllName, EventSource source)
at System.Diagnostics.Tracing.EventSource.InsureInitialized()
at System.Diagnostics.Tracing.EventSource.SendCommand(EventListener listener, EventCommand command, Boolean enable, EventLevel level, EventKeywords matchAnyKeyword, IDictionary`2 commandArguments)
at System.Diagnostics.Tracing.EventListener.EnableEvents(EventSource eventSource, EventLevel level)
at Api.Global.SetupListener()
at Api.Global.InitializeDiagnostics()
at Api.Global.Application_Start(Object sender, EventArgs e)



Request information:
Request URL: https://xyz.cloudapp.net:443/webapi/User 
Request path: /webapi/User 
User host address: 131.107.147.102 
User:  
Is authenticated: False 
Authentication Type:  
Thread account name: NT AUTHORITY\NETWORK SERVICE 
Thread information:
Thread ID: 6 
Thread account name: NT AUTHORITY\NETWORK SERVICE 
Is impersonating: False 
Stack trace:    at System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app)
at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)
at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context)
at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)

What am I missing here?
Jun 12, 2013 at 8:37 PM
Exception message: Unsupported type ServiceContext in event source.
This message means that there is a method in the EventSource that has a parameter of type ServiceContext which is not one of the predefined supported types.

What sample Logging app code are you using? Can you provide a link or post the code?

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Jun 12, 2013 at 8:49 PM
The Global ASAX where I register the listener looks like this :
    /// <summary>
    /// The logging connection string Setting name
    /// </summary>
    internal const string AzureLoggingConfigurationSettingName = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";

    /// <summary>
    /// The Logging verbosity setting
    /// </summary>
    internal const string AzureLoggingVerbositySettingName = "LoggingVerbosity";

    /// <summary>
    /// The observable listener used for logging
    /// </summary>
    private ObservableEventListener listener;
    #endregion

    #region Methods
    /// <summary>
    /// Initialize the diagnostics
    /// </summary>
    internal void InitializeDiagnostics()
    {
        var connectionString = RoleEnvironment.GetConfigurationSettingValue(AzureLoggingConfigurationSettingName);

        this.listener = new ObservableEventListener();
        this.listener.LogToWindowsAzureTable(RoleEnvironment.CurrentRoleInstance.Id, connectionString, bufferingInterval: TimeSpan.FromSeconds(30));

        this.SetupListener();
        if (RoleEnvironment.IsAvailable)
        {
            RoleEnvironment.Changed += this.RoleEnvironment_Changed;
        }
    }

    /// <summary>
    /// Setup the observable listener.
    /// </summary>
    internal void SetupListener()
    {
        EventLevel level;
        if (Enum.TryParse<EventLevel>(RoleEnvironment.GetConfigurationSettingValue(AzureLoggingVerbositySettingName), out level))
        {
            Trace.TraceInformation("Updating verbosity to {0}", level);
            this.listener.EnableEvents(Instrumentation.MyEventSource.Log, level);
        }
        else
        {
            Trace.TraceWarning("Invalid verbosity configuration");
        }
    }

    /// <summary>
    /// Called when the first resource (such as a page) in an ASP.NET application is requested.
    /// </summary>
    /// <param name="sender">
    /// The source of the event.
    /// </param>
    /// <param name="e">
    /// The <see cref="EventArgs"/> instance containing the event data.
    /// </param>
    /// <remarks>
    /// The Application_Start method is called only one time during the life cycle of an application
    /// </remarks>
    protected override void Application_Start(object sender, EventArgs e)
    {
        RouteConfiguration.Register();
        this.InitializeDiagnostics();
        base.Application_Start(sender, e);
    }

    /// <summary>
    /// The role environment changed event.
    /// </summary>
    /// <param name="sender">the sender</param>
    /// <param name="e">changed event args</param>
    private void RoleEnvironment_Changed(object sender, RoleEnvironmentChangedEventArgs e)
    {
        // Using WAD for tracing how the verbosity is updated
        Trace.TraceInformation("Updating instance");

        foreach (var settingChange in e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>())
        {
            if (string.Equals(settingChange.ConfigurationSettingName, AzureLoggingVerbositySettingName, StringComparison.Ordinal))
            {
                Trace.TraceInformation("Setting up listener after change");
                this.SetupListener();
            }
        }
    }
And My event source class looks like this:

namespace XYZ.Instrumentation
{
using System;
using System.Diagnostics.Tracing;
using System.Text;
using XYZ.Contracts.Security;

/// <summary>
///  The Event source class
/// </summary>
[EventSource(Name = "MyEventSource")]
public sealed class MyEventSource : EventSource
{
    /// <summary>
    ///  The internal reference to the event source
    /// </summary>
    private static readonly Lazy<MyEventSource> LogSource = new Lazy<MyEventSource>(() => new MyEventSource());

    /// <summary>
    /// Gets the event source object
    /// </summary>
    public static MyEventSource Log
    {
        get { return LogSource.Value; }
    }

    #region Logging methods

    /// <summary>
    /// Logs My Event 90001
    /// </summary>
    /// <param name="context">the service context of the call</param>
    /// <param name="info">the event information</param>
    /// <param name="ex">the exception</param>
    [Event(90001, Level = EventLevel.Critical)]
    public void LogMyUnknownEvent(Xyz.ServiceContext context, Xyz.EventInformation info, Exception ex)
    {
        if (this.IsEnabled())
        {
            this.WriteEvent(90001, MyExceptionHandler.FormatExceptionEventToWindowEventLogMessage(exceptionEvent));
        }
    }
}
Jun 12, 2013 at 9:01 PM
Can I Not use my own context/ Event Information methods/ classes in the event source?
Do I register additional types That I want to use? Or Am I completely missing the point?
Jun 12, 2013 at 9:08 PM
public void LogMyUnknownEvent(Xyz.ServiceContext context, Xyz.EventInformation info, Exception ex)
The above line is causing the error. Only certain types are supported as arguments to EventSource methods (basically primitive types plus a few others such as string, GUID). You need to modify the method signature to not use those types.

One approach would be to use the NonEvent attribute and then have the objects formatted to strings or override ToString() on your classes and have the NonEvent method call ToString(). The code could look something like this:
    /// <summary>
    /// Logs My Event 90001
    /// </summary>
    /// <param name="context">the service context of the call</param>
    /// <param name="info">the event information</param>
    /// <param name="ex">the exception</param>
    [Event(90001, Level = EventLevel.Critical)]
    public void LogMyUnknownEvent(string serviceContext, string eventInformation, string exception)
    {
        if (this.IsEnabled())
        {
            this.WriteEvent(90001, serviceContext, eventInformation, exception);
        }
    }

    [NonEvent]
    public void LogMyUnknownEvent(Xyz.ServiceContext context, Xyz.EventInformation info, Exception ex)
    {
            // Formatters that convert objects to string
            this.LogMyUnknownEvent(FormatServiceContext(context), FormatEventInformation(info), FormatException(ex));
            // Or maybe have classes override ToString()
            this.LogMyUnknownEvent(context.ToString(), info.ToString(), ex.ToString());
    }
~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Jun 12, 2013 at 9:39 PM
Understood.
Thanks Randy.