Skip to content

Commit 865a3c5

Browse files
committed
system.text.json: trace2message updates
Update the Trace2Message class to use System.Text.Json instead of Json.NET for event format target messages. Note that ordering was purposefully added to ensure the expected format of the new JSON tests.
1 parent f1bed77 commit 865a3c5

File tree

2 files changed

+144
-91
lines changed

2 files changed

+144
-91
lines changed

src/shared/Core.Tests/Trace2MessageTests.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Collections.Generic;
13
using GitCredentialManager;
24
using Xunit;
35

@@ -35,4 +37,51 @@ public void BuildCategorySpan_Match_Returns_Expected_String(string input, string
3537
var actual = Trace2Message.BuildCategorySpan(input);
3638
Assert.Equal(expected, actual);
3739
}
40+
41+
[Fact]
42+
public void Event_Message_Without_Snake_Case_ToJson_Creates_Expected_Json()
43+
{
44+
var errorMessage = new ErrorMessage()
45+
{
46+
Event = Trace2Event.Error,
47+
Sid = "123",
48+
Thread = "main",
49+
Time = new DateTimeOffset(),
50+
File = "foo.cs",
51+
Line = 1,
52+
Depth = 1,
53+
Message = "bar",
54+
ParameterizedMessage = "baz"
55+
};
56+
57+
var expected = "{\"event\":\"error\",\"sid\":\"123\",\"thread\":\"main\",\"time\":\"0001-01-01T00:00:00+00:00\",\"file\":\"foo.cs\",\"line\":1,\"depth\":1,\"msg\":\"bar\",\"format\":\"baz\"}";
58+
var actual = errorMessage.ToJson();
59+
60+
Assert.Equal(expected, actual);
61+
}
62+
63+
[Fact]
64+
public void Event_Message_With_Snake_Case_ToJson_Creates_Expected_Json()
65+
{
66+
var childStartMessage = new ChildStartMessage()
67+
{
68+
Event = Trace2Event.ChildStart,
69+
Sid = "123",
70+
Thread = "main",
71+
Time = new DateTimeOffset(),
72+
File = "foo.cs",
73+
Line = 1,
74+
Depth = 1,
75+
Id = 1,
76+
Classification = Trace2ProcessClass.UIHelper,
77+
UseShell = false,
78+
Argv = new List<string>() { "bar", "baz" },
79+
ElapsedTime = 0.05
80+
};
81+
82+
var expected = "{\"event\":\"child_start\",\"sid\":\"123\",\"thread\":\"main\",\"time\":\"0001-01-01T00:00:00+00:00\",\"file\":\"foo.cs\",\"line\":1,\"depth\":1,\"t_abs\":0.05,\"argv\":[\"bar\",\"baz\"],\"child_id\":1,\"child_class\":\"ui_helper\",\"use_shell\":false}";
83+
var actual = childStartMessage.ToJson();
84+
85+
Assert.Equal(expected, actual);
86+
}
3887
}

src/shared/Core/Trace2Message.cs

Lines changed: 95 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Text;
4-
using Newtonsoft.Json;
5-
using Newtonsoft.Json.Converters;
6-
using Newtonsoft.Json.Serialization;
4+
using System.Text.Json;
5+
using System.Text.Json.Serialization;
76

87
namespace GitCredentialManager;
98

@@ -13,28 +12,38 @@ public abstract class Trace2Message
1312
private const string NormalPerfTimeFormat = "HH:mm:ss.ffffff";
1413

1514
protected const string EmptyPerformanceSpan = "| | | | ";
16-
protected const string TimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'";
15+
protected static readonly JsonSerializerOptions JsonSerializerOptions = new()
16+
{
17+
PropertyNameCaseInsensitive = true,
18+
Converters = { new JsonStringEnumConverter(new SnakeCaseNamingPolicy()) }
19+
};
1720

18-
[JsonProperty("event")]
21+
[JsonPropertyName("event")]
22+
[JsonPropertyOrder(1)]
1923
public Trace2Event Event { get; set; }
2024

21-
[JsonProperty("sid")]
25+
[JsonPropertyName("sid")]
26+
[JsonPropertyOrder(2)]
2227
public string Sid { get; set; }
2328

24-
[JsonProperty("thread")]
29+
[JsonPropertyName("thread")]
30+
[JsonPropertyOrder(3)]
2531
public string Thread { get; set; }
2632

27-
[JsonProperty("time")]
33+
[JsonPropertyName("time")]
34+
[JsonPropertyOrder(4)]
2835
public DateTimeOffset Time { get; set; }
2936

30-
[JsonProperty("file")]
31-
37+
[JsonPropertyName("file")]
38+
[JsonPropertyOrder(5)]
3239
public string File { get; set; }
3340

