-
Notifications
You must be signed in to change notification settings - Fork 357
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding support for Application Insights Diagnostics event logging (#3045
) * Adding support for ApplicationInsights Diagnostics event logging --------- Co-authored-by: Jacob Viau <[email protected]>
- Loading branch information
1 parent
59d3c4a
commit 9fad0f7
Showing
7 changed files
with
321 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
...e.WebJobs.Logging.ApplicationInsights/SelfDiagnostics/ApplicationInsightsEventListener.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Diagnostics; | ||
using System.Diagnostics.Tracing; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Timers; | ||
|
||
namespace Microsoft.Azure.WebJobs.Logging.ApplicationInsights | ||
{ | ||
/// <summary> | ||
/// Implementation of <see cref="EventListener"/> that listens to events produced by ApplicationInsights SDK. | ||
/// Logs data either every 10 seconds or when the batch becomes full, whichever occurs first. | ||
/// Logs in batch to reduce the volume of logs in kusto | ||
/// </summary> | ||
internal class ApplicationInsightsEventListener : EventListener | ||
{ | ||
private static readonly DiagnosticListener _source = new DiagnosticListener(string.Concat(ApplicationInsightsDiagnosticConstants.ApplicationInsightsDiagnosticSourcePrefix, nameof(ApplicationInsightsEventListener))); | ||
private readonly EventLevel _eventLevel; | ||
|
||
private const int LogFlushIntervalMs = 10 * 1000; | ||
private const string EventSourceNamePrefix = "Microsoft-ApplicationInsights-"; | ||
private const string EventName = nameof(ApplicationInsightsEventListener); | ||
private const int MaxLogLinesPerFlushInterval = 30; | ||
|
||
private Timer _flushTimer; | ||
private ConcurrentQueue<string> _logBuffer = new ConcurrentQueue<string>(); | ||
private ConcurrentQueue<EventSource> _eventSource = new ConcurrentQueue<EventSource>(); | ||
private static object _syncLock = new object(); | ||
private bool _disposed = false; | ||
|
||
public ApplicationInsightsEventListener(EventLevel eventLevel) | ||
{ | ||
this._eventLevel = eventLevel; | ||
_flushTimer = new Timer | ||
{ | ||
AutoReset = true, | ||
Interval = LogFlushIntervalMs | ||
}; | ||
_flushTimer.Elapsed += (sender, e) => Flush(); | ||
_flushTimer.Start(); | ||
} | ||
|
||
protected override void OnEventSourceCreated(EventSource eventSource) | ||
{ | ||
if (eventSource.Name.StartsWith(EventSourceNamePrefix)) | ||
{ | ||
EnableEvents(eventSource, _eventLevel, EventKeywords.All); | ||
_eventSource.Enqueue(eventSource); | ||
} | ||
base.OnEventSourceCreated(eventSource); | ||
} | ||
|
||
protected override void OnEventWritten(EventWrittenEventArgs eventData) | ||
{ | ||
if (!string.IsNullOrWhiteSpace(eventData.Message)) | ||
{ | ||
_logBuffer.Enqueue(string.Format(CultureInfo.InvariantCulture, eventData.Message, eventData.Payload.ToArray())); | ||
if (_logBuffer.Count >= MaxLogLinesPerFlushInterval) | ||
{ | ||
Flush(); | ||
} | ||
} | ||
} | ||
|
||
public void Flush() | ||
{ | ||
if (_logBuffer.Count == 0) | ||
{ | ||
return; | ||
} | ||
|
||
ConcurrentQueue<string> currentBuffer = null; | ||
lock (_syncLock) | ||
{ | ||
if (_logBuffer.Count == 0) | ||
{ | ||
return; | ||
} | ||
currentBuffer = _logBuffer; | ||
_logBuffer = new ConcurrentQueue<string>(); | ||
} | ||
|
||
// batch up to 30 events in one log | ||
StringBuilder sb = new StringBuilder(); | ||
// start with a new line | ||
sb.AppendLine(string.Empty); | ||
while (currentBuffer.TryDequeue(out string line)) | ||
{ | ||
sb.AppendLine(line); | ||
} | ||
_source.Write(EventName, sb.ToString()); | ||
} | ||
|
||
protected virtual void Dispose(bool disposing) | ||
{ | ||
if (!_disposed) | ||
{ | ||
if (disposing) | ||
{ | ||
while (_eventSource.TryDequeue(out EventSource source)) | ||
{ | ||
if (source != null) | ||
{ | ||
DisableEvents(source); | ||
source.Dispose(); | ||
} | ||
} | ||
|
||
if (_flushTimer != null) | ||
{ | ||
_flushTimer.Dispose(); | ||
} | ||
base.Dispose(); | ||
// ensure any remaining logs are flushed | ||
Flush(); | ||
} | ||
_disposed = true; | ||
} | ||
} | ||
|
||
public override void Dispose() | ||
{ | ||
Dispose(true); | ||
GC.SuppressFinalize(this); | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...ure.WebJobs.Logging.ApplicationInsights/SelfDiagnostics/SelfDiagnosticsTelemetryModule.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using Microsoft.ApplicationInsights.Extensibility; | ||
using System; | ||
using System.Diagnostics.Tracing; | ||
|
||
namespace Microsoft.Azure.WebJobs.Logging.ApplicationInsights | ||
{ | ||
/// <summary> | ||
/// Initializes <see cref="ApplicationInsightsEventListener"/> that listens to events produced by ApplicationInsights SDK. | ||
/// </summary> | ||
internal class SelfDiagnosticsTelemetryModule : ITelemetryModule, IDisposable | ||
{ | ||
private ApplicationInsightsEventListener _eventListener; | ||
private EventLevel _eventLevel; | ||
|
||
internal SelfDiagnosticsTelemetryModule(EventLevel eventLevel) | ||
{ | ||
_eventLevel = eventLevel; | ||
} | ||
|
||
public void Initialize(TelemetryConfiguration configuration) | ||
{ | ||
_eventListener = new ApplicationInsightsEventListener(_eventLevel); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Dispose(disposing: true); | ||
GC.SuppressFinalize(this); | ||
} | ||
|
||
private void Dispose(bool disposing) | ||
{ | ||
if (disposing) | ||
{ | ||
_eventListener?.Dispose(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.