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

Added support to read diagnostics config from the path defined in environment variable #2769

Merged
merged 14 commits into from
Oct 17, 2023
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
namespace Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.SelfDiagnostics
{
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;

[TestClass]
public class SelfDiagnosticsConfigRefresherTest
Expand Down Expand Up @@ -74,6 +77,52 @@ public void SelfDiagnosticsConfigRefresher_CaptureAsConfigured()
}
}

[TestMethod]
public void SelfDiagnosticsConfigRefresher_ReadFromEnviornmentVar()
{

var key = "APPLICATIONINSIGHTS_LOG_DIAGNOSTICS";
var val = string.Empty;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
val = @"C:\home\LogFiles\SelfDiagnostics";
}
else
{
val = "/home/user/LogFiles/SelfDiagnostics";
}
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved

Environment.SetEnvironmentVariable(key, val);

try
{
CreateConfigFile(false);
using (var configRefresher = new SelfDiagnosticsConfigRefresher())
{
// Emitting event of EventLevel.Error
CoreEventSource.Log.InvalidOperationToStopError();
var filePath = configRefresher.CurrentFilePath;

int bufferSize = 512;
byte[] actualBytes = ReadFile(filePath, bufferSize);
string logText = Encoding.UTF8.GetString(actualBytes);
Assert.IsTrue(logText.StartsWith(MessageOnNewFileString));

// The event was captured
string logLine = logText.Substring(MessageOnNewFileString.Length);
string logMessage = ParseLogMessage(logLine);
string expectedMessage = "Operation to stop does not match the current operation. Telemetry is not tracked.";
Assert.IsTrue(logMessage.StartsWith(expectedMessage));
}
}
finally
{
Environment.SetEnvironmentVariable(key, null);
Platform.PlatformSingleton.Current = null; // Force reinitialization in future tests so that new environment variables will be loaded.
CleanupConfigFile();
}
}

private static string ParseLogMessage(string logLine)
{
int timestampPrefixLength = "2020-08-14T20:33:24.4788109Z:".Length;
Expand All @@ -91,13 +140,25 @@ private static byte[] ReadFile(string filePath, int byteCount)
}
}

private static void CreateConfigFile()
private static void CreateConfigFile(bool userDefinedLogDirectory = true)
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved
{
string configJson = @"{
string configJson = string.Empty;
if (!userDefinedLogDirectory)
{
configJson = @"{
""FileSize"": 1024,
""LogLevel"": ""Error""
}";
}
else
{
configJson = @"{
""LogDirectory"": ""."",
""FileSize"": 1024,
""LogLevel"": ""Error""
}";
}

using (FileStream file = File.Open(ConfigFilePath, FileMode.Create, FileAccess.Write))
{
byte[] configBytes = Encoding.UTF8.GetBytes(configJson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.ApplicationInsights.Extensibility.Implementation.Platform;

internal class SelfDiagnosticsConfigParser
{
public const string ConfigFileName = "ApplicationInsightsDiagnostics.json";
private const int FileSizeLowerLimit = 1024; // Lower limit for log file size in KB: 1MB
private const int FileSizeUpperLimit = 128 * 1024; // Upper limit for log file size in KB: 128MB

private const string LogDiagnosticsEnvironmentVariable = "APPLICATIONINSIGHTS_LOG_DIAGNOSTICS";

/// <summary>
/// ConfigBufferSize is the maximum bytes of config file that will be read.
/// </summary>
Expand Down Expand Up @@ -40,16 +43,23 @@ public bool TryGetConfiguration(out string logDirectory, out int fileSizeInKB, o
{
var configFilePath = ConfigFileName;

// First check using current working directory
if (!File.Exists(configFilePath))
// First, check whether the enviornment variable was set.
if (PlatformSingleton.Current.TryGetEnvironmentVariable(LogDiagnosticsEnvironmentVariable, out string logDiagnosticsPath))
{
configFilePath = Path.Combine(logDiagnosticsPath, ConfigFileName);
logDirectory = logDiagnosticsPath;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the blank space before else if.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to have a blank line before comment?

// Second, check using current working directory.
else if (!File.Exists(configFilePath))
{
#if NET452
configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFileName);
#else
configFilePath = Path.Combine(AppContext.BaseDirectory, ConfigFileName);
#endif

// Second check using application base directory
// Third, check using application base directory.
if (!File.Exists(configFilePath))
{
return false;
Expand All @@ -67,7 +77,8 @@ public bool TryGetConfiguration(out string logDirectory, out int fileSizeInKB, o

file.Read(buffer, 0, buffer.Length);
string configJson = Encoding.UTF8.GetString(buffer);
if (!TryParseLogDirectory(configJson, out logDirectory))

if (logDirectory == null && !TryParseLogDirectory(configJson, out logDirectory))
{
return false;
}
Expand Down