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
2 changes: 1 addition & 1 deletion Documentation/Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ We can collect logs from trackers through an enviroment variable
set COVERLET_ENABLETRACKERLOG=1
```
When enabled, tracking event will be collected in log file near to module location.
File name will be something like `moduleName.dll_tracker.txt`
File name will be something like `moduleName.dll_tracker.txt` and files with detailed hits will be in a folder named `TrackersHitsLog`.

## Enable msbuild task instrumentation debugging

Expand Down
44 changes: 33 additions & 11 deletions src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
Expand All @@ -20,7 +21,7 @@ internal static class ModuleTrackerTemplate
public static string HitsFilePath;
public static int[] HitsArray;
public static bool SingleHit;
private static bool _enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) ? result == 1 : false;
private static readonly bool _enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) ? result == 1 : false;

static ModuleTrackerTemplate()
{
Expand Down Expand Up @@ -116,6 +117,8 @@ public static void UnloadModule(object sender, EventArgs e)
using (var bw = new BinaryWriter(fs))
{
int hitsLength = br.ReadInt32();
WriteLog($"Current hits found '{hitsLength}'");

if (hitsLength != hitsArray.Length)
{
throw new InvalidOperationException(
Expand All @@ -134,6 +137,8 @@ public static void UnloadModule(object sender, EventArgs e)
}
}

WriteHits();

// On purpose this is not under a try-finally: it is better to have an exception if there was any error writing the hits file
// this case is relevant when instrumenting corelib since multiple processes can be running against the same instrumented dll.
mutex.ReleaseMutex();
Expand All @@ -147,21 +152,38 @@ public static void UnloadModule(object sender, EventArgs e)
}
}

private static void WriteLog(string logText)
private static void WriteHits()
{
if (_enableLog)
{
try
{
// We don't set path as global var to keep benign possible errors inside try/catch
// I'm not sure that location will be ok in every scenario
string location = Assembly.GetExecutingAssembly().Location;
File.AppendAllText(Path.Combine(Path.GetDirectoryName(location), Path.GetFileName(location) + "_tracker.txt"), $"[{DateTime.UtcNow} {Thread.CurrentThread.ManagedThreadId}]{logText}{Environment.NewLine}");
}
catch
Assembly currentAssembly = Assembly.GetExecutingAssembly();
DirectoryInfo location = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(currentAssembly.Location), "TrackersHitsLog"));
location.Create();
string logFile = Path.Combine(location.FullName, $"{Path.GetFileName(currentAssembly.Location)}_{DateTime.UtcNow.Ticks}_{Process.GetCurrentProcess().Id}.txt");
using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
using (var log = new FileStream(logFile, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
using (var logWriter = new StreamWriter(log))
using (var br = new BinaryReader(fs))
{
// do nothing if log fail
int hitsLength = br.ReadInt32();
for (int i = 0; i < hitsLength; ++i)
{
logWriter.WriteLine($"{i},{br.ReadInt32()}");
}
}

File.AppendAllText(logFile, "Hits flushed");
}
}

private static void WriteLog(string logText)
{
if (_enableLog)
{
// We don't set path as global var to keep benign possible errors inside try/catch
// I'm not sure that location will be ok in every scenario
string location = Assembly.GetExecutingAssembly().Location;
File.AppendAllText(Path.Combine(Path.GetDirectoryName(location), Path.GetFileName(location) + "_tracker.txt"), $"[{DateTime.UtcNow} P:{Process.GetCurrentProcess().Id} T:{Thread.CurrentThread.ManagedThreadId}]{logText}{Environment.NewLine}");
}
}
}
Expand Down