Self-Diagnostics: include datetimestamp in filename (#2325)
* include datetimestamp in self-diagnostics filename * come review comments * update readme * update readme * Update Readme.md
This commit is contained in:
Родитель
c68a4f4d83
Коммит
317786702e
|
@ -15,15 +15,16 @@
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MemoryMappedFileHandler_Success()
|
public void MemoryMappedFileHandler_Success()
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName) + "."
|
string filePath;
|
||||||
+ Process.GetCurrentProcess().Id + ".log";
|
|
||||||
var fileSize = 1024;
|
var fileSize = 1024;
|
||||||
using (var handler = new MemoryMappedFileHandler())
|
using (var handler = new MemoryMappedFileHandler())
|
||||||
{
|
{
|
||||||
handler.CreateLogFile(".", fileSize);
|
handler.CreateLogFile(".", fileSize);
|
||||||
|
|
||||||
|
filePath = handler.CurrentFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
var actualBytes = ReadFile(fileName, MessageOnNewFile.Length);
|
var actualBytes = ReadFile(filePath, MessageOnNewFile.Length);
|
||||||
|
|
||||||
CollectionAssert.AreEqual(MessageOnNewFile, actualBytes);
|
CollectionAssert.AreEqual(MessageOnNewFile, actualBytes);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +37,8 @@
|
||||||
var messageToOverflow = Encoding.UTF8.GetBytes("1234567");
|
var messageToOverflow = Encoding.UTF8.GetBytes("1234567");
|
||||||
var expectedBytesAtEnd = Encoding.UTF8.GetBytes("1234");
|
var expectedBytesAtEnd = Encoding.UTF8.GetBytes("1234");
|
||||||
var expectedBytesAtStart = Encoding.UTF8.GetBytes("567cessfully opened file.\n");
|
var expectedBytesAtStart = Encoding.UTF8.GetBytes("567cessfully opened file.\n");
|
||||||
|
string filePath;
|
||||||
|
|
||||||
using (var handler = new MemoryMappedFileHandler())
|
using (var handler = new MemoryMappedFileHandler())
|
||||||
{
|
{
|
||||||
handler.CreateLogFile(".", fileSize);
|
handler.CreateLogFile(".", fileSize);
|
||||||
|
@ -43,20 +46,20 @@
|
||||||
handler.Write(buffer, fileSize - MessageOnNewFile.Length - expectedBytesAtEnd.Length);
|
handler.Write(buffer, fileSize - MessageOnNewFile.Length - expectedBytesAtEnd.Length);
|
||||||
|
|
||||||
handler.Write(messageToOverflow, messageToOverflow.Length);
|
handler.Write(messageToOverflow, messageToOverflow.Length);
|
||||||
|
|
||||||
|
filePath = handler.CurrentFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName) + "."
|
var actualBytes = ReadFile(filePath, buffer.Length);
|
||||||
+ Process.GetCurrentProcess().Id + ".log";
|
|
||||||
var actualBytes = ReadFile(fileName, buffer.Length);
|
|
||||||
|
|
||||||
CollectionAssert.AreEqual(expectedBytesAtStart, SubArray(actualBytes, 0, expectedBytesAtStart.Length));
|
CollectionAssert.AreEqual(expectedBytesAtStart, SubArray(actualBytes, 0, expectedBytesAtStart.Length));
|
||||||
CollectionAssert.AreEqual(expectedBytesAtEnd, SubArray(actualBytes, actualBytes.Length - expectedBytesAtEnd.Length, expectedBytesAtEnd.Length));
|
CollectionAssert.AreEqual(expectedBytesAtEnd, SubArray(actualBytes, actualBytes.Length - expectedBytesAtEnd.Length, expectedBytesAtEnd.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] ReadFile(string fileName, int byteCount)
|
private static byte[] ReadFile(string filePath, int byteCount)
|
||||||
{
|
{
|
||||||
byte[] actualBytes = new byte[byteCount];
|
byte[] actualBytes = new byte[byteCount];
|
||||||
using (var file = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
using (var file = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
{
|
{
|
||||||
file.Read(actualBytes, 0, byteCount);
|
file.Read(actualBytes, 0, byteCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,10 @@
|
||||||
// Emitting event of EventLevel.Warning
|
// Emitting event of EventLevel.Warning
|
||||||
CoreEventSource.Log.OperationIsNullWarning();
|
CoreEventSource.Log.OperationIsNullWarning();
|
||||||
|
|
||||||
|
var filePath = configRefresher.CurrentFilePath;
|
||||||
|
|
||||||
int bufferSize = 512;
|
int bufferSize = 512;
|
||||||
byte[] actualBytes = ReadFile(bufferSize);
|
byte[] actualBytes = ReadFile(filePath, bufferSize);
|
||||||
string logText = Encoding.UTF8.GetString(actualBytes);
|
string logText = Encoding.UTF8.GetString(actualBytes);
|
||||||
Assert.IsTrue(logText.StartsWith(MessageOnNewFileString));
|
Assert.IsTrue(logText.StartsWith(MessageOnNewFileString));
|
||||||
|
|
||||||
|
@ -52,8 +54,10 @@
|
||||||
// Emitting event of EventLevel.Error
|
// Emitting event of EventLevel.Error
|
||||||
CoreEventSource.Log.InvalidOperationToStopError();
|
CoreEventSource.Log.InvalidOperationToStopError();
|
||||||
|
|
||||||
|
var filePath = configRefresher.CurrentFilePath;
|
||||||
|
|
||||||
int bufferSize = 512;
|
int bufferSize = 512;
|
||||||
byte[] actualBytes = ReadFile(bufferSize);
|
byte[] actualBytes = ReadFile(filePath, bufferSize);
|
||||||
string logText = Encoding.UTF8.GetString(actualBytes);
|
string logText = Encoding.UTF8.GetString(actualBytes);
|
||||||
Assert.IsTrue(logText.StartsWith(MessageOnNewFileString));
|
Assert.IsTrue(logText.StartsWith(MessageOnNewFileString));
|
||||||
|
|
||||||
|
@ -77,12 +81,9 @@
|
||||||
return logLine.Substring(timestampPrefixLength);
|
return logLine.Substring(timestampPrefixLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] ReadFile(int byteCount)
|
private static byte[] ReadFile(string filePath, int byteCount)
|
||||||
{
|
{
|
||||||
var outputFileName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName) + "."
|
using (var file = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
+ Process.GetCurrentProcess().Id + ".log";
|
|
||||||
var outputFilePath = Path.Combine(".", outputFileName);
|
|
||||||
using (var file = File.Open(outputFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
{
|
{
|
||||||
byte[] actualBytes = new byte[byteCount];
|
byte[] actualBytes = new byte[byteCount];
|
||||||
file.Read(actualBytes, 0, byteCount);
|
file.Read(actualBytes, 0, byteCount);
|
||||||
|
|
|
@ -2,6 +2,7 @@ namespace Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.Sel
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.MemoryMappedFiles;
|
using System.IO.MemoryMappedFiles;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -38,6 +39,8 @@ namespace Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.Sel
|
||||||
|
|
||||||
public int LogFileSize { get => this.logFileSize; private set => this.logFileSize = value; }
|
public int LogFileSize { get => this.logFileSize; private set => this.logFileSize = value; }
|
||||||
|
|
||||||
|
public string CurrentFilePath => this.underlyingFileStreamForMemoryMappedFile?.Name;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a log file. If the file already exists, it will be overwritten.
|
/// Create a log file. If the file already exists, it will be overwritten.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -48,8 +51,7 @@ namespace Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.Sel
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(logDirectory);
|
Directory.CreateDirectory(logDirectory);
|
||||||
var fileName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName) + "."
|
var fileName = GenerateFileName();
|
||||||
+ Process.GetCurrentProcess().Id + ".log";
|
|
||||||
var filePath = Path.Combine(logDirectory, fileName);
|
var filePath = Path.Combine(logDirectory, fileName);
|
||||||
|
|
||||||
// Because the API [MemoryMappedFile.CreateFromFile][1](the string version) behaves differently on
|
// Because the API [MemoryMappedFile.CreateFromFile][1](the string version) behaves differently on
|
||||||
|
@ -162,6 +164,17 @@ namespace Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.Sel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GenerateFileName()
|
||||||
|
{
|
||||||
|
var dateTimeStamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
var currentProcess = Process.GetCurrentProcess();
|
||||||
|
var processFileName = Path.GetFileName(currentProcess.MainModule.FileName);
|
||||||
|
var processId = currentProcess.Id;
|
||||||
|
|
||||||
|
return $"{dateTimeStamp}.{processFileName}.{processId}.log";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to get the log stream which is seeked to the position where the next line of log should be written.
|
/// Try to get the log stream which is seeked to the position where the next line of log should be written.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
this.worker = Task.Run(() => this.Worker(this.cancellationTokenSource.Token), this.cancellationTokenSource.Token);
|
this.worker = Task.Run(() => this.Worker(this.cancellationTokenSource.Token), this.cancellationTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string CurrentFilePath => this.memoryMappedFileHandler.CurrentFilePath;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,7 +122,8 @@ As of version 2.18.0, this SDK ships a "self-diagnostics feature" which captures
|
||||||
|
|
||||||
The self-diagnostics feature can be enabled/changed/disabled while the process is running.
|
The self-diagnostics feature can be enabled/changed/disabled while the process is running.
|
||||||
The SDK will attempt to read the configuration file every 10 seconds, using a non-exclusive read-only mode.
|
The SDK will attempt to read the configuration file every 10 seconds, using a non-exclusive read-only mode.
|
||||||
The SDK will create or overwrite a file with new logs according to the configuration.
|
The SDK will create or overwrite a file with new logs according to the configuration.
|
||||||
|
This file will not exceed the configured max size and will be circularly overwritten.
|
||||||
|
|
||||||
#### Configuration
|
#### Configuration
|
||||||
|
|
||||||
|
@ -150,13 +151,15 @@ Example:
|
||||||
|
|
||||||
#### Configuration Parameters
|
#### Configuration Parameters
|
||||||
|
|
||||||
A `FileSize`-KiB log file named as `ExecutableName.ProcessId.log` (e.g. `foobar.exe.12345.log`) will be generated at the specified directory `LogDirectory`.
|
A `FileSize`-KiB log file named as `YearMonthDay-HourMinuteSecond.ExecutableName.ProcessId.log` (e.g. `20010101-120000.foobar.exe.12345.log`) will be generated at the specified directory `LogDirectory`.
|
||||||
|
The file name starts with the `DateTime.UtcNow` timestamp of when the file was created.
|
||||||
|
|
||||||
1. `LogDirectory` is the directory where the output log file will be stored.
|
1. `LogDirectory` is the directory where the output log file will be stored.
|
||||||
It can be an absolute path or a relative path to the current directory.
|
It can be an absolute path or a relative path to the current directory.
|
||||||
|
|
||||||
2. `FileSize` is a positive integer, which specifies the log file size in [KiB](https://en.wikipedia.org/wiki/Kibibyte).
|
2. `FileSize` is a positive integer, which specifies the log file size in [KiB](https://en.wikipedia.org/wiki/Kibibyte).
|
||||||
This value must be between 1 MiB and 128 MiB (inclusive), or it will be rounded to the closest upper or lower limit.
|
This value must be between 1 MiB and 128 MiB (inclusive), or it will be rounded to the closest upper or lower limit.
|
||||||
|
The log file will never exceed this configured size, and will be circularly rewriten.
|
||||||
|
|
||||||
3. `LogLevel` is the lowest level of the events to be captured.
|
3. `LogLevel` is the lowest level of the events to be captured.
|
||||||
This value must match one of the [fields](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlevel#fields) of the `EventLevel` enum.
|
This value must match one of the [fields](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlevel#fields) of the `EventLevel` enum.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче