/// <summary> /// Create a logger using the configured sinks, enrichers and minimum level. /// </summary> /// <returns>The logger.</returns> /// <remarks>To free resources held by sinks ahead of program shutdown, /// the returned logger may be cast to <see cref="IDisposable"/> and /// disposed.</remarks> public Logger CreateLogger() { if (_loggerCreated) { throw new InvalidOperationException("CreateLogger() was previously called and can only be called once."); } _loggerCreated = true; Action dispose = () => { foreach (var disposable in _logEventSinks.OfType <IDisposable>()) { disposable.Dispose(); } }; ILogEventSink sink = new SafeAggregateSink(_logEventSinks); if (_filters.Any()) { sink = new FilteringSink(sink, _filters); } var converter = new PropertyValueConverter(_maximumDestructuringDepth, _additionalScalarTypes, _additionalDestructuringPolicies); var processor = new MessageTemplateProcessor(converter); ILogEventEnricher enricher; switch (_enrichers.Count) { case 0: // Should be a rare case, so no problem making that extra interface dispatch. enricher = new EmptyEnricher(); break; case 1: enricher = _enrichers[0]; break; default: enricher = new SafeAggregateEnricher(_enrichers); break; } LevelOverrideMap overrideMap = null; if (_overrides.Count != 0) { overrideMap = new LevelOverrideMap(_overrides, _minimumLevel, _levelSwitch); } return(_levelSwitch == null ? new Logger(processor, _minimumLevel, sink, enricher, dispose, overrideMap) : new Logger(processor, _levelSwitch, sink, enricher, dispose, overrideMap)); }
/// <summary> /// Initializes a subscription tracking service based on the supplied /// <paramref name="configuration"/> /// </summary> /// <param name="configuration">The subscription tracking configuration</param> /// <returns>Returns a task whose result is the initialized subscription tracking service</returns> public async Task <IDiagnosticEventSink> InitDiagnosticEventSink(IConfiguration configuration) { var name = configuration?["name"]; var providerName = configuration?["provider"]; if (string.IsNullOrWhiteSpace(providerName)) { var message = "Provider not specified for diagnostic event sink '" + name + "'"; await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ConfigurationError) { Detail = message }.Build()); throw new ConfigurationErrorsException(message); } var provider = GetProvider(providerName); if (provider == null) { var message = "Unknown provider '" + providerName + "' specified for diagnostic event sink '" + name + "'"; await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ConfigurationError) { Detail = message }.Build()); throw new ConfigurationErrorsException(message); } await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ComponentInitialization) { Detail = "Initializing diagnostic event sink '" + name + "'" }.Build()); var minLevel = configuration.GetValue("minLevel", DiagnosticEventLevel.Debug); var maxLevel = configuration.GetValue("minLevel", DiagnosticEventLevel.Error); var sink = await provider.CreateDiagnosticEventSink(configuration); var filterSpec = new DiagnosticEventLevelSpecification(minLevel, maxLevel); var filterSink = new FilteringSink(sink, filterSpec); await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ComponentInitialization) { Detail = "Diagnostic event sink '" + name + "' initialized" }.Build()); return(filterSink); }
/// <summary> /// Initializes a subscription tracking service based on the supplied /// <paramref name="configuration"/> /// </summary> /// <param name="configuration">The subscription tracking configuration</param> /// <returns>Returns a task whose result is the initialized subscription tracking service</returns> public async Task <IDiagnosticEventSink> InitDiagnosticEventSink(DiagnosticEventSinkElement configuration) { var myConfig = configuration ?? new DiagnosticEventSinkElement(); if (string.IsNullOrWhiteSpace(myConfig.Provider)) { var message = "Provider not specified for diagnostic event sink '" + myConfig.Name + "'"; await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ConfigurationError) { Detail = message }.Build()); throw new ConfigurationErrorsException(message); } var provider = GetProvider(myConfig.Provider); if (provider == null) { var message = "Unknown provider '" + myConfig.Provider + "' specified for diagnostic event sink '" + myConfig.Name + "'"; await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ConfigurationError) { Detail = message }.Build()); throw new ConfigurationErrorsException(message); } await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ComponentInitialization) { Detail = "Initializing diagnostic event sink '" + myConfig.Name + "'" }.Build()); var sink = await provider.CreateDiagnosticEventSink(myConfig); var filterSpec = new DiagnosticEventLevelSpecification(myConfig.MinLevel, myConfig.MaxLevel); var filterSink = new FilteringSink(sink, filterSpec); await _diagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.ComponentInitialization) { Detail = "Diagnostic event sink '" + myConfig.Name + "' initialized" }.Build()); return(filterSink); }
protected async Task WhenFilteringAsync() { var filter = new FilteringSink(Inner.Object, Specification); await filter.ConsumeAsync(Event); }
protected void WhenFiltering() { var filter = new FilteringSink(Inner.Object, Specification); filter.Consume(Event); }
/// <summary> /// Create a logger using the configured sinks, enrichers and minimum level. /// </summary> /// <returns>The logger.</returns> /// <remarks>To free resources held by sinks ahead of program shutdown, /// the returned logger may be cast to <see cref="IDisposable"/> and /// disposed.</remarks> public Logger CreateLogger() { if (_loggerCreated) throw new InvalidOperationException("CreateLogger() was previously called and can only be called once."); _loggerCreated = true; Action dispose = () => { foreach (var disposable in _logEventSinks.OfType<IDisposable>()) disposable.Dispose(); }; ILogEventSink sink = new SafeAggregateSink(_logEventSinks); var auditing = _auditSinks.Any(); if (auditing) sink = new AggregateSink(new[] { sink }.Concat(_auditSinks)); if (_filters.Any()) { // A throwing filter could drop an auditable event, so exceptions in filters must be propagated // if auditing is used. sink = new FilteringSink(sink, _filters, auditing); } var converter = new PropertyValueConverter(_maximumDestructuringDepth, _additionalScalarTypes, _additionalDestructuringPolicies, auditing); var processor = new MessageTemplateProcessor(converter); ILogEventEnricher enricher; switch (_enrichers.Count) { case 0: // Should be a rare case, so no problem making that extra interface dispatch. enricher = new EmptyEnricher(); break; case 1: enricher = _enrichers[0]; break; default: enricher = new SafeAggregateEnricher(_enrichers); break; } LevelOverrideMap overrideMap = null; if (_overrides.Count != 0) { overrideMap = new LevelOverrideMap(_overrides, _minimumLevel, _levelSwitch); } return _levelSwitch == null ? new Logger(processor, _minimumLevel, sink, enricher, dispose, overrideMap) : new Logger(processor, _levelSwitch, sink, enricher, dispose, overrideMap); }
/// <summary> /// Create a logger using the configured sinks, enrichers and minimum level. /// </summary> /// <returns>The logger.</returns> /// <remarks>To free resources held by sinks ahead of program shutdown, /// the returned logger may be cast to <see cref="IDisposable"/> and /// disposed.</remarks> /// <exception cref="InvalidOperationException">When the logger is already created</exception> public Logger CreateLogger() { if (_loggerCreated) { throw new InvalidOperationException("CreateLogger() was previously called and can only be called once."); } _loggerCreated = true; ILogEventSink sink = new SafeAggregateSink(_logEventSinks); var auditing = _auditSinks.Any(); if (auditing) { sink = new AggregateSink(new[] { sink }.Concat(_auditSinks)); } if (_filters.Any()) { // A throwing filter could drop an auditable event, so exceptions in filters must be propagated // if auditing is used. sink = new FilteringSink(sink, _filters, auditing); } var converter = new PropertyValueConverter( _maximumDestructuringDepth, _maximumStringLength, _maximumCollectionCount, _additionalScalarTypes, _additionalDestructuringPolicies, auditing); var processor = new MessageTemplateProcessor(converter); ILogEventEnricher enricher; switch (_enrichers.Count) { case 0: // Should be a rare case, so no problem making that extra interface dispatch. enricher = new EmptyEnricher(); break; case 1: enricher = _enrichers[0]; break; default: // Enrichment failures are not considered blocking for auditing purposes. enricher = new SafeAggregateEnricher(_enrichers); break; } LevelOverrideMap overrideMap = null; if (_overrides.Count != 0) { overrideMap = new LevelOverrideMap(_overrides, _minimumLevel, _levelSwitch); } var disposableSinks = _logEventSinks.Concat(_auditSinks).OfType <IDisposable>().ToArray(); void Dispose() { foreach (var disposable in disposableSinks) { disposable.Dispose(); } } return(_levelSwitch == null ? new Logger(processor, _minimumLevel, sink, enricher, Dispose, overrideMap) : new Logger(processor, _levelSwitch, sink, enricher, Dispose, overrideMap)); }