test passes
This commit is contained in:
parent
7a3a2b558b
commit
f6cd9db408
@ -1,20 +1,24 @@
|
|||||||
namespace OverwatchTranscript
|
using Logging;
|
||||||
|
|
||||||
|
namespace OverwatchTranscript
|
||||||
{
|
{
|
||||||
public class BucketSet
|
public class BucketSet
|
||||||
{
|
{
|
||||||
private const int numberOfActiveBuckets = 5;
|
private const int numberOfActiveBuckets = 5;
|
||||||
private readonly object _counterLock = new object();
|
private readonly object _counterLock = new object();
|
||||||
private int pendingAdds = 0;
|
private int pendingAdds = 0;
|
||||||
|
private readonly ILog log;
|
||||||
|
private readonly string workingDir;
|
||||||
private readonly object _bucketLock = new object();
|
private readonly object _bucketLock = new object();
|
||||||
private readonly List<EventBucket> fullBuckets = new List<EventBucket>();
|
private readonly List<EventBucket> fullBuckets = new List<EventBucket>();
|
||||||
private readonly List<EventBucket> activeBuckets = new List<EventBucket>();
|
private readonly List<EventBucket> activeBuckets = new List<EventBucket>();
|
||||||
private int activeBucketIndex = 0;
|
private int activeBucketIndex = 0;
|
||||||
private bool closed = false;
|
private bool closed = false;
|
||||||
private readonly string workingDir;
|
private string internalErrors = string.Empty;
|
||||||
|
|
||||||
public BucketSet(string workingDir)
|
public BucketSet(ILog log, string workingDir)
|
||||||
{
|
{
|
||||||
|
this.log = log;
|
||||||
this.workingDir = workingDir;
|
this.workingDir = workingDir;
|
||||||
|
|
||||||
for (var i = 0; i < numberOfActiveBuckets;i++)
|
for (var i = 0; i < numberOfActiveBuckets;i++)
|
||||||
@ -23,8 +27,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Error { get; private set; } = string.Empty;
|
|
||||||
|
|
||||||
public void Add(DateTime utc, object payload)
|
public void Add(DateTime utc, object payload)
|
||||||
{
|
{
|
||||||
if (closed) throw new Exception("Buckets already closed!");
|
if (closed) throw new Exception("Buckets already closed!");
|
||||||
@ -32,20 +34,24 @@
|
|||||||
Task.Run(() => AddInternal(utc, payload));
|
Task.Run(() => AddInternal(utc, payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty()
|
|
||||||
{
|
|
||||||
return fullBuckets.All(b => b.Count == 0) && activeBuckets.All(b => b.Count == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFinalizedBucket[] FinalizeBuckets()
|
public IFinalizedBucket[] FinalizeBuckets()
|
||||||
{
|
{
|
||||||
closed = true;
|
closed = true;
|
||||||
WaitForZeroPending();
|
WaitForZeroPending();
|
||||||
|
|
||||||
|
if (IsEmpty()) throw new Exception("No entries have been added.");
|
||||||
|
if (!string.IsNullOrEmpty(internalErrors)) throw new Exception(internalErrors);
|
||||||
|
|
||||||
var buckets = fullBuckets.Concat(activeBuckets).ToArray();
|
var buckets = fullBuckets.Concat(activeBuckets).ToArray();
|
||||||
|
log.Debug($"Finalizing {buckets.Length} buckets...");
|
||||||
return buckets.Select(b => b.FinalizeBucket()).ToArray();
|
return buckets.Select(b => b.FinalizeBucket()).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsEmpty()
|
||||||
|
{
|
||||||
|
return fullBuckets.All(b => b.Count == 0) && activeBuckets.All(b => b.Count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
private void AddInternal(DateTime utc, object payload)
|
private void AddInternal(DateTime utc, object payload)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -67,7 +73,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Error += ex.ToString();
|
internalErrors += ex.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +81,7 @@
|
|||||||
{
|
{
|
||||||
lock (_bucketLock)
|
lock (_bucketLock)
|
||||||
{
|
{
|
||||||
activeBuckets.Add(new EventBucket(Path.Combine(workingDir, Guid.NewGuid().ToString())));
|
activeBuckets.Add(new EventBucket(log, Path.Combine(workingDir, Guid.NewGuid().ToString())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +90,7 @@
|
|||||||
lock (_counterLock)
|
lock (_counterLock)
|
||||||
{
|
{
|
||||||
pendingAdds++;
|
pendingAdds++;
|
||||||
|
log.Debug("(+) Pending: " + pendingAdds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,16 +99,19 @@
|
|||||||
lock (_counterLock)
|
lock (_counterLock)
|
||||||
{
|
{
|
||||||
pendingAdds--;
|
pendingAdds--;
|
||||||
if (pendingAdds < 0) Error += "Pending less than zero";
|
if (pendingAdds < 0) internalErrors += "Pending less than zero";
|
||||||
|
log.Debug("(-) Pending: " + pendingAdds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WaitForZeroPending()
|
private void WaitForZeroPending()
|
||||||
{
|
{
|
||||||
|
log.Debug("Wait for zero pending.");
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
lock (_counterLock)
|
lock (_counterLock)
|
||||||
{
|
{
|
||||||
|
log.Debug("(wait) Pending: " + pendingAdds);
|
||||||
if (pendingAdds == 0) return;
|
if (pendingAdds == 0) return;
|
||||||
}
|
}
|
||||||
Thread.Sleep(10);
|
Thread.Sleep(10);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace OverwatchTranscript
|
namespace OverwatchTranscript
|
||||||
{
|
{
|
||||||
@ -9,24 +10,22 @@ namespace OverwatchTranscript
|
|||||||
|
|
||||||
private readonly object _lock = new object();
|
private readonly object _lock = new object();
|
||||||
private bool closed = false;
|
private bool closed = false;
|
||||||
|
private readonly ILog log;
|
||||||
private readonly string bucketFile;
|
private readonly string bucketFile;
|
||||||
private readonly List<EventBucketEntry> buffer = new List<EventBucketEntry>();
|
private readonly List<EventBucketEntry> buffer = new List<EventBucketEntry>();
|
||||||
private EventBucketEntry? topEntry;
|
private EventBucketEntry? topEntry;
|
||||||
|
|
||||||
public EventBucket(string bucketFile)
|
public EventBucket(ILog log, string bucketFile)
|
||||||
{
|
{
|
||||||
|
this.log = log;
|
||||||
this.bucketFile = bucketFile;
|
this.bucketFile = bucketFile;
|
||||||
if (File.Exists(bucketFile)) throw new Exception("Already exists");
|
if (File.Exists(bucketFile)) throw new Exception("Already exists");
|
||||||
|
|
||||||
EarliestUtc = DateTime.MaxValue;
|
log.Debug("Bucket open: " + bucketFile);
|
||||||
LatestUtc = DateTime.MinValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count { get; private set; }
|
public int Count { get; private set; }
|
||||||
public bool IsFull { get; private set; }
|
public bool IsFull { get; private set; }
|
||||||
public DateTime EarliestUtc { get; private set; }
|
|
||||||
public DateTime LatestUtc { get; private set; }
|
|
||||||
|
|
||||||
public void Add(DateTime utc, object payload)
|
public void Add(DateTime utc, object payload)
|
||||||
{
|
{
|
||||||
@ -34,7 +33,7 @@ namespace OverwatchTranscript
|
|||||||
{
|
{
|
||||||
if (closed) throw new Exception("Already closed");
|
if (closed) throw new Exception("Already closed");
|
||||||
AddToBuffer(utc, payload);
|
AddToBuffer(utc, payload);
|
||||||
BufferToFile();
|
BufferToFile(emptyBuffer: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,9 +42,10 @@ namespace OverwatchTranscript
|
|||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
closed = true;
|
closed = true;
|
||||||
BufferToFile();
|
BufferToFile(emptyBuffer: true);
|
||||||
SortFileByTimestamps();
|
SortFileByTimestamps();
|
||||||
}
|
}
|
||||||
|
log.Debug($"Finalized bucket with {Count} entries");
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +71,11 @@ namespace OverwatchTranscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"EventBucket: " + Count;
|
||||||
|
}
|
||||||
|
|
||||||
private void AddToBuffer(DateTime utc, object payload)
|
private void AddToBuffer(DateTime utc, object payload)
|
||||||
{
|
{
|
||||||
var typeName = payload.GetType().FullName;
|
var typeName = payload.GetType().FullName;
|
||||||
@ -87,17 +92,15 @@ namespace OverwatchTranscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (utc < EarliestUtc) EarliestUtc = utc;
|
|
||||||
if (utc > LatestUtc) LatestUtc = utc;
|
|
||||||
Count++;
|
Count++;
|
||||||
IsFull = Count > MaxCount;
|
IsFull = Count > MaxCount;
|
||||||
|
|
||||||
buffer.Add(entry);
|
buffer.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BufferToFile()
|
private void BufferToFile(bool emptyBuffer)
|
||||||
{
|
{
|
||||||
if (buffer.Count > MaxBuffer)
|
if (emptyBuffer || buffer.Count > MaxBuffer)
|
||||||
{
|
{
|
||||||
using var file = File.Open(bucketFile, FileMode.Append);
|
using var file = File.Open(bucketFile, FileMode.Append);
|
||||||
using var writer = new StreamWriter(file);
|
using var writer = new StreamWriter(file);
|
||||||
@ -105,6 +108,7 @@ namespace OverwatchTranscript
|
|||||||
{
|
{
|
||||||
writer.WriteLine(JsonConvert.SerializeObject(entry));
|
writer.WriteLine(JsonConvert.SerializeObject(entry));
|
||||||
}
|
}
|
||||||
|
log.Debug($"Bucket wrote {buffer.Count} entries to file.");
|
||||||
buffer.Clear();
|
buffer.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +124,7 @@ namespace OverwatchTranscript
|
|||||||
File.Delete(bucketFile);
|
File.Delete(bucketFile);
|
||||||
File.WriteAllLines(bucketFile, entries.Select(JsonConvert.SerializeObject));
|
File.WriteAllLines(bucketFile, entries.Select(JsonConvert.SerializeObject));
|
||||||
|
|
||||||
topEntry = entries.First();
|
topEntry = entries.FirstOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +132,6 @@ namespace OverwatchTranscript
|
|||||||
{
|
{
|
||||||
int Count { get; }
|
int Count { get; }
|
||||||
bool IsFull { get; }
|
bool IsFull { get; }
|
||||||
DateTime EarliestUtc { get; }
|
|
||||||
DateTime LatestUtc { get; }
|
|
||||||
EventBucketEntry? ViewTopEntry();
|
EventBucketEntry? ViewTopEntry();
|
||||||
void PopTopEntry();
|
void PopTopEntry();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ namespace OverwatchTranscript
|
|||||||
public OverwatchMomentReference[] Build(IFinalizedBucket[] buckets)
|
public OverwatchMomentReference[] Build(IFinalizedBucket[] buckets)
|
||||||
{
|
{
|
||||||
var result = new List<OverwatchMomentReference>();
|
var result = new List<OverwatchMomentReference>();
|
||||||
|
|
||||||
var currentBuilder = new Builder(workingDir);
|
var currentBuilder = new Builder(workingDir);
|
||||||
|
|
||||||
while (EntriesRemaining(buckets))
|
while (EntriesRemaining(buckets))
|
||||||
@ -31,6 +30,11 @@ namespace OverwatchTranscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentBuilder.NumberOfMoments > 0)
|
||||||
|
{
|
||||||
|
result.Add(currentBuilder.Build());
|
||||||
|
}
|
||||||
|
|
||||||
return result.ToArray();
|
return result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,4 +10,8 @@
|
|||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Logging\Logging.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
namespace OverwatchTranscript
|
using Logging;
|
||||||
|
|
||||||
|
namespace OverwatchTranscript
|
||||||
{
|
{
|
||||||
public static class Transcript
|
public static class Transcript
|
||||||
{
|
{
|
||||||
public static ITranscriptWriter NewWriter()
|
public static ITranscriptWriter NewWriter(ILog log)
|
||||||
{
|
{
|
||||||
return new TranscriptWriter(NewWorkDir());
|
log = new LogPrefixer(log, "(TranscriptWriter) ");
|
||||||
|
return new TranscriptWriter(log, NewWorkDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ITranscriptReader NewReader(string transcriptFile)
|
public static ITranscriptReader NewReader(string transcriptFile)
|
||||||
|
@ -31,6 +31,7 @@ namespace OverwatchTranscript
|
|||||||
private long momentCounter;
|
private long momentCounter;
|
||||||
private readonly object queueLock = new object();
|
private readonly object queueLock = new object();
|
||||||
private readonly List<OverwatchMoment> queue = new List<OverwatchMoment>();
|
private readonly List<OverwatchMoment> queue = new List<OverwatchMoment>();
|
||||||
|
private readonly Task queueFiller;
|
||||||
|
|
||||||
public TranscriptReader(string workingDir, string inputFilename)
|
public TranscriptReader(string workingDir, string inputFilename)
|
||||||
{
|
{
|
||||||
@ -44,6 +45,8 @@ namespace OverwatchTranscript
|
|||||||
|
|
||||||
model = LoadModel(inputFilename);
|
model = LoadModel(inputFilename);
|
||||||
reader = new MomentReader(model, workingDir);
|
reader = new MomentReader(model, workingDir);
|
||||||
|
|
||||||
|
queueFiller = Task.Run(FillQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OverwatchCommonHeader Header
|
public OverwatchCommonHeader Header
|
||||||
@ -98,21 +101,28 @@ namespace OverwatchTranscript
|
|||||||
{
|
{
|
||||||
CheckClosed();
|
CheckClosed();
|
||||||
OverwatchMoment moment = null!;
|
OverwatchMoment moment = null!;
|
||||||
|
OverwatchMoment? next = null;
|
||||||
lock (queueLock)
|
lock (queueLock)
|
||||||
{
|
{
|
||||||
if (queue.Count == 0) return;
|
if (queue.Count == 0) return;
|
||||||
moment = queue[0];
|
moment = queue[0];
|
||||||
|
if (queue.Count > 1) next = queue[1];
|
||||||
|
|
||||||
queue.RemoveAt(0);
|
queue.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivateMoment(moment);
|
var duration = GetMomentDuration(moment, next);
|
||||||
|
ActivateMoment(moment, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
CheckClosed();
|
CheckClosed();
|
||||||
Directory.Delete(workingDir, true);
|
|
||||||
closed = true;
|
closed = true;
|
||||||
|
|
||||||
|
queueFiller.Wait();
|
||||||
|
|
||||||
|
Directory.Delete(workingDir, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action<ActivateMoment, string> CreateEventAction<T>(Action<ActivateEvent<T>> handler)
|
private Action<ActivateMoment, string> CreateEventAction<T>(Action<ActivateEvent<T>> handler)
|
||||||
@ -123,17 +133,37 @@ namespace OverwatchTranscript
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeSpan? GetMomentDuration()
|
private void FillQueue()
|
||||||
{
|
{
|
||||||
if (current == null) return null;
|
while (true)
|
||||||
if (next == null) return null;
|
{
|
||||||
|
if (closed) return;
|
||||||
|
|
||||||
return next.Utc - current.Utc;
|
lock (queueLock)
|
||||||
|
{
|
||||||
|
while (queue.Count < 100)
|
||||||
|
{
|
||||||
|
var moment = reader.Next();
|
||||||
|
if (moment == null) return;
|
||||||
|
queue.Add(moment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ActivateMoment(OverwatchMoment moment, TimeSpan? duration, long momentIndex)
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimeSpan? GetMomentDuration(OverwatchMoment moment, OverwatchMoment? next)
|
||||||
{
|
{
|
||||||
var m = new ActivateMoment(moment.Utc, duration, momentIndex);
|
if (moment == null) return null;
|
||||||
|
if (next == null) return null;
|
||||||
|
|
||||||
|
return next.Utc - moment.Utc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActivateMoment(OverwatchMoment moment, TimeSpan? duration)
|
||||||
|
{
|
||||||
|
var m = new ActivateMoment(moment.Utc, duration, momentCounter);
|
||||||
|
|
||||||
lock (handlersLock)
|
lock (handlersLock)
|
||||||
{
|
{
|
||||||
@ -144,6 +174,8 @@ namespace OverwatchTranscript
|
|||||||
ActivateEventHandlers(m, @event);
|
ActivateEventHandlers(m, @event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
momentCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ActivateMomentHandlers(ActivateMoment m)
|
private void ActivateMomentHandlers(ActivateMoment m)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
|
||||||
namespace OverwatchTranscript
|
namespace OverwatchTranscript
|
||||||
@ -19,14 +20,16 @@ namespace OverwatchTranscript
|
|||||||
private readonly string artifactsFolder;
|
private readonly string artifactsFolder;
|
||||||
private readonly Dictionary<string, string> header = new Dictionary<string, string>();
|
private readonly Dictionary<string, string> header = new Dictionary<string, string>();
|
||||||
private readonly BucketSet bucketSet;
|
private readonly BucketSet bucketSet;
|
||||||
|
private readonly ILog log;
|
||||||
private readonly string workingDir;
|
private readonly string workingDir;
|
||||||
private bool closed;
|
private bool closed;
|
||||||
|
|
||||||
public TranscriptWriter(string workingDir)
|
public TranscriptWriter(ILog log, string workingDir)
|
||||||
{
|
{
|
||||||
closed = false;
|
closed = false;
|
||||||
|
this.log = log;
|
||||||
this.workingDir = workingDir;
|
this.workingDir = workingDir;
|
||||||
bucketSet = new BucketSet(workingDir);
|
bucketSet = new BucketSet(log, workingDir);
|
||||||
builder = new MomentReferenceBuilder(workingDir);
|
builder = new MomentReferenceBuilder(workingDir);
|
||||||
transcriptFile = Path.Combine(workingDir, TranscriptConstants.TranscriptFilename);
|
transcriptFile = Path.Combine(workingDir, TranscriptConstants.TranscriptFilename);
|
||||||
artifactsFolder = Path.Combine(workingDir, TranscriptConstants.ArtifactFolderName);
|
artifactsFolder = Path.Combine(workingDir, TranscriptConstants.ArtifactFolderName);
|
||||||
@ -61,12 +64,6 @@ namespace OverwatchTranscript
|
|||||||
|
|
||||||
public void Write(string outputFilename)
|
public void Write(string outputFilename)
|
||||||
{
|
{
|
||||||
if (bucketSet.IsEmpty()) throw new Exception("No entries added.");
|
|
||||||
if (!string.IsNullOrEmpty(bucketSet.Error))
|
|
||||||
{
|
|
||||||
throw new Exception("Exceptions in BucketSet: " + bucketSet.Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckClosed();
|
CheckClosed();
|
||||||
closed = true;
|
closed = true;
|
||||||
|
|
||||||
@ -76,8 +73,10 @@ namespace OverwatchTranscript
|
|||||||
File.WriteAllText(transcriptFile, JsonConvert.SerializeObject(model, Formatting.Indented));
|
File.WriteAllText(transcriptFile, JsonConvert.SerializeObject(model, Formatting.Indented));
|
||||||
|
|
||||||
ZipFile.CreateFromDirectory(workingDir, outputFilename);
|
ZipFile.CreateFromDirectory(workingDir, outputFilename);
|
||||||
|
log.Debug($"Transcript written to {outputFilename}");
|
||||||
|
|
||||||
Directory.Delete(workingDir, true);
|
Directory.Delete(workingDir, true);
|
||||||
|
log.Debug($"Workdir {workingDir} deleted");
|
||||||
}
|
}
|
||||||
|
|
||||||
private OverwatchTranscript CreateModel(OverwatchMomentReference[] momentReferences)
|
private OverwatchTranscript CreateModel(OverwatchMomentReference[] momentReferences)
|
||||||
|
@ -139,7 +139,7 @@ namespace CodexTests
|
|||||||
if (GetTranscriptAttributeOfCurrentTest() == null) return;
|
if (GetTranscriptAttributeOfCurrentTest() == null) return;
|
||||||
|
|
||||||
var log = new LogPrefixer(lifecycle.Log, "(Transcript) ");
|
var log = new LogPrefixer(lifecycle.Log, "(Transcript) ");
|
||||||
var writer = new CodexTranscriptWriter(log, Transcript.NewWriter());
|
var writer = new CodexTranscriptWriter(log, Transcript.NewWriter(log));
|
||||||
Ci.SetCodexHooksProvider(writer);
|
Ci.SetCodexHooksProvider(writer);
|
||||||
writers.Add(lifecycle, writer);
|
writers.Add(lifecycle, writer);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using OverwatchTranscript;
|
using OverwatchTranscript;
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ namespace FrameworkTests.OverwatchTranscript
|
|||||||
|
|
||||||
private void WriteTranscript(string workdir)
|
private void WriteTranscript(string workdir)
|
||||||
{
|
{
|
||||||
var writer = new TranscriptWriter(workdir);
|
var log = new ConsoleLog();
|
||||||
|
var writer = new TranscriptWriter(log, workdir);
|
||||||
|
|
||||||
writer.AddHeader(HeaderKey, new TestHeader
|
writer.AddHeader(HeaderKey, new TestHeader
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user