Logging
.AddAvalancheServiceQueryLogger() adds a logger that writes debug information at end of query. It requires support service for microsoft's ILogger<T>.
// Service collection
IServiceCollection serviceCollection = new ServiceCollection();
// Add logging
InitializeLogging(serviceCollection);
// Avalanche.Service
serviceCollection
.AddCachePolicy(CachePolicies.Default)
.AddEntryPolicy(EntryPolicies.Default)
.AddAvalancheService()
.AddAvalancheServiceQueryLogger()
.AddHandlers(ServiceHandlers.Instance);
// Create MS service
using var msService = serviceCollection.BuildServiceProvider();
// Create Av service
IService avService = msService.GetRequiredService<IService>();
// Create request
IRequestFor<Type> request = new TypeRequest("System.String");
// Get type and have query result logged
Type type = avService.GetRequired<IRequestFor<Type>, Type>(request);
// Get logger
var logger = msService.GetRequiredService<Microsoft.Extensions.Logging.ILogger<IService>>();
//
logger.LogInformation(new EventId(0x0Abc0000), "HELLO!");
[1306000200 D] Query completed: TypeRequest(System.String, Module=)=System.String (Value, Cached) [2000000500 I] HELLO!
Full Example
Full example
using System;
using Avalanche.Service;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Core;
using Serilog.Events;
public class di_querylogger
{
// <InitializeLogging>
static IServiceCollection InitializeLogging(IServiceCollection serviceCollection)
{
// Initial configuration
MemoryConfiguration memConfig = new MemoryConfiguration()
.Set("Logging:LogLevel:Default", "Debug")
.Set("Serilog:WriteTo:0:Name", "Console")
.Set("Serilog:WriteTo:0:Args:OutputTemplate", "[{EventIdHex} {Level:u1}] {Message:lj}{NewLine}{Exception}")
.Set("Serilog:WriteTo:0:Args:RestrictedToMinimumLevel", "Verbose")
.Set("Serilog:WriteTo:0:Args:Theme", "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console");
// Read configuration
IConfigurationRoot configuration = new ConfigurationBuilder()
.Add(memConfig)
.Build();
// Logging
serviceCollection.AddLogging(loggingBuilder =>
loggingBuilder
#if DEBUG
.SetMinimumLevel(LogLevel.Trace)
#else
.SetMinimumLevel(LogLevel.Information)
#endif
.AddSerilog(SwitchableLogger.Instance, true)
.AddSerilogConfigurationLoader(configuration, SwitchableLogger.Instance,
c => new Serilog.LoggerConfiguration()
#if DEBUG
.MinimumLevel.Verbose()
#else
.MinimumLevel.Information()
#endif
.Enrich.With(new EventIdEnricher())
.ReadFrom.Configuration(configuration)
.CreateLogger())
);
//
return serviceCollection;
}
// </InitializeLogging>
public static void Run()
{
{
// <01>
// Service collection
IServiceCollection serviceCollection = new ServiceCollection();
// Add logging
InitializeLogging(serviceCollection);
// Avalanche.Service
serviceCollection
.AddCachePolicy(CachePolicies.Default)
.AddEntryPolicy(EntryPolicies.Default)
.AddAvalancheService()
.AddAvalancheServiceQueryLogger()
.AddHandlers(ServiceHandlers.Instance);
// Create MS service
using var msService = serviceCollection.BuildServiceProvider();
// Create Av service
IService avService = msService.GetRequiredService<IService>();
// Create request
IRequestFor<Type> request = new TypeRequest("System.String");
// Get type and have query result logged
Type type = avService.GetRequired<IRequestFor<Type>, Type>(request);
// Get logger
var logger = msService.GetRequiredService<Microsoft.Extensions.Logging.ILogger<IService>>();
//
logger.LogInformation(new EventId(0x0Abc0000), "HELLO!");
// </01>
}
{
// <10>
// Service collection
IServiceCollection serviceCollection = new ServiceCollection();
// Add logging
InitializeLogging(serviceCollection);
// Avalanche.Service
serviceCollection
.AddAvalancheServiceQueryLogger()
.AddHandlers(ServiceHandlers.Instance);
// Services
using var service = serviceCollection.BuildAvalancheServiceProvider(cachePolicy: CachePolicies.Default);
// Create request
IRequestFor<Type> request = new TypeRequest("System.String");
// Get type and have query result logged
Type type = service.GetRequired<IRequestFor<Type>, Type>(request);
// Get logger
var logger = service.GetRequiredService<Microsoft.Extensions.Logging.ILogger<IService>>();
//
logger.LogInformation(new EventId(2000000500), "HELLO!");
// </10>
}
}
// <MemoryConfiguration>
/// <summary>Memory configuration</summary>
public class MemoryConfiguration : ConfigurationProvider, IEnumerable<KeyValuePair<string, string>>, IConfigurationSource
{
/// <summary>Expose inner configuration data</summary>
public new IDictionary<String, String> Data => base.Data;
/// <summary>Configuration data</summary>
public string this[string key] { get => base.Data[key]; set => base.Data[key] = value; }
/// <summary>Create memory configuration</summary>
public MemoryConfiguration() : base() { }
/// <summary>Assign <paramref name="value"/> to <paramref name="key"/></summary>
public new MemoryConfiguration Set(string key, string value) { base.Data[key] = value; return this; }
/// <summary>Build configuration provider.</summary>
public IConfigurationProvider Build(IConfigurationBuilder builder) => this;
/// <summary>Enumerate</summary>
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => Data.GetEnumerator();
/// <summary>Enumerate</summary>
IEnumerator IEnumerable.GetEnumerator() => Data.GetEnumerator();
}
// </MemoryConfiguration>
// <EventIdEnricher>
/// <summary>Serilog enricher that reduces "EventId" to its "id" field.</summary>
public class EventIdEnricher : ILogEventEnricher
{
/// <summary>Reduce to EventId.id</summary>
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
// Get properties
if (!logEvent.Properties.TryGetValue("EventId", out LogEventPropertyValue? eventIdStructure)) return;
// Not structure field
if (eventIdStructure is not StructureValue structureValue || structureValue.Properties == null) return;
// Get list
IReadOnlyList<LogEventProperty> list = structureValue.Properties;
// Process each
for (int i = 0; i < list.Count; i++)
{
// Get property
LogEventProperty logEventProperty = list[i];
// Not id
if (logEventProperty.Name != "Id") continue;
// New property
LogEventProperty eventId = propertyFactory.CreateProperty("EventId", logEventProperty.Value);
// Add as new key
logEvent.AddOrUpdateProperty(eventId);
// Print as hex
string hex = logEventProperty.Value.ToString("X8", CultureInfo.InvariantCulture);
// New property
LogEventProperty eventIdHex = propertyFactory.CreateProperty("EventIdHex", hex);
// Add as new key
logEvent.AddOrUpdateProperty(eventIdHex);
// Completed
return;
}
}
}
// </EventIdEnricher>
}