Skip to content

Commit a503c38

Browse files
committed
Addressing PR issues
1 parent af4a19e commit a503c38

9 files changed

Lines changed: 139 additions & 40 deletions

File tree

IL/Microsoft.Internal.VisualStudio.Shell.Embeddable.il

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
}
66
.assembly Microsoft.Internal.VisualStudio.Shell.Embeddable
77
{
8+
.custom instance void [mscorlib]System.Runtime.InteropServices.ImportedFromTypeLibAttribute::.ctor(string) = { string('Microsoft.Internal.VisualStudio.Shell.Embeddable') }
9+
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = { string('190F8999-290E-4111-AE15-1509B895B58C') }
810
.publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00 07 D1 FA 57 C4 AE D9 F0 A3 2E 84 AA 0F AE FD 0D E9 E8 FD 6A EC 8F 87 FB 03 76 6C 83 4C 99 92 1E B2 3B E7 9A D9 D5 DC C1 DD 9A D2 36 13 21 02 90 0B 72 3C F9 80 95 7F C4 E1 77 10 8F C6 07 77 4F 29 E8 32 0E 92 EA 05 EC E4 E8 21 C0 A5 EF E8 F1 64 5C 4C 0C 93 C1 AB 99 28 5D 62 2C AA 65 2C 1D FA D6 3D 74 5D 6F 2D E5 F1 7E 5E AF 0F C4 96 3D 26 1C 8A 12 43 65 18 20 6D C0 93 34 4D 5A D2 93)
911
.hash algorithm 0x00008004
1012
.ver 16:0:0:0

src/DebugEngineHost.Stub/DebugEngineHost.ref.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,18 @@ public static void Reset()
309309
throw new NotImplementedException();
310310
}
311311

312+
/// <summary>
313+
/// Returns true if the feedback log is currently active
314+
/// </summary>
315+
public static bool IsFeedbackLogEnabled
316+
{
317+
get { throw new NotImplementedException(); }
318+
}
319+
320+
/// <summary>
321+
/// Writes a message to the feedback circular buffer and, if active, to the feedback log file.
322+
/// </summary>
323+
/// <param name="message">The message to write to the feedback log.</param>
312324
public static void WriteFeedbackLog(string message)
313325
{
314326
throw new NotImplementedException();

src/DebugEngineHost.VSCode/HostLogger.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public static void Reset()
5252
s_engineLogChannel = null;
5353
}
5454

55+
public static bool IsFeedbackLogEnabled
56+
{
57+
get { return false; }
58+
}
59+
5560
public static void WriteFeedbackLog(string message)
5661
{
5762
}

src/DebugEngineHost/DebugEngineHost.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
</Reference>
110110
<Reference Include="Microsoft.Internal.VisualStudio.Shell.Embeddable">
111111
<HintPath>$(GeneratedAssembliesDir)Microsoft.Internal.VisualStudio.Shell.Embeddable.dll</HintPath>
112+
<EmbedInteropTypes>true</EmbedInteropTypes>
112113
<Private>false</Private>
113114
</Reference>
114115
</ItemGroup>
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.ComponentModel.Composition;
67
using System.Diagnostics;
78
using System.IO;
8-
using System.Text;
9+
using System.Threading.Tasks;
910
using Microsoft.Internal.VisualStudio.Shell.Embeddable.Feedback;
1011

