Skip to content

Commit 414d92b

Browse files
authored
Merge pull request #385 from nblumhardt/2025.1-websockets-support
Final 2025.1 updates
2 parents 30dc76e + bca673d commit 414d92b

19 files changed

+371
-176
lines changed

ci.global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"sdk": {
3-
"version": "9.0.200"
3+
"version": "9.0.203"
44
}
55
}

src/SeqCli/Cli/Commands/ApiKey/CreateCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ protected override async Task<int> Run()
106106
var apiKey = await connection.ApiKeys.TemplateAsync();
107107

108108
apiKey.Title = _title;
109-
apiKey.InputSettings.AppliedProperties = _properties.Properties
109+
apiKey.InputSettings.AppliedProperties = _properties.FlatProperties
110110
.Select(kvp => new EventPropertyPart(kvp.Key, kvp.Value))
111111
.ToList();
112112
apiKey.InputSettings.UseServerTimestamps = _useServerTimestamps;
Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,56 @@
1-
// Copyright 2018 Datalust Pty Ltd and Contributors
2-
//
3-
// Licensed under the Apache License, Version 2.0 (the "License");
4-
// you may not use this file except in compliance with the License.
5-
// You may obtain a copy of the License at
6-
//
7-
// http://www.apache.org/licenses/LICENSE-2.0
8-
//
9-
// Unless required by applicable law or agreed to in writing, software
10-
// distributed under the License is distributed on an "AS IS" BASIS,
11-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
// See the License for the specific language governing permissions and
13-
// limitations under the License.
14-
15-
using System;
16-
using System.Linq;
17-
using System.Threading.Tasks;
18-
using SeqCli.Cli.Features;
19-
using SeqCli.Config;
20-
using SeqCli.Connection;
21-
22-
namespace SeqCli.Cli.Commands.ApiKey;
23-
24-
[Command("apikey", "list", "List available API keys", Example="seqcli apikey list")]
25-
class ListCommand : Command
26-
{
27-
readonly SeqConnectionFactory _connectionFactory;
28-
29-
readonly EntityIdentityFeature _entityIdentity;
30-
readonly ConnectionFeature _connection;
31-
readonly OutputFormatFeature _output;
32-
33-
public ListCommand(SeqConnectionFactory connectionFactory, SeqCliConfig config)
34-
{
35-
if (config == null) throw new ArgumentNullException(nameof(config));
36-
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
37-
38-
_entityIdentity = Enable(new EntityIdentityFeature("API key", "list"));
39-
_output = Enable(new OutputFormatFeature(config.Output));
40-
_connection = Enable<ConnectionFeature>();
41-
}
42-
43-
protected override async Task<int> Run()
44-
{
45-
var connection = _connectionFactory.Connect(_connection);
46-
47-
var list = _entityIdentity.Id != null ?
48-
new[] { await connection.ApiKeys.FindAsync(_entityIdentity.Id) } :
49-
(await connection.ApiKeys.ListAsync())
50-
.Where(ak => _entityIdentity.Title == null || _entityIdentity.Title == ak.Title);
51-
52-
_output.ListEntities(list);
53-
54-
return 0;
55-
}
1+
// Copyright 2018 Datalust Pty Ltd and Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Linq;
17+
using System.Threading.Tasks;
18+
using SeqCli.Cli.Features;
19+
using SeqCli.Config;
20+
using SeqCli.Connection;
21+
22+
namespace SeqCli.Cli.Commands.ApiKey;
23+
24+
[Command("apikey", "list", "List available API keys", Example="seqcli apikey list")]
25+
class ListCommand : Command
26+
{
27+
readonly SeqConnectionFactory _connectionFactory;
28+
29+
readonly EntityIdentityFeature _entityIdentity;
30+
readonly ConnectionFeature _connection;
31+
readonly OutputFormatFeature _output;
32+
33+
public ListCommand(SeqConnectionFactory connectionFactory, SeqCliConfig config)
34+
{
35+
if (config == null) throw new ArgumentNullException(nameof(config));
36+
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
37+
38+
_entityIdentity = Enable(new EntityIdentityFeature("API key", "list"));
39+
_output = Enable(new OutputFormatFeature(config.Output));
40+
_connection = Enable<ConnectionFeature>();
41+
}
42+
43+
protected override async Task<int> Run()
44+
{
45+
var connection = _connectionFactory.Connect(_connection);
46+
47+
var list = _entityIdentity.Id != null ?
48+
new[] { await connection.ApiKeys.FindAsync(_entityIdentity.Id) } :
49+
(await connection.ApiKeys.ListAsync())
50+
.Where(ak => _entityIdentity.Title == null || _entityIdentity.Title == ak.Title);
51+
52+
_output.ListEntities(list);
53+
54+
return 0;
55+
}
5656
}
Lines changed: 67 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,68 @@
1-
// Copyright 2018 Datalust Pty Ltd and Contributors
2-
//
3-
// Licensed under the Apache License, Version 2.0 (the "License");
4-
// you may not use this file except in compliance with the License.
5-
// You may obtain a copy of the License at
6-
//
7-
// http://www.apache.org/licenses/LICENSE-2.0
8-
//
9-
// Unless required by applicable law or agreed to in writing, software
10-
// distributed under the License is distributed on an "AS IS" BASIS,
11-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
// See the License for the specific language governing permissions and
13-
// limitations under the License.
14-
15-
using System;
16-
using System.Linq;
17-
using System.Threading.Tasks;
18-
using SeqCli.Cli.Features;
19-
using SeqCli.Connection;
20-
using Serilog;
21-
22-
namespace SeqCli.Cli.Commands.ApiKey;
23-
24-
[Command("apikey", "remove", "Remove an API key from the server",
25-
Example="seqcli apikey remove -t 'Test API Key'")]
26-
class RemoveCommand : Command
27-
{
28-
readonly SeqConnectionFactory _connectionFactory;
29-
30-
readonly EntityIdentityFeature _entityIdentity;
31-
readonly ConnectionFeature _connection;
32-
33-
public RemoveCommand(SeqConnectionFactory connectionFactory)
34-
{
35-
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
36-
37-
_entityIdentity = Enable(new EntityIdentityFeature("API key", "remove"));
38-
_connection = Enable<ConnectionFeature>();
39-
}
40-
41-
protected override async Task<int> Run()
42-
{
43-
if (_entityIdentity.Title == null && _entityIdentity.Id == null)
44-
{
45-
Log.Error("A `title` or `id` must be specified");
46-
return 1;
47-
}
48-
49-
var connection = _connectionFactory.Connect(_connection);
50-
51-
var toRemove = _entityIdentity.Id != null ?
52-
new[] {await connection.ApiKeys.FindAsync(_entityIdentity.Id)} :
53-
(await connection.ApiKeys.ListAsync())
54-
.Where(ak => _entityIdentity.Title == ak.Title)
55-
.ToArray();
56-
57-
if (!toRemove.Any())
58-
{
59-
Log.Error("No matching API key was found");
60-
return 1;
61-
}
62-
63-
foreach (var apiKeyEntity in toRemove)
64-
await connection.ApiKeys.RemoveAsync(apiKeyEntity);
65-
66-
return 0;
67-
}
1+
// Copyright 2018 Datalust Pty Ltd and Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Linq;
17+
using System.Threading.Tasks;
18+
using SeqCli.Cli.Features;
19+
using SeqCli.Connection;
20+
using Serilog;
21+
22+
namespace SeqCli.Cli.Commands.ApiKey;
23+
24+
[Command("apikey", "remove", "Remove an API key from the server",
25+
Example="seqcli apikey remove -t 'Test API Key'")]
26+
class RemoveCommand : Command
27+
{
28+
readonly SeqConnectionFactory _connectionFactory;
29+
30+
readonly EntityIdentityFeature _entityIdentity;
31+
readonly ConnectionFeature _connection;
32+
33+
public RemoveCommand(SeqConnectionFactory connectionFactory)
34+
{
35+
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
36+
37+
_entityIdentity = Enable(new EntityIdentityFeature("API key", "remove"));
38+
_connection = Enable<ConnectionFeature>();
39+
}
40+
41+
protected override async Task<int> Run()
42+
{
43+
if (_entityIdentity.Title == null && _entityIdentity.Id == null)
44+
{
45+
Log.Error("A `title` or `id` must be specified");
46+
return 1;
47+
}
48+
49+
var connection = _connectionFactory.Connect(_connection);
50+
51+
var toRemove = _entityIdentity.Id != null ?
52+
new[] {await connection.ApiKeys.FindAsync(_entityIdentity.Id)} :
53+
(await connection.ApiKeys.ListAsync())
54+
.Where(ak => _entityIdentity.Title == ak.Title)
55+
.ToArray();
56+
57+
if (!toRemove.Any())
58+
{
59+
Log.Error("No matching API key was found");
60+
return 1;
61+
}
62+
63+
foreach (var apiKeyEntity in toRemove)
64+
await connection.ApiKeys.RemoveAsync(apiKeyEntity);
65+
66+
return 0;
67+
}
6868
}

src/SeqCli/Cli/Commands/IngestCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected override async Task<int> Run()
8787
if (_level != null)
8888
enrichers.Add(new ScalarPropertyEnricher(LevelMapping.SurrogateLevelProperty, _level));
8989

90-
foreach (var (name, value) in _properties.Properties)
90+
foreach (var (name, value) in _properties.FlatProperties)
9191
enrichers.Add(new ScalarPropertyEnricher(name, value));
9292

9393
Func<LogEvent, bool>? filter = null;

src/SeqCli/Cli/Commands/LogCommand.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
// Copyright 2018 Datalust Pty Ltd
34
//
45
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -80,7 +81,7 @@ protected override async Task<int> Run()
8081
if (!string.IsNullOrWhiteSpace(_exception))
8182
payload["@x"] = _exception;
8283

83-
foreach (var (key, value) in _properties.Properties)
84+
foreach (var (key, value) in _properties.NestedProperties)
8485
{
8586
if (string.IsNullOrWhiteSpace(key))
8687
continue;
@@ -89,7 +90,7 @@ protected override async Task<int> Run()
8990
if (name.StartsWith('@'))
9091
name = $"@{name}";
9192

92-
payload[name] = new JValue(value);
93+
payload[name] = ToJsonValue(value);
9394
}
9495

9596
StringContent content;
@@ -134,4 +135,20 @@ protected override async Task<int> Run()
134135
Log.Error("Failed with status code {StatusCode} ({ReasonPhrase})", result.StatusCode, result.ReasonPhrase);
135136
return 1;
136137
}
138+
139+
static JToken ToJsonValue(object? value)
140+
{
141+
if (value is not IReadOnlyDictionary<string, object?> rod)
142+
{
143+
return new JValue(value);
144+
}
145+
146+
var result = new JObject();
147+
foreach (var (key, sub) in rod)
148+
{
149+
result[key] = ToJsonValue(sub);
150+
}
151+
152+
return result;
153+
}
137154
}

src/SeqCli/Cli/Commands/PrintCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ public PrintCommand(SeqCliOutputConfig outputConfig)
5656

5757
_invalidDataHandlingFeature = Enable<InvalidDataHandlingFeature>();
5858

59-
Options.Add("no-color", "Don't colorize text output", v => _noColor = true);
59+
Options.Add("no-color", "Don't colorize text output", _ => _noColor = true);
6060

6161
Options.Add("force-color",
6262
"Force redirected output to have ANSI color (unless `--no-color` is also specified)",
63-
v => _forceColor = true);
63+
_ => _forceColor = true);
6464
}
6565

6666
protected override async Task<int> Run()

src/SeqCli/Cli/Commands/QueryCommand.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class QueryCommand : Command
3535
readonly SignalExpressionFeature _signal;
3636
readonly TimeoutFeature _timeout;
3737
string? _query;
38+
bool _trace;
3839

3940
public QueryCommand(SeqConnectionFactory connectionFactory, SeqCliConfig config)
4041
{
@@ -45,6 +46,7 @@ public QueryCommand(SeqConnectionFactory connectionFactory, SeqCliConfig config)
4546
_signal = Enable<SignalExpressionFeature>();
4647
_timeout = Enable<TimeoutFeature>();
4748
_output = Enable(new OutputFormatFeature(config.Output));
49+
Options.Add("trace", "Enable detailed (server-side) query tracing", _ => _trace = true);
4850
_connection = Enable<ConnectionFeature>();
4951
}
5052

@@ -62,14 +64,14 @@ protected override async Task<int> Run()
6264

6365
if (_output.Json)
6466
{
65-
var result = await connection.Data.QueryAsync(_query, _range.Start, _range.End, _signal.Signal, timeout: timeout);
67+
var result = await connection.Data.QueryAsync(_query, _range.Start, _range.End, _signal.Signal, timeout: timeout, trace: _trace);
6668

6769
// Some friendlier JSON output is definitely possible here
6870
Console.WriteLine(JsonConvert.SerializeObject(result));
6971
}
7072
else
7173
{
72-
var result = await connection.Data.QueryCsvAsync(_query, _range.Start, _range.End, _signal.Signal, timeout: timeout);
74+
var result = await connection.Data.QueryCsvAsync(_query, _range.Start, _range.End, _signal.Signal, timeout: timeout, trace: _trace);
7375
_output.WriteCsv(result);
7476
}
7577

0 commit comments

Comments
 (0)