4
4
using System . IO ;
5
5
using System . IO . Pipes ;
6
6
using System . Linq ;
7
+ using System . Runtime . Serialization ;
7
8
using System . Text ;
8
9
using Newtonsoft . Json ;
9
10
using Newtonsoft . Json . Converters ;
@@ -16,7 +17,12 @@ namespace GitCredentialManager;
16
17
/// system.
17
18
/// </summary>
18
19
public enum Trace2Event
19
- { }
20
+ {
21
+ [ EnumMember ( Value = "version" ) ]
22
+ Version = 0 ,
23
+ [ EnumMember ( Value = "start" ) ]
24
+ Start = 1 ,
25
+ }
20
26
21
27
public class Trace2Settings
22
28
{
@@ -36,7 +42,13 @@ public interface ITrace2 : IDisposable
36
42
/// <param name="error">The standard error text stream connected back to the calling process.</param>
37
43
/// <param name="fileSystem">File system abstraction.</param>
38
44
/// <param name="appPath">The path to the GCM application.</param>
39
- void Start ( TextWriter error , IFileSystem fileSystem , string appPath ) ;
45
+ /// <param name="filePath">Path of the file this method is called from.</param>
46
+ /// <param name="lineNumber">Line number of file this method is called from.</param>
47
+ void Start ( TextWriter error ,
48
+ IFileSystem fileSystem ,
49
+ string appPath ,
50
+ [ System . Runtime . CompilerServices . CallerFilePath ] string filePath = "" ,
51
+ [ System . Runtime . CompilerServices . CallerLineNumber ] int lineNumber = 0 ) ;
40
52
}
41
53
42
54
public class Trace2 : DisposableObject , ITrace2
@@ -63,9 +75,22 @@ public Trace2(IEnvironment environment, Trace2Settings settings, string[] argv,
63
75
_sid = SetSid ( ) ;
64
76
}
65
77
66
- public void Start ( TextWriter error , IFileSystem fileSystem , string appPath )
78
+ public void Start ( TextWriter error ,
79
+ IFileSystem fileSystem ,
80
+ string appPath ,
81
+ string filePath ,
82
+ int lineNumber )
67
83
{
68
84
TryParseSettings ( error , fileSystem ) ;
85
+
86
+ if ( ! AssemblyUtils . TryGetAssemblyVersion ( out string version ) )
87
+ {
88
+ // A version is required for TRACE2, so if this call fails
89
+ // manually set the version.
90
+ version = "0.0.0" ;
91
+ }
92
+ WriteVersion ( version , filePath , lineNumber ) ;
93
+ WriteStart ( appPath , filePath , lineNumber ) ;
69
94
}
70
95
71
96
protected override void ReleaseManagedResources ( )
@@ -164,6 +189,50 @@ private void TryParseSettings(TextWriter error, IFileSystem fileSystem)
164
189
}
165
190
}
166
191
192
+ private void WriteVersion (
193
+ string gcmVersion ,
194
+ string filePath ,
195
+ int lineNumber ,
196
+ string eventFormatVersion = "3" )
197
+ {
198
+ EnsureArgument . NotNull ( gcmVersion , nameof ( gcmVersion ) ) ;
199
+
200
+ WriteMessage ( new VersionMessage ( )
201
+ {
202
+ Event = Trace2Event . Version ,
203
+ Sid = _sid ,
204
+ Time = DateTimeOffset . UtcNow ,
205
+ File = Path . GetFileName ( filePath ) . ToLower ( ) ,
206
+ Line = lineNumber ,
207
+ Evt = eventFormatVersion ,
208
+ Exe = gcmVersion
209
+ } ) ;
210
+ }
211
+
212
+ private void WriteStart (
213
+ string appPath ,
214
+ string filePath ,
215
+ int lineNumber )
216
+ {
217
+ // Prepend GCM exe to arguments
218
+ var argv = new List < string > ( )
219
+ {
220
+ Path . GetFileName ( appPath ) ,
221
+ } ;
222
+ argv . AddRange ( _argv ) ;
223
+
224
+ WriteMessage ( new StartMessage ( )
225
+ {
226
+ Event = Trace2Event . Start ,
227
+ Sid = _sid ,
228
+ Time = DateTimeOffset . UtcNow ,
229
+ File = Path . GetFileName ( filePath ) . ToLower ( ) ,
230
+ Line = lineNumber ,
231
+ Argv = argv ,
232
+ ElapsedTime = ( DateTimeOffset . UtcNow - _applicationStartTime ) . TotalSeconds
233
+ } ) ;
234
+ }
235
+
167
236
private void AddWriter ( ITrace2Writer writer )
168
237
{
169
238
ThrowIfDisposed ( ) ;
@@ -203,6 +272,7 @@ private void WriteMessage(Trace2Message message)
203
272
public abstract class Trace2Message
204
273
{
205
274
protected const string TimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'" ;
275
+ private const int SourceColumnMaxWidth = 23 ;
206
276
207
277
[ JsonProperty ( "event" , Order = 1 ) ]
208
278
public Trace2Event Event { get ; set ; }
@@ -226,4 +296,69 @@ public abstract class Trace2Message
226
296
public abstract string ToJson ( ) ;
227
297
228
298
public abstract string ToNormalString ( ) ;
299
+
300
+ protected string BuildNormalString ( string message )
301
+ {
302
+ // The normal format uses local time rather than UTC time.
303
+ string time = Time . ToLocalTime ( ) . ToString ( "HH:mm:ss.ffffff" ) ;
304
+
305
+ // Source column format is file:line
306
+ string source = $ "{ File . ToLower ( ) } :{ Line } ";
307
+ if ( source . Length > SourceColumnMaxWidth )
308
+ {
309
+ source = TraceUtils . FormatSource ( source , SourceColumnMaxWidth ) ;
310
+ }
311
+
312
+ // Git's TRACE2 normal format is:
313
+ // [<time> SP <filename>:<line> SP+] <event-name> [[SP] <event-message>] LF
314
+ return $ "{ time } { source , - 33 } { Event . ToString ( ) . ToLower ( ) } { message } ";
315
+ }
316
+ }
317
+
318
+ public class VersionMessage : Trace2Message
319
+ {
320
+ [ JsonProperty ( "evt" , Order = 7 ) ]
321
+ public string Evt { get ; set ; }
322
+
323
+ [ JsonProperty ( "exe" , Order = 8 ) ]
324
+ public string Exe { get ; set ; }
325
+
326
+ public override string ToJson ( )
327
+ {
328
+ return JsonConvert . SerializeObject ( this ,
329
+ new StringEnumConverter ( ) ,
330
+ new IsoDateTimeConverter ( )
331
+ {
332
+ DateTimeFormat = TimeFormat
333
+ } ) ;
334
+ }
335
+
336
+ public override string ToNormalString ( )
337
+ {
338
+ return BuildNormalString ( Exe . ToLower ( ) ) ;
339
+ }
340
+ }
341
+
342
+ public class StartMessage : Trace2Message
343
+ {
344
+ [ JsonProperty ( "t_abs" , Order = 7 ) ]
345
+ public double ElapsedTime { get ; set ; }
346
+
347
+ [ JsonProperty ( "argv" , Order = 8 ) ]
348
+ public List < string > Argv { get ; set ; }
349
+
350
+ public override string ToJson ( )
351
+ {
352
+ return JsonConvert . SerializeObject ( this ,
353
+ new StringEnumConverter ( ) ,
354
+ new IsoDateTimeConverter ( )
355
+ {
356
+ DateTimeFormat = TimeFormat
357
+ } ) ;
358
+ }
359
+
360
+ public override string ToNormalString ( )
361
+ {
362
+ return BuildNormalString ( string . Join ( " " , Argv ) ) ;
363
+ }
229
364
}
0 commit comments