1112
namespace Microsoft.DebugEngineHost
@@ -15,35 +16,34 @@ public class FeedbackDiagnosticFileProvider : IFeedbackDiagnosticFileProvider
1516
{
1617
public IReadOnlyCollection<string> GetFiles()
1718
{
19+
if (!HostLogger.HasFeedbackEntries)
20+
{
21+
return Array.Empty<string>();
22+
}
23+
1824
string logFileName = HostLogger.GetFeedbackLogFilePath(Process.GetCurrentProcess().Id);
1925

26+
IReadOnlyCollection<string> entries = HostLogger.GetNewFeedbackEntries();
27+
if (entries.Count > 0)
28+
{
29+
_ = Task.Run(() => WriteFeedbackEntries(logFileName, entries));
30+
}
31+
32+
return new[] { logFileName };
33+
}
34+
35+
private static void WriteFeedbackEntries(string logFileName, IReadOnlyCollection<string> entries)
36+
{
2037
try
2138
{
22-
IReadOnlyCollection<string> entries = HostLogger.GetNewFeedbackEntries();
23-
if (entries.Count > 0)
39+
using (StreamWriter logWriter = FeedbackLogBuffer.OpenLogFile(logFileName))
2440
{
25-
using (var fs = new FileStream(logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
26-
using (var logWriter = new StreamWriter(fs, Encoding.UTF8))
27-
{
28-
foreach (string logLine in entries)
29-
{
30-
logWriter.WriteLine(logLine);
31-
}
32-
33-
logWriter.Flush();
34-
}
41+
FeedbackLogBuffer.WriteEntries(logWriter, entries);
3542
}
3643
}
3744
catch
3845
{
3946
}
40-
41-
if (File.Exists(logFileName))
42-
{
43-
return new[] { logFileName };
44-
}
45-
46-
return new string[0];
4747
}
4848
}
4949
}

src/DebugEngineHost/FeedbackLogBuffer.cs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System;
45
using System.Collections.Generic;
6+
using System.IO;
57
using System.Linq;
8+
using System.Text;
69

710
namespace Microsoft.DebugEngineHost
811
{
@@ -19,6 +22,20 @@ internal class FeedbackLogBuffer
1922
private long _lastFlushSequence;
2023
private readonly object _syncObj = new object();
2124

25+
/// <summary>
26+
/// Returns true if no entries have been written since the last flush.
27+
/// </summary>
28+
internal bool IsEmpty
29+
{
30+
get
31+
{
32+
lock (_syncObj)
33+
{
34+
return _writeSequence == _lastFlushSequence;
35+
}
36+
}
37+
}
38+
2239
internal void Write(string logLine)
2340
{
2441
lock (_syncObj)
@@ -50,12 +67,42 @@ internal IReadOnlyCollection<string> FlushNewEntries()
5067

5168
if (newEntryCount <= 0)
5269
{
53-
return new string[0];
70+
return Array.Empty<string>();
5471
}
5572

5673
int skipCount = _logBuffer.Count - (int)newEntryCount;
5774
return _logBuffer.Skip(skipCount).ToList().AsReadOnly();
5875
}
5976
}
77+
78+
/// <summary>
79+
/// Opens the feedback log file for appending with shared read/write access.
80+
/// </summary>
81+
internal static StreamWriter OpenLogFile(string logFileName)
82+
{
83+
var fs = new FileStream(logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
84+
try
85+
{
86+
return new StreamWriter(fs, Encoding.UTF8);
87+
}
88+
catch
89+
{
90+
fs.Dispose();
91+
throw;
92+
}
93+
}
94+
95+
/// <summary>
96+
/// Writes a collection of log entries to the given writer.
97+
/// </summary>
98+
internal static void WriteEntries(StreamWriter writer, IEnumerable<string> entries)
99+
{
100+
foreach (string logLine in entries)
101+
{
102+
writer.WriteLine(logLine);
103+
}
104+
105+
writer.Flush();
106+
}
60107
}
61108
}

src/DebugEngineHost/HostLogger.cs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Globalization;
77
using System.IO;
8+
using System.Threading;
89

910
namespace Microsoft.DebugEngineHost
1011
{
@@ -15,7 +16,7 @@ public static class HostLogger
1516

1617
private static string s_engineLogFile;
1718

18-
private static readonly FeedbackLogBuffer s_circularBuffer = new FeedbackLogBuffer();
19+
private static FeedbackLogBuffer s_circularBuffer;
1920
private static VSFeedbackLogger s_feedbackLogger;
2021

2122
public static void EnableHostLogging(Action<string> callback, LogLevel level = LogLevel.Verbose)
@@ -27,7 +28,7 @@ public static void EnableHostLogging(Action<string> callback, LogLevel level = L
2728

2829
if (s_feedbackLogger == null)
2930
{
30-
s_feedbackLogger = new VSFeedbackLogger(s_circularBuffer);
31+
s_feedbackLogger = new VSFeedbackLogger(EnsureFeedbackBuffer());
3132
}
3233
}
3334

@@ -59,6 +60,14 @@ public static ILogChannel GetNatvisLogChannel()
5960
return s_natvisLogChannel;
6061
}
6162

63+
/// <summary>
64+
/// Returns true if the feedback log is currently active (buffer has been created).
65+
/// </summary>
66+
public static bool IsFeedbackLogEnabled
67+
{
68+
get { return s_circularBuffer != null; }
69+
}
70+
6271
/// <summary>
6372
/// Writes a message to the feedback circular buffer and, if active, to the feedback log file.
6473
/// </summary>
@@ -72,16 +81,39 @@ public static void WriteFeedbackLog(string message)
7281
string timestamp = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
7382
string logLine = string.Format(CultureInfo.InvariantCulture, "{0}: {1}", timestamp, message);
7483

