Windows 8 Pro or Windows 8 Enterprise offers the ability to use Semantic Logging so that a Window 8 App can log to a central database using the OUT-OF-PROCESS service from the Enterprise Library. (ETW with EventSource in the Windows App)
Here’s a simple Howto:
Step 1: Install the Enterprise Library Semantic Logging OUT-OF-PROCESS service. Link underneath.
Enterprise Library 6, Semantic Logging, Part 2, OUT-OF-PROCESS
Step 2: Add an EventSource class
using System.Diagnostics.Tracing;
namespace SemanticLoggingOutOfProcessTestApp.Log
{
[EventSource(Name = "BasicLogger")]
public class BasicLogger : EventSource
{
public static readonly BasicLogger Log = new BasicLogger();
/// <summary>
/// Using Keywords
/// The example includes a Keywords parameter for the Event attribute for many of the log methods.
/// You can use keywords to define different groups of log methods so that when you enable an event source, you can specify which groups of log methods to enable:
/// only log methods whose Keywords parameter matches one of the specified groups will be able to write log messages.
/// You must define the keywords you will use in a nested class called Keywords as shown in the example. Each keyword value is a 64 bit integer,
/// which is treated as a bit array enabling you to define 64 different keywords.
/// You can associate a log method with multiple keywords as shown in the following example where the Failure message is associated with both the Diagnostic and Perf keywords.
/// </summary>
public class Keywords
{
public const EventKeywords Page = (EventKeywords)1;
public const EventKeywords DataBase = (EventKeywords)2;
public const EventKeywords Diagnostic = (EventKeywords)4;
public const EventKeywords Perf = (EventKeywords)8;
public const EventKeywords ControllerAction = (EventKeywords)16;
public const EventKeywords DiagnosticStartStop = (EventKeywords)32;
}
/// <summary>
/// Using Opcodes and Tasks
///
/// You can use the Opcodes and Tasks parameters of the Event attribute to add additional information to the message that the event source logs.
/// The Opcodes and Tasks are defined using nested classes of the same name in the same way that you define Keywords. The example event source includes two tasks: Page and DBQuery.
///
/// #!SPOKENBY(Poe)!# The logs contain just the numeric task and opcode identifiers.
/// The developers who write the EventSource class and IT Pros who use the logs must agree on the definitions of the tasks and opcodes used in the application.
/// Notice how in the sample, the task constants have meaningful names such as Page and DBQuery: these tasks appear in the logs as task ids 1 and 2 respectively.
///
/// If you choose to define custom opcodes, you should assign integer values of 11 or above.
/// If you define a custom opcode with a value of 10 or below, messages that use these opcodes will not be delivered.
/// </summary>
public class Task
{
public const EventTask Page = (EventTask)1;
public const EventTask DBQuery = (EventTask)2;
public const EventTask AmazingTask = (EventTask)3;
}
public class Opcodes
{
public const EventOpcode Page = (EventOpcode)11;
public const EventOpcode DBQuery = (EventOpcode)12;
}
// Keyword value = 17 (16 + 1)
[Event(1, Message = "{0}", Level = EventLevel.Error, Keywords = Keywords.ControllerAction | Keywords.Page)]
public void ErrorWithKeywordsControllerActionAndKeywordsPage(string message)
{
if (IsEnabled()) WriteEvent(1, message);
}
// Keyword value = 16
[Event(4, Message = "{0}", Level = EventLevel.Error, Keywords = Keywords.ControllerAction)]
public void ErrorWithKeywordsControllerAction(string message)
{
if (IsEnabled()) WriteEvent(4, message);
}
// Keyword value = 32
[Event(5, Message = "{0}", Level = EventLevel.Error, Keywords = Keywords.DiagnosticStartStop)]
public void ErrorWithKeywordsDiagnosticStartStop(string message)
{
if (IsEnabled()) WriteEvent(5, message);
}
// Keyword value = 0
[Event(2, Message = "{0}", Level = EventLevel.Error)]
public void ErrorWithNoKeywordsDefined(string message)
{
if (IsEnabled()) WriteEvent(2, message);
}
[Event(7, Message = "{0}", Level = EventLevel.Warning, Task= Task.Page)]
public void WarningWithEventTaskPage(string message)
{
if (IsEnabled()) WriteEvent(7, message);
}
[Event(8, Message = "{0}", Level = EventLevel.Warning, Task = Task.AmazingTask)]
public void WarningWithEventTaskAmazingTask(string message)
{
if (IsEnabled()) WriteEvent(8, message);
}
[Event(9, Message = "{0}", Level = EventLevel.Warning)]
public void WarningWithNoEventTaskDefined(string message)
{
if (IsEnabled()) WriteEvent(9, message);
}
[Event(10, Message = "{0}", Level = EventLevel.Warning,Opcode=Opcodes.Page)]
public void WarningWithOpcodePage(string message)
{
if (IsEnabled()) WriteEvent(10, message);
}
}
}
Step 3: write a log message
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
BasicLogger.Log.ErrorWithNoKeywordsDefined("Hello World log test");
If the OUT-OF-PROCESS service is configured correctly, the log entry will be saved to a database.
NOTE:
If using WinRT, this option is not possible.
This link shows how to log on a WinRT system
http://code.msdn.microsoft.com/windowsapps/Logging-Sample-for-Windows-0b9dffd7
and here’s another example
http://sharepoint.namics.com/2013/06/logging-fur-windows-store-apps.html