34-
[JsonProperty("line")]
41+
[JsonPropertyName("line")]
42+
[JsonPropertyOrder(6)]
3543
public int Line { get; set; }
3644

37-
[JsonProperty("depth")]
45+
[JsonPropertyName("depth")]
46+
[JsonPropertyOrder(7)]
3847
public int Depth { get; set; }
3948

4049
public abstract string ToJson();
@@ -175,20 +184,17 @@ private static string BuildSpan(PerformanceFormatSpan component, string data)
175184

176185
public class VersionMessage : Trace2Message
177186
{
178-
[JsonProperty("evt")]
187+
[JsonPropertyName("evt")]
188+
[JsonPropertyOrder(8)]
179189
public string Evt { get; set; }
180190

181-
[JsonProperty("exe")]
191+
[JsonPropertyName("exe")]
192+
[JsonPropertyOrder(9)]
182193
public string Exe { get; set; }
183194

184195
public override string ToJson()
185196
{
186-
return JsonConvert.SerializeObject(this,
187-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
188-
new IsoDateTimeConverter()
189-
{
190-
DateTimeFormat = TimeFormat
191-
});
197+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
192198
}
193199

194200
public override string ToNormalString()
@@ -214,20 +220,17 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
214220

215221
public class StartMessage : Trace2Message
216222
{
217-
[JsonProperty("t_abs")]
223+
[JsonPropertyName("t_abs")]
224+
[JsonPropertyOrder(8)]
218225
public double ElapsedTime { get; set; }
219226

220-
[JsonProperty("argv")]
227+
[JsonPropertyName("argv")]
228+
[JsonPropertyOrder(9)]
221229
public List<string> Argv { get; set; }
222230

223231
public override string ToJson()
224232
{
225-
return JsonConvert.SerializeObject(this,
226-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
227-
new IsoDateTimeConverter()
228-
{
229-
DateTimeFormat = TimeFormat
230-
});
233+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
231234
}
232235

233236
public override string ToNormalString()
@@ -253,20 +256,17 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
253256

254257
public class ExitMessage : Trace2Message
255258
{
256-
[JsonProperty("t_abs")]
259+
[JsonPropertyName("t_abs")]
260+
[JsonPropertyOrder(8)]
257261
public double ElapsedTime { get; set; }
258262

259-
[JsonProperty("code")]
263+
[JsonPropertyName("code")]
264+
[JsonPropertyOrder(9)]
260265
public int Code { get; set; }
261266

262267
public override string ToJson()
263268
{
264-
return JsonConvert.SerializeObject(this,
265-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
266-
new IsoDateTimeConverter()
267-
{
268-
DateTimeFormat = TimeFormat
269-
});
269+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
270270
}
271271

272272
public override string ToNormalString()
@@ -292,28 +292,29 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
292292

293293
public class ChildStartMessage : Trace2Message
294294
{
295-
[JsonProperty("child_id")]
295+
[JsonPropertyName("t_abs")]
296+
[JsonPropertyOrder(8)]
297+
public double ElapsedTime { get; set; }
298+
299+
[JsonPropertyName("argv")]
300+
[JsonPropertyOrder(9)]
301+
public IList<string> Argv { get; set; }
302+
303+
[JsonPropertyName("child_id")]
304+
[JsonPropertyOrder(10)]
296305
public long Id { get; set; }
297306

298-
[JsonProperty("child_class")]
307+
[JsonPropertyName("child_class")]
308+
[JsonPropertyOrder(11)]
299309
public Trace2ProcessClass Classification { get; set; }
300310

301-
[JsonProperty("use_shell")]
311+
[JsonPropertyName("use_shell")]
312+
[JsonPropertyOrder(12)]
302313
public bool UseShell { get; set; }
303314

304-
[JsonProperty("argv")]
305-
public IList<string> Argv { get; set; }
306-
307-
public double ElapsedTime { get; set; }
308-
309315
public override string ToJson()
310316
{
311-
return JsonConvert.SerializeObject(this,
312-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
313-
new IsoDateTimeConverter()
314-
{
315-
DateTimeFormat = TimeFormat
316-
});
317+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
317318
}
318319

319320
public override string ToNormalString()
@@ -348,28 +349,29 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
348349

349350
public class ChildExitMessage : Trace2Message
350351
{
351-
[JsonProperty("child_id")]
352+
[JsonPropertyName("t_abs")]
353+
[JsonPropertyOrder(8)]
354+
public double ElapsedTime { get; set; }
355+
356+
[JsonPropertyName("t_rel")]
357+
[JsonPropertyOrder(9)]
358+
public double RelativeTime { get; set; }
359+
360+
[JsonPropertyName("child_id")]
361+
[JsonPropertyOrder(10)]
352362
public long Id { get; set; }
353363

354-
[JsonProperty("pid")]
364+
[JsonPropertyName("pid")]
365+
[JsonPropertyOrder(11)]
355366
public int Pid { get; set; }
356367

357-
[JsonProperty("code")]
368+
[JsonPropertyName("code")]
369+
[JsonPropertyOrder(12)]
358370
public int Code { get; set; }
359371

360-
[JsonProperty("t_rel")]
361-
public double RelativeTime { get; set; }
362-
363-
public double ElapsedTime { get; set; }
364-
365372
public override string ToJson()
366373
{
367-
return JsonConvert.SerializeObject(this,
368-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
369-
new IsoDateTimeConverter()
370-
{
371-
DateTimeFormat = TimeFormat
372-
});
374+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
373375
}
374376

375377
public override string ToNormalString()
@@ -403,18 +405,17 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
403405

404406
public class ErrorMessage : Trace2Message
405407
{
406-
[JsonProperty("msg")] public string Message { get; set; }
408+
[JsonPropertyName("msg")]
409+
[JsonPropertyOrder(8)]
410+
public string Message { get; set; }
407411

408-
[JsonProperty("format")] public string ParameterizedMessage { get; set; }
412+
[JsonPropertyName("format")]
413+
[JsonPropertyOrder(9)]
414+
public string ParameterizedMessage { get; set; }
409415

410416
public override string ToJson()
411417
{
412-
return JsonConvert.SerializeObject(this,
413-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
414-
new IsoDateTimeConverter()
415-
{
416-
DateTimeFormat = TimeFormat
417-
});
418+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
418419
}
419420

420421
public override string ToNormalString()
@@ -440,38 +441,39 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
440441

441442
public abstract class RegionMessage : Trace2Message
442443
{
443-
[JsonProperty("repo")]
444+
[JsonPropertyName("t_abs")]
445+
[JsonPropertyOrder(8)]
446+
public double ElapsedTime { get; set; }
444447

448+
[JsonPropertyName("repo")]
449+
[JsonPropertyOrder(9)]
445450
// Defaults to 1, as does Git.
446451
// See https://git-scm.com/docs/api-trace2#Documentation/technical/api-trace2.txt-codeltrepo-idgtcode for details.
447452
public int Repo { get; set; } = 1;
448453

449454
// TODO: Remove default value if support for nested regions is implemented.
450-
[JsonProperty("nesting")]
455+
[JsonPropertyName("nesting")]
456+
[JsonPropertyOrder(10)]
451457
public int Nesting { get; set; } = 1;
452458

453-
[JsonProperty("category")]
459+
[JsonPropertyName("category")]
460+
[JsonPropertyOrder(11)]
454461
public string Category { get; set; }
455462

456-
[JsonProperty("label")]
463+
[JsonPropertyName("label")]
464+
[JsonPropertyOrder(12)]
457465
public string Label { get; set; }
458466

459-
[JsonProperty("msg")]
467+
[JsonPropertyName("msg")]
468+
[JsonPropertyOrder(13)]
460469
public string Message { get; set; }
461-
462-
public double ElapsedTime { get; set; }
463470
}
464471

465472
public class RegionEnterMessage : RegionMessage
466473
{
467474
public override string ToJson()
468475
{
469-
return JsonConvert.SerializeObject(this,
470-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
471-
new IsoDateTimeConverter()
472-
{
473-
DateTimeFormat = TimeFormat
474-
});
476+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
475477
}
476478

477479
public override string ToNormalString()
@@ -497,16 +499,12 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
497499

498500
public class RegionLeaveMessage : RegionMessage
499501
{
502+
[JsonPropertyOrder(14)]
500503
public double RelativeTime { get; set; }
501504

502505
public override string ToJson()
503506
{
504-
return JsonConvert.SerializeObject(this,
505-
new StringEnumConverter(typeof(SnakeCaseNamingStrategy)),
506-
new IsoDateTimeConverter()
507-
{
508-
DateTimeFormat = TimeFormat
509-
});
507+
return JsonSerializer.Serialize(this, JsonSerializerOptions);
510508
}
511509

512510
public override string ToNormalString()
@@ -529,3 +527,9 @@ protected override string GetEventMessage(Trace2FormatTarget formatTarget)
529527
return Message;
530528
}
531529
}
530+
531+
public class SnakeCaseNamingPolicy : JsonNamingPolicy
532+
{
533+
public override string ConvertName(string name) =>
534+
name.ToSnakeCase();
535+
}

0 commit comments

Comments
 (0)