75-
s_circularBuffer.Write(logLine);
84+
EnsureFeedbackBuffer().Write(logLine);
7685
s_feedbackLogger?.Write(logLine);
7786
}
7887

88+
private static FeedbackLogBuffer EnsureFeedbackBuffer()
89+
{
90+
if (s_circularBuffer == null)
91+
{
92+
Interlocked.CompareExchange(ref s_circularBuffer, new FeedbackLogBuffer(), null);
93+
}
94+
95+
return s_circularBuffer;
96+
}
97+
98+
/// <summary>
99+
/// Returns true if the feedback buffer has been created and has entries.
100+
/// This is a cheap check to avoid unnecessary work in non-MIEngine scenarios.
101+
/// </summary>
102+
internal static bool HasFeedbackEntries
103+
{
104+
get
105+
{
106+
FeedbackLogBuffer buffer = s_circularBuffer;
107+
return buffer != null && !buffer.IsEmpty;
108+
}
109+
}
110+
79111
/// <summary>
80112
/// Returns log entries added since the last flush, then advances the flush marker.
81113
/// </summary>
82114
internal static IReadOnlyCollection<string> GetNewFeedbackEntries()
83115
{
84-
return s_circularBuffer.FlushNewEntries();
116+
return s_circularBuffer?.FlushNewEntries() ?? Array.Empty<string>();
85117
}
86118

87119
/// <summary>

src/DebugEngineHost/VSFeedbackLogger.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,10 @@ private void OnFeedbackSemaphoreCreated(object sender, FileSystemEventArgs e)
7272
if (!_enabled)
7373
{
7474
string logFileName = HostLogger.GetFeedbackLogFilePath(_vsPid);
75-
StreamWriter writer = new StreamWriter(logFileName, append: true, encoding: Encoding.UTF8);
75+
StreamWriter writer = FeedbackLogBuffer.OpenLogFile(logFileName);
7676
try
7777
{
78-
foreach (string logLine in _circularBuffer.FlushNewEntries())
79-
{
80-
writer.WriteLine(logLine);
81-
}
82-
writer.Flush();
78+
FeedbackLogBuffer.WriteEntries(writer, _circularBuffer.FlushNewEntries());
8379
}
8480
catch
8581
{

src/MICore/Logger.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,15 @@ public static void Reset()
108108
/// <param name="line">[Required] line to write</param>
109109
public void WriteLine(LogLevel level, string line)
110110
{
111-
HostLogger.WriteFeedbackLog(line);
112-
113111
if (s_isEnabled)
114112
{
115113
WriteLineImpl(level, line);
116114
}
115+
116+
if (HostLogger.IsFeedbackLogEnabled)
117+
{
118+
HostLogger.WriteFeedbackLog(line);
119+
}
117120
}
118121

119122
/// <summary>
@@ -124,12 +127,10 @@ public void WriteLine(LogLevel level, string line)
124127
/// <param name="args">arguments to use in the format string</param>
125128
public void WriteLine(LogLevel level, string format, params object[] args)
126129
{
127-
string message = string.Format(CultureInfo.CurrentCulture, format, args);
128-
HostLogger.WriteFeedbackLog(message);
129-
130-
if (s_isEnabled)
130+
if (s_isEnabled || HostLogger.IsFeedbackLogEnabled)
131131
{
132-
WriteLineImpl(level, message);
132+
string message = string.Format(CultureInfo.CurrentCulture, format, args);
133+
WriteLine(level, message);
133134
}
134135
}
135136

@@ -141,12 +142,15 @@ public void WriteLine(LogLevel level, string format, params object[] args)
141142
/// <param name="textBlock">Block of text to write</param>
142143
public void WriteTextBlock(LogLevel level, string prefix, string textBlock)
143144
{
144-
HostLogger.WriteFeedbackLog((!string.IsNullOrEmpty(prefix) ? prefix : string.Empty) + textBlock);
145-
146145
if (s_isEnabled)
147146
{
148147
WriteTextBlockImpl(level, prefix, textBlock);
149148
}
149+
150+
if (HostLogger.IsFeedbackLogEnabled)
151+
{
152+
HostLogger.WriteFeedbackLog((!string.IsNullOrEmpty(prefix) ? prefix : string.Empty) + textBlock);
153+
}
150154
}
151155

152156
/// <summary>

0 commit comments

Comments
 (0)