Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
a07777b
hc4-o61.1: Add the telemetry option set with duration parsing and env…
PascalSenn Sep 20, 2026
e196604
hc4-o61.2: add agent telemetry renderers
PascalSenn Sep 20, 2026
65b0227
hc4-wpf.1: refresh telemetry client schema
PascalSenn Sep 20, 2026
6895e65
hc4-o61.1: fix review cycle 1
PascalSenn Sep 20, 2026
b556a5a
hc4-o61.1: fix review cycle 2
PascalSenn Sep 20, 2026
5eb1401
Integrate hc4-o61.1: telemetry option set
PascalSenn Sep 20, 2026
1d903b8
Merge branch 'nitro-telemetry-integration' into wt/hc4-o61.2
PascalSenn Sep 20, 2026
0c390ff
hc4-o61.2: fix review cycle 2
PascalSenn Sep 20, 2026
b5c50b6
hc4-wpf.1: fix review cycle 1
PascalSenn Sep 20, 2026
f6c18d3
Integrate hc4-wpf.1: refresh client schema and telemetry operations
PascalSenn Sep 20, 2026
a063c52
Integrate hc4-o61.2: agent mode and telemetry renderers
PascalSenn Sep 20, 2026
b1c3c09
hc4-wpf.2: Add ITelemetryClient with DI registration over the generat…
PascalSenn Sep 20, 2026
0581ba8
hc4-o61.10: Use PooledArrayWriter instead of ArrayBufferWriter in the…
PascalSenn Sep 20, 2026
a83d1ba
Integrate hc4-o61.10: pooled writer in telemetry renderer
PascalSenn Sep 20, 2026
296f525
Integrate hc4-wpf.2: ITelemetryClient
PascalSenn Sep 20, 2026
81fbea6
hc4-o61.3: Port the portal filter grammar to C# and compile it to Ope…
PascalSenn Sep 20, 2026
d875fa2
hc4-o61.3: fix review cycle 1
PascalSenn Sep 20, 2026
040549e
Cover portal filtering grammar corpus
PascalSenn Sep 20, 2026
d7c16ac
hc4-o61.4: Add nitro telemetry services list|show and attributes keys…
PascalSenn Sep 20, 2026
3051c2a
hc4-o61.4: Forward telemetry service filters
PascalSenn Sep 20, 2026
ca364f6
hc4-o61.5: Add nitro telemetry logs list|show commands
PascalSenn Sep 20, 2026
564066c
hc4-o61.6: Add nitro telemetry traces list command over entry spans
PascalSenn Sep 20, 2026
8259439
hc4-o61.6: render trace filter errors
PascalSenn Sep 20, 2026
a480e9f
hc4-o61.6: align telemetry service snapshots with agent output
PascalSenn Sep 20, 2026
530b4a6
Add telemetry trace show tree command
PascalSenn Sep 20, 2026
63380eb
Fix telemetry trace show cycle one findings
PascalSenn Sep 20, 2026
f4451e2
Fix atomic span selection admission
PascalSenn Sep 20, 2026
ae466ca
Register telemetry trace show command
PascalSenn Sep 21, 2026
712a10e
Add telemetry attribute key hints
PascalSenn Sep 21, 2026
366a3c7
Add telemetry nudge persistence
PascalSenn Sep 21, 2026
e460298
Add telemetry pre-tool hook nudge
PascalSenn Sep 21, 2026
b3cf8ce
Add pre-tool-use hook matchers
PascalSenn Sep 21, 2026
256e874
Fix hook documentation summaries
PascalSenn Sep 21, 2026
07d6b0a
Address telemetry review feedback
PascalSenn Sep 26, 2026
f1635ad
fix(nitro): remove telemetry ndjson output
PascalSenn Sep 23, 2026
7c9a3b4
fix(nitro): render telemetry lists as JSON
PascalSenn Sep 23, 2026
2738f30
fix(nitro): render telemetry show commands as JSON
PascalSenn Sep 23, 2026
deaf9a9
Refactor telemetry command helpers and include query documents
PascalSenn Oct 1, 2026
42899e8
Merge main into nitro-telemetry-integration
PascalSenn Oct 1, 2026
0d0e4ec
Fix console trace truncation
PascalSenn Oct 1, 2026
0d24e5e
Address telemetry CLI review feedback
PascalSenn Oct 1, 2026
b5df076
Fix telemetry CLI review findings
PascalSenn Oct 1, 2026
e472fa9
Move telemetry helper logic back into owning classes
PascalSenn Oct 2, 2026
269aa92
Format telemetry filtering with peppermill
PascalSenn Oct 2, 2026
c5e2cb1
Remove telemetry environment defaults and extract LevenshteinDistance
PascalSenn Oct 2, 2026
b61f13f
Clean up telemetry filtering names
PascalSenn Oct 2, 2026
cb5981b
Replace TelemetryListFilter with CompiledTelemetryFilter
PascalSenn Oct 3, 2026
9f0164a
Format new telemetry files with peppermill
PascalSenn Oct 3, 2026
dcaee43
Move FirstNonEmpty into the span tree renderer extensions
PascalSenn Oct 3, 2026
edf289c
Restore the Nitro client GraphQL document glob
PascalSenn Oct 3, 2026
94dd4da
Name the exception events in the span tree renderer
PascalSenn Oct 3, 2026
3f5ec0d
Remove redundant telemetry tests
PascalSenn Oct 3, 2026
aa8ad87
Cover telemetry client mapping and untested CLI behavior
PascalSenn Oct 3, 2026
17aa507
Address telemetry review feedback
PascalSenn Oct 3, 2026
e587edf
Merge branch 'main' into nitro-telemetry-integration
PascalSenn Oct 5, 2026
365ed57
Merge branch 'main' into nitro-telemetry-integration
PascalSenn Oct 6, 2026
e4cab5d
Use ResultHolder consistently
tobias-tengler Oct 6, 2026
3e320c9
Remove TelemetryErrorRenderer
tobias-tengler Oct 6, 2026
1387994
Document Nitro CLI telemetry commands
tobias-tengler Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Arguments;

internal sealed class AttributeKeyArgument : Argument<string>
{
public AttributeKeyArgument() : base("key")
{
Description = "The attribute key";
Arity = ArgumentArity.ExactlyOne;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Arguments;

internal sealed class LogIdArgument : Argument<string>
{
public LogIdArgument() : base("log-id")
{
Description = "The log ID";
Arity = ArgumentArity.ExactlyOne;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Arguments;

internal sealed class ServiceNameArgument : Argument<string>
{
public ServiceNameArgument() : base("name")
{
Description = "The service name";
Arity = ArgumentArity.ExactlyOne;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Arguments;

internal sealed class TraceIdArgument : Argument<string>
{
public TraceIdArgument() : base("trace-id")
{
Description = "The trace ID";
Arity = ArgumentArity.ExactlyOne;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Attributes;

internal sealed class AttributesCommand : Command
{
public AttributesCommand() : base("attributes")
{
Description = "Inspect telemetry attributes.";

Subcommands.Add(new ListAttributeKeysCommand());
Subcommands.Add(new ListAttributeValuesCommand());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using ChilliCream.Nitro.Client.Telemetry;
using ChilliCream.Nitro.Client.Telemetry.Models;
using ChilliCream.Nitro.CommandLine.Commands.Telemetry.Options;
using ChilliCream.Nitro.CommandLine.Helpers;
using ChilliCream.Nitro.CommandLine.Results;
using ChilliCream.Nitro.CommandLine.Services.Sessions;

namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Attributes;

internal sealed class ListAttributeKeysCommand : Command
{
public ListAttributeKeysCommand() : base("keys")
{
Description = "List telemetry attribute keys.";

Options.Add(Opt<AttributeSignalOption>.Instance);
Options.Add(Opt<AttributeKindsOption>.Instance);
Options.Add(Opt<AttributeKeySearchOption>.Instance);
Options.Add(Opt<TelemetrySinceOption>.Instance);
Options.Add(Opt<TelemetryUntilOption>.Instance);
Options.Add(Opt<TelemetryLimitOption>.Instance);
Options.Add(Opt<OptionalCursorOption>.Instance);

TelemetryCommandOptions.AddOptions(this);

TelemetryCommandOptions.AddTimeRangeValidator(this);

this.AddExamples("telemetry attributes keys --signal traces");

this.SetActionWithExceptionHandling(ExecuteAsync);
}

private static async Task<int> ExecuteAsync(
ICommandServices services,
ParseResult parseResult,
CancellationToken cancellationToken)
{
var client = services.GetRequiredService<ITelemetryClient>();
var sessionService = services.GetRequiredService<ISessionService>();
var resultHolder = services.GetRequiredService<IResultHolder>();

parseResult.AssertHasAuthentication(sessionService);

var workspaceId = parseResult.GetWorkspaceId(sessionService);

var signal = parseResult.GetRequiredValue(Opt<AttributeSignalOption>.Instance);
var kinds = parseResult.GetValue(Opt<AttributeKindsOption>.Instance);
var search = parseResult.GetValue(Opt<AttributeKeySearchOption>.Instance);
var since = parseResult.GetValue(Opt<TelemetrySinceOption>.Instance);
var until = parseResult.GetValue(Opt<TelemetryUntilOption>.Instance);
var cursor = parseResult.GetValue(Opt<OptionalCursorOption>.Instance);
var limit = parseResult.GetValue(Opt<TelemetryLimitOption>.Instance) ?? 50;

var page = await client.ListAttributeKeysAsync(
workspaceId,
signal,
kinds,
search,
since,
until,
limit,
cursor,
cancellationToken);

var items = page.Items.Select(AttributeKeyListItem.From).ToArray();
resultHolder.SetResult(new PaginatedListResult<AttributeKeyListItem>(items, page.EndCursor));

return ExitCodes.Success;
}

internal sealed record AttributeKeyListItem(string Key, string Kind)
{
public static AttributeKeyListItem From(AttributeKeyRow key) => new(key.Path, key.Kind);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System.Globalization;
using ChilliCream.Nitro.Client.Telemetry;
using ChilliCream.Nitro.Client.Telemetry.Models;
using ChilliCream.Nitro.CommandLine.Commands.Telemetry.Arguments;
using ChilliCream.Nitro.CommandLine.Commands.Telemetry.Options;
using ChilliCream.Nitro.CommandLine.Helpers;
using ChilliCream.Nitro.CommandLine.Results;
using ChilliCream.Nitro.CommandLine.Services.Sessions;

namespace ChilliCream.Nitro.CommandLine.Commands.Telemetry.Attributes;

internal sealed class ListAttributeValuesCommand : Command
{
public ListAttributeValuesCommand() : base("values")
{
Description = "List telemetry attribute values.";

Arguments.Add(Opt<AttributeKeyArgument>.Instance);
Options.Add(Opt<AttributeSignalOption>.Instance);
Options.Add(Opt<AttributeKindOption>.Instance);
Options.Add(Opt<AttributeValueSearchOption>.Instance);
Options.Add(Opt<TelemetrySinceOption>.Instance);
Options.Add(Opt<TelemetryUntilOption>.Instance);
Options.Add(Opt<TelemetryLimitOption>.Instance);
Options.Add(Opt<OptionalCursorOption>.Instance);

TelemetryCommandOptions.AddOptions(this);

TelemetryCommandOptions.AddTimeRangeValidator(this);

this.AddExamples("telemetry attributes values service.name --signal traces");

this.SetActionWithExceptionHandling(ExecuteAsync);
}

private static async Task<int> ExecuteAsync(
ICommandServices services,
ParseResult parseResult,
CancellationToken cancellationToken)
{
var client = services.GetRequiredService<ITelemetryClient>();
var sessionService = services.GetRequiredService<ISessionService>();
var resultHolder = services.GetRequiredService<IResultHolder>();

parseResult.AssertHasAuthentication(sessionService);

var workspaceId = parseResult.GetWorkspaceId(sessionService);

var key = parseResult.GetRequiredValue(Opt<AttributeKeyArgument>.Instance);
var signal = parseResult.GetRequiredValue(Opt<AttributeSignalOption>.Instance);
var kind = parseResult.GetValue(Opt<AttributeKindOption>.Instance);
var search = parseResult.GetValue(Opt<AttributeValueSearchOption>.Instance);
var since = parseResult.GetValue(Opt<TelemetrySinceOption>.Instance);
var until = parseResult.GetValue(Opt<TelemetryUntilOption>.Instance);
var cursor = parseResult.GetValue(Opt<OptionalCursorOption>.Instance);
var limit = parseResult.GetValue(Opt<TelemetryLimitOption>.Instance) ?? 50;

var page = await client.ListAttributeValuesAsync(
workspaceId,
signal,
key,
kind,
search,
since,
until,
limit,
cursor,
cancellationToken);

var items = page.Items.Select(AttributeValueListItem.From).ToArray();
resultHolder.SetResult(new PaginatedListResult<AttributeValueListItem>(items, page.EndCursor));

return ExitCodes.Success;
}

internal sealed record AttributeValueListItem(string Value)
{
public static AttributeValueListItem From(AttributeValue value)
{
if (value.String is { } stringValue)
{
return new AttributeValueListItem(stringValue);
}

if (value.Int is { } intValue)
{
return new AttributeValueListItem(intValue.ToString(CultureInfo.InvariantCulture));
}

if (value.Float is { } floatValue)
{
return new AttributeValueListItem(floatValue.ToString(CultureInfo.InvariantCulture));
}

return new AttributeValueListItem(
value.Boolean switch
{
true => "true",
false => "false",
_ => string.Empty
});
}
}
}
Loading
Loading