Uh oh!
There was an error while loading. Please reload this page.
Migrate data handling from Serilog's LogEvent across to System.Text.Json.JsonObject, with the help of Seq.Syntax v2.0 - #496
Conversation
…t.Json.JsonObject`, with the help of Seq.Syntax v2.0. Assisted-by: Claude:claude-fable-5
…t want easy or obvious conversions into Serilog types, the set of scenarios that require this should be and stay vanishingly small
…eviously used for trace formatting
| @@ -1,31 +1,41 @@ | |||
| using System; | |||
| using System; | |||
There was a problem hiding this comment.
Note that with this move and a few others, previously-general-purpose types have been scoped back to use only for app hosting interop, or sample data generation.
…ould point us in the right direction
| namespace SeqCli.Data; | ||
| static class EventJsonDocument |
There was a problem hiding this comment.
It would be nice to pull together more functionality for working with raw JSON events into this namespace; it's a bit bare right now.
nblumhardt-ro
commented
Sep 1, 2026
Blocking on datalust/seq-syntax#7 |
Assisted-by: Claude:claude-fable-5-1
nblumhardt-ro
commented
Sep 2, 2026
All good to go! |
| public void Enrich(JsonObject eventJson) | ||
| { | ||
| logEvent.RemovePropertyIfPresent("@i"); | ||
| eventJson["@l"] = level; |
| throw new InvalidDataException($"The line is not a JSON object: `{json.Trim()}`."); | ||
| if (!eventJson.ContainsKey("@t")) | ||
| eventJson["@t"] = DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture); |
| catch (Exception ex) | ||
| { | ||
| if (ex is JsonReaderException || ex is InvalidDataException) | ||
| if (ex is System.Text.Json.JsonException || ex is InvalidDataException) |
There was a problem hiding this comment.
nit: Does this need to be fully qualified?
| readonly struct ReadResult | ||
| { | ||
| public LogEvent? LogEvent { get; } | ||
| /// <summary> |
| using SeqCli.Data; | ||
| using SeqCli.Output; | ||
| namespace SeqCli.Mapping; |
| if (evt.Elapsed is { } elapsed) | ||
| properties.Add(new(ElapsedProperty, new ScalarValue(elapsed))); | ||
| eventJson[ElapsedProperty] = elapsed.ToString("c", CultureInfo.InvariantCulture); |
| [Fact] | ||
| public void LiteralBracesAreEscapedInTemplateText() | ||
| { | ||
| var (message, _) = StructuredMessage.Read(new JArray("a {not-a-hole} b")); |
There was a problem hiding this comment.
This is actually returning a template
| try | ||
| { | ||
| var error = JsonConvert.DeserializeObject<dynamic>(resultJson)!; | ||
| var error = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(resultJson)!; |
There was a problem hiding this comment.
Does this need to be Newtonsoft.Json?
Uh oh!
There was an error while loading. Please reload this page.
This one's been in the pipeline for a long time!
seqclioriginally piggy-backed on Serilog for event processing and formatting. This made sense when Seq's and Serilog's data models were aligned, but over time, Seq became completely general-purpose and dropped all Serilog-isms in its event model.As Seq became general purpose only incrementally (first relaxing level name constraints, then adding OTel properties, then dropping existence requirements for things like messages, then adding tracing-specific and metrics-specific schema, ...), the mapping into and out of Serilog's
LogEventdata model slowly became contorted and fragile.This PR moves all event data handling to
System.Text.Json.JsonObject, and leans on the v2 preview of Seq.Expressions to reimplement expression evaluation, formatting, and theming. I was able to lean on Claude for the mechanical bits, and I've run over a few more nice-to-have areas just to really strongly avoid any future temptation to mix up our data handling with Serilog.Externally, the change shouldn't have any obvious behavioral impacts, modulo bugs I'm yet to spot. I did update the
trace --jsonoutput to (correctly) preserve original, non-Serilog level names in this version (yet one more place where the Serilog model unnecessarily leaked in).