Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EventListener for SelfDiagnostics #2259

Merged
merged 3 commits into from
May 11, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
namespace Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.SelfDiagnosticsInternals
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.Tracing;
using System.IO;
using System.Text;
using System.Threading;

/// <summary>
/// SelfDiagnosticsEventListener class enables the events from OpenTelemetry event sources
/// and write the events to a local file in a circular way.
/// </summary>
internal class SelfDiagnosticsEventListener : EventListener
{
private const string EventSourceNamePrefix = "Microsoft-ApplicationInsights-";
private readonly object lockObj = new object();
private readonly EventLevel logLevel;

// private readonly SelfDiagnosticsConfigRefresher configRefresher;
private readonly List<EventSource> eventSourcesBeforeConstructor = new List<EventSource>();

public SelfDiagnosticsEventListener(EventLevel logLevel/*, SelfDiagnosticsConfigRefresher configRefresher*/)
{
this.logLevel = logLevel;

// this.configRefresher = configRefresher ?? throw new ArgumentNullException(nameof(configRefresher));

List<EventSource> eventSources;
lock (this.lockObj)
{
eventSources = this.eventSourcesBeforeConstructor;
this.eventSourcesBeforeConstructor = null;
}

foreach (var eventSource in eventSources)
{
#if NET452
this.EnableEvents(eventSource, this.logLevel, (EventKeywords)(-1));
#else
this.EnableEvents(eventSource, this.logLevel, EventKeywords.All);
#endif
}
}

internal void WriteEvent(string eventMessage, ReadOnlyCollection<object> payload)
{
// TODO
}

protected override void OnEventSourceCreated(EventSource eventSource)
{
if (eventSource.Name.StartsWith(EventSourceNamePrefix, StringComparison.Ordinal))
{
// If there are EventSource classes already initialized as of now, this method would be called from
// the base class constructor before the first line of code in SelfDiagnosticsEventListener constructor.
// In this case logLevel is always its default value, "LogAlways".
// Thus we should save the event source and enable them later, when code runs in constructor.
if (this.eventSourcesBeforeConstructor != null)
{
lock (this.lockObj)
{
if (this.eventSourcesBeforeConstructor != null)
{
this.eventSourcesBeforeConstructor.Add(eventSource);
return;
}
}
}

#if NET452
this.EnableEvents(eventSource, this.logLevel, (EventKeywords)(-1));
#else
this.EnableEvents(eventSource, this.logLevel, EventKeywords.All);
#endif
}

base.OnEventSourceCreated(eventSource);
}

/// <summary>
/// This method records the events from event sources to a local file, which is provided as a stream object by
/// SelfDiagnosticsConfigRefresher class. The file size is bound to a upper limit. Once the write position
/// reaches the end, it will be reset to the beginning of the file.
/// </summary>
/// <param name="eventData">Data of the EventSource event.</param>
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
this.WriteEvent(eventData.Message, eventData.Payload);
}
}
}