Skip to content
Merged
Show file tree
Hide file tree
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
@@ -1,106 +1,108 @@
using System;
using System.Diagnostics;
using System.Globalization;

namespace Microsoft.ApplicationInsights.Kubernetes.Debugging
{
/// <summary>
/// Diagnostic Source of Application Insights for Kubernetes.
/// </summary>
public sealed class ApplicationInsightsKubernetesDiagnosticSource
{
private readonly DiagnosticSource _innerSource;

/// <summary>
/// Diagnostic source listener subscribe point.
/// </summary>
public DiagnosticListener Observable => (DiagnosticListener)this._innerSource;

/// <summary>
/// Gets the name of the diagnostic source.
/// </summary>
public const string DiagnosticSourceName = "ApplicationInsightsKubernetesDiagnosticSource";

private ApplicationInsightsKubernetesDiagnosticSource()
{
_innerSource = new DiagnosticListener(DiagnosticSourceName);
}

// Explict static constructor to tell C# compiler not to mark type as beforefieldinit
static ApplicationInsightsKubernetesDiagnosticSource()
{
}

/// <summary>
/// Gets the singleton instance of Application Insights for Kubernetes.
/// </summary>
/// <returns></returns>
public static ApplicationInsightsKubernetesDiagnosticSource Instance { get; } = new ApplicationInsightsKubernetesDiagnosticSource();

/// <summary>
/// Logs the critical message.
/// </summary>
public void LogCritical(string message, params object[] args)
{
Write(DiagnosticLogLevel.Critical, message, args);
}

/// <summary>
/// Logs the error.
/// </summary>
public void LogError(string message, params object[] args)
{
Write(DiagnosticLogLevel.Error, message, args);
}

/// <summary>
/// Logs the warning message.
/// </summary>
public void LogWarning(string message, params object[] args)
{
Write(DiagnosticLogLevel.Warning, message, args);
}

/// <summary>
/// Logs the information.
/// </summary>
/// <param name="message"></param>
/// <param name="args"></param>
public void LogInformation(string message, params object[] args)
{
Write(DiagnosticLogLevel.Information, message, args);
}

/// <summary>
/// Logs the debugging message.
/// </summary>
/// <param name="message"></param>
/// <param name="args"></param>
public void LogDebug(string message, params object[] args)
{
Write(DiagnosticLogLevel.Debug, message, args);
}

/// <summary>
/// Logs the trace message.
/// </summary>
/// <param name="message"></param>
/// <param name="args"></param>
public void LogTrace(string message, params object[] args)
{
Write(DiagnosticLogLevel.Trace, message, args);
}

private void Write(DiagnosticLogLevel level, string message, params object[] args)
{
if (_innerSource.IsEnabled(level.ToString()))
{
string timedFormat = "[" + DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture) + "] " + message;
_innerSource.Write(level.ToString(), new
{
content = string.Format(CultureInfo.InvariantCulture, timedFormat, args),
});
}
}
}
}
using System;
using System.Diagnostics;
using System.Globalization;

namespace Microsoft.ApplicationInsights.Kubernetes.Debugging
{
/// <summary>
/// Diagnostic Source of Application Insights for Kubernetes.
/// </summary>
public sealed class ApplicationInsightsKubernetesDiagnosticSource
{
private readonly DiagnosticSource _innerSource;

/// <summary>
/// Diagnostic source listener subscribe point.
/// </summary>
public DiagnosticListener Observable => (DiagnosticListener)this._innerSource;

/// <summary>
/// Gets the name of the diagnostic source.
/// </summary>
public const string DiagnosticSourceName = "ApplicationInsightsKubernetesDiagnosticSource";

private ApplicationInsightsKubernetesDiagnosticSource()
{
_innerSource = new DiagnosticListener(DiagnosticSourceName);
}

// Explict static constructor to tell C# compiler not to mark type as beforefieldinit
static ApplicationInsightsKubernetesDiagnosticSource()
{
}

/// <summary>
/// Gets the singleton instance of Application Insights for Kubernetes.
/// </summary>
/// <returns></returns>
public static ApplicationInsightsKubernetesDiagnosticSource Instance { get; } = new ApplicationInsightsKubernetesDiagnosticSource();

/// <summary>
/// Logs the critical message.
/// </summary>
public void LogCritical(string message, params object[] args)
{
Write(DiagnosticLogLevel.Critical, message, args);
}

/// <summary>
/// Logs the error.
/// </summary>
public void LogError(string message, params object[] args)
{
Write(DiagnosticLogLevel.Error, message, args);
}

/// <summary>
/// Logs the warning message.
/// </summary>
public void LogWarning(string message, params object[] args)
{
Write(DiagnosticLogLevel.Warning, message, args);
}

/// <summary>
/// Logs the information.
/// </summary>
/// <param name="message"></param>
/// <param name="args"></param>
public void LogInformation(string message, params object[] args)
{
Write(DiagnosticLogLevel.Information, message, args);
}

/// <summary>
/// Logs the debugging message.
/// </summary>
/// <param name="message"></param>
/// <param name="args"></param>
public void LogDebug(string message, params object[] args)
{
Write(DiagnosticLogLevel.Debug, message, args);
}

/// <summary>
/// Logs the trace message.
/// </summary>
/// <param name="message"></param>
/// <param name="args"></param>
public void LogTrace(string message, params object[] args)
{
Write(DiagnosticLogLevel.Trace, message, args);
}

private void Write(DiagnosticLogLevel level, string message, params object[] args)
{
if (_innerSource.IsEnabled(level.ToString()))
{
string timedFormat = "[" + DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture) + "] " + message;
_innerSource.Write(level.ToString(), new
{
content = args.Length > 0
? string.Format(CultureInfo.InvariantCulture, timedFormat, args)
: timedFormat,
});
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using Microsoft.ApplicationInsights.Kubernetes.Debugging;
using Microsoft.ApplicationInsights.Kubernetes.Utilities;
using Xunit;

namespace Microsoft.ApplicationInsights.Kubernetes.Tests;

public class ApplicationInsightsKubernetesDiagnosticSourceTests
{
[Fact]
public void ShouldHandleKubernetesErrors()
{
var target = ApplicationInsightsKubernetesDiagnosticSource.Instance;

// sample AKS exception message with {}
var ex = new k8s.Autorest.HttpOperationException("Operation returned an invalid status code 'Forbidden', response body {\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"nodes is forbidden: User \"system:serviceaccount:xxx\" cannot list resource \"nodes\" in API group \"\" at the cluster scope\",\"reason\":\"Forbidden\",\"details\":{\"kind\":\"nodes\"},\"code\":403}");

target.LogDebug(ex.Message);
target.LogTrace(ex.ToString());
}
}
Loading