From ca6c8f2b37e134c8ee8f945e549fe4f2ace50a6c Mon Sep 17 00:00:00 2001 From: Kent Karlsson Date: Tue, 2 Apr 2024 12:12:46 +0200 Subject: [PATCH 1/6] Seq 2024.2 EntraID Example fix * Provider value updated to Microsoft Entra ID from Azure Active Directory --- example/SeqEnableAAD/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/SeqEnableAAD/Program.cs b/example/SeqEnableAAD/Program.cs index 93d5a59..1e8523f 100644 --- a/example/SeqEnableAAD/Program.cs +++ b/example/SeqEnableAAD/Program.cs @@ -60,7 +60,7 @@ static async Task Run(string server, string? username, string? tenantId, string? var tid = await connection.Settings.FindNamedAsync(SettingName.EntraIDTenantId); user.Username = username; - provider.Value = "Azure Active Directory"; + provider.Value = "Microsoft Entra ID"; cid.Value = clientId; ckey.Value = clientKey; tid.Value = tenantId; @@ -77,4 +77,4 @@ static async Task Run(string server, string? username, string? tenantId, string? var iae = await connection.Settings.FindNamedAsync(SettingName.IsAuthenticationEnabled); iae.Value = true; await connection.Settings.UpdateAsync(iae); // this update needs to happen last, as enabling auth will lock this connection out -} \ No newline at end of file +} From 6f05bf3394551bac7c145dff73998ab5d6e306e9 Mon Sep 17 00:00:00 2001 From: Liam McLennan Date: Mon, 22 Apr 2024 10:37:58 +1000 Subject: [PATCH 2/6] Add expression indexes --- src/Seq.Api/Model/Indexes/IndexEntity.cs | 33 ++++++++++ .../Model/Indexes/IndexedEntityType.cs | 23 +++++++ .../Model/Indexing/ExpressionIndexEntity.cs | 18 ++++++ src/Seq.Api/Model/Settings/SettingName.cs | 11 ++++ src/Seq.Api/Model/Signals/SignalEntity.cs | 5 ++ .../ExpressionIndexesResourceGroup.cs | 60 +++++++++++++++++++ .../ResourceGroups/IndexesResourceGroup.cs | 58 ++++++++++++++++++ .../ResourceGroups/SignalsResourceGroup.cs | 1 + src/Seq.Api/Seq.Api.csproj | 2 +- src/Seq.Api/SeqConnection.cs | 10 ++++ 10 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 src/Seq.Api/Model/Indexes/IndexEntity.cs create mode 100644 src/Seq.Api/Model/Indexes/IndexedEntityType.cs create mode 100644 src/Seq.Api/Model/Indexing/ExpressionIndexEntity.cs create mode 100644 src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs create mode 100644 src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs diff --git a/src/Seq.Api/Model/Indexes/IndexEntity.cs b/src/Seq.Api/Model/Indexes/IndexEntity.cs new file mode 100644 index 0000000..627e72f --- /dev/null +++ b/src/Seq.Api/Model/Indexes/IndexEntity.cs @@ -0,0 +1,33 @@ +namespace Seq.Api.Model.Indexes +{ + /// + /// Model type specifically for the Data > Indexes list. + /// + public class IndexEntity: Entity + { + /// + /// The `Id` of the associated entity (Signal, Alert or Expression index). + /// + public string IndexedEntityId { get; set; } + + /// + /// The type of this index. + /// + public IndexedEntityType IndexedEntityType { get; set; } + + /// + /// The owner / creator of this index. + /// + public string OwnerUsername { get; set; } + + /// + /// The name of this index. May not be applicable to all index types. + /// + public string Label { get; set; } + + /// + /// The storage used by this index. + /// + public ulong StorageBytes { get; set; } + } +} diff --git a/src/Seq.Api/Model/Indexes/IndexedEntityType.cs b/src/Seq.Api/Model/Indexes/IndexedEntityType.cs new file mode 100644 index 0000000..cdfb60b --- /dev/null +++ b/src/Seq.Api/Model/Indexes/IndexedEntityType.cs @@ -0,0 +1,23 @@ +namespace Seq.Api.Model.Indexes +{ + /// + /// The type of the index. + /// + public enum IndexedEntityType + { + /// + /// A predicate index for a signal expression. + /// + Signal, + + /// + /// An expression index. + /// + ExpressionIndex, + + /// + /// A predicate index for an alert filter. + /// + Alert, + } +} \ No newline at end of file diff --git a/src/Seq.Api/Model/Indexing/ExpressionIndexEntity.cs b/src/Seq.Api/Model/Indexing/ExpressionIndexEntity.cs new file mode 100644 index 0000000..e0d3b86 --- /dev/null +++ b/src/Seq.Api/Model/Indexing/ExpressionIndexEntity.cs @@ -0,0 +1,18 @@ +namespace Seq.Api.Model.Indexing +{ + /// + /// An index based on an expression. + /// + public class ExpressionIndexEntity: Entity + { + /// + /// The expression to be indexed. + /// + public string Expression { get; set; } + + /// + /// A user-provided description of the index. + /// + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/src/Seq.Api/Model/Settings/SettingName.cs b/src/Seq.Api/Model/Settings/SettingName.cs index 1a36756..9609e57 100644 --- a/src/Seq.Api/Model/Settings/SettingName.cs +++ b/src/Seq.Api/Model/Settings/SettingName.cs @@ -15,6 +15,7 @@ using System; using Seq.Api.Model.Apps; using Seq.Api.Model.Updates; +using Seq.Api.Model.Users; using Seq.Api.ResourceGroups; namespace Seq.Api.Model.Settings @@ -124,6 +125,16 @@ public enum SettingName /// Seq will stop accepting new events. /// MinimumFreeStorageSpace, + + /// + /// A dictionary of `(string, string)` pairs that will be used to initialize the + /// property when preparing new user entities + /// with , and with automatically + /// provisioning SSO users (when enabled). + /// + /// User preference keys are unconstrained; the Seq UI uses a number of these, but + /// alternative interfaces and integrations may add additional items to this collection. + NewUserPreferences, /// /// A comma-separated list of role ids that will be assigned to new users by default. diff --git a/src/Seq.Api/Model/Signals/SignalEntity.cs b/src/Seq.Api/Model/Signals/SignalEntity.cs index 9c90ba2..82fd86d 100644 --- a/src/Seq.Api/Model/Signals/SignalEntity.cs +++ b/src/Seq.Api/Model/Signals/SignalEntity.cs @@ -67,6 +67,11 @@ public SignalEntity() /// If true, the signal can only be modified by users with the permission. /// public bool IsProtected { get; set; } + + /// + /// If true, the signal has no backing index. + /// + public bool IsIndexSuppressed { get; set; } /// /// How the signal is grouped in the Seq UI. diff --git a/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs b/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs new file mode 100644 index 0000000..5635915 --- /dev/null +++ b/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Seq.Api.Model; +using Seq.Api.Model.Indexing; + +namespace Seq.Api.ResourceGroups +{ + /// + /// Perform operations on expression indexes. + /// + public class ExpressionIndexesResourceGroup: ApiResourceGroup + { + internal ExpressionIndexesResourceGroup(ILoadResourceGroup connection) : base("ExpressionIndexes", connection) + { + } + + /// + /// Retrieve expression indexes. + /// + /// allowing the operation to be canceled. + /// A list containing matching expression indexes. + public async Task> ListAsync(CancellationToken cancellationToken = default) + { + return await GroupListAsync("Items", cancellationToken: cancellationToken).ConfigureAwait(false); + } + + /// + /// Construct an expression index with server defaults pre-initialized. + /// + /// allowing the operation to be canceled. + /// The unsaved expression index. + public async Task TemplateAsync(CancellationToken cancellationToken = default) + { + return await GroupGetAsync("Template", cancellationToken: cancellationToken).ConfigureAwait(false); + } + + /// + /// Add a new expression index. + /// + /// The expression index to add. + /// A allowing the operation to be canceled. + /// The expression index, with server-allocated properties such as initialized. + public async Task AddAsync(ExpressionIndexEntity entity, CancellationToken cancellationToken = default) + { + return await GroupCreateAsync(entity, cancellationToken: cancellationToken).ConfigureAwait(false); + } + + /// + /// Remove an existing expression index. + /// + /// The expression index to remove. + /// A allowing the operation to be canceled. + /// A task indicating completion. + public async Task RemoveAsync(ExpressionIndexEntity entity, CancellationToken cancellationToken = default) + { + await Client.DeleteAsync(entity, "Self", entity, cancellationToken: cancellationToken).ConfigureAwait(false); + } + } +} \ No newline at end of file diff --git a/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs b/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs new file mode 100644 index 0000000..5c8038a --- /dev/null +++ b/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Seq.Api.Model.Alerting; +using Seq.Api.Model.Indexes; +using Seq.Api.Model.Indexing; +using Seq.Api.Model.Signals; + +namespace Seq.Api.ResourceGroups +{ + /// + /// Statistics about indexes. + /// + public class IndexesResourceGroup : ApiResourceGroup + { + internal IndexesResourceGroup(ILoadResourceGroup connection) + : base("Indexes", connection) + { + } + /// + /// Retrieve the index with the given id; throws if the entity does not exist. + /// + /// The id of the index. + /// A allowing the operation to be canceled. + /// The index. + public async Task FindAsync(string id, CancellationToken cancellationToken = default) + { + if (id == null) throw new ArgumentNullException(nameof(id)); + return await GroupGetAsync("Item", new Dictionary { { "id", id } }, cancellationToken).ConfigureAwait(false); + } + + + /// + /// Retrieve statistics on all indexes. + /// + /// allowing the operation to be canceled. + /// A list containing matching expression indexes. + public async Task> ListAsync(CancellationToken cancellationToken = default) + { + return await GroupListAsync("Items", cancellationToken: cancellationToken).ConfigureAwait(false); + } + + /// + /// Suppress an index. Not all index types can be suppressed: signal indexes do support suppression, in the case + /// of which the flag will be set to . + /// Expression indexes can only be suppressed by deleting the associated + /// and alert indexes can only be suppressed by deleting the corresponding . + /// + /// The index to suppress. + /// A allowing the operation to be canceled. + /// A task indicating completion. + public async Task SuppressAsync(IndexEntity entity, CancellationToken cancellationToken = default) + { + await Client.DeleteAsync(entity, "Self", entity, cancellationToken: cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs b/src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs index d74c680..7249714 100644 --- a/src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs @@ -78,6 +78,7 @@ public async Task AddAsync(SignalEntity entity, CancellationToken { return await GroupCreateAsync(entity, cancellationToken: cancellationToken).ConfigureAwait(false); } + /// /// Remove an existing signal. /// diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index 13e4ee2..9eed51c 100644 --- a/src/Seq.Api/Seq.Api.csproj +++ b/src/Seq.Api/Seq.Api.csproj @@ -1,7 +1,7 @@ Client library for the Seq HTTP API. - 2024.2.0 + 2024.3.0 Datalust;Contributors netstandard2.0;net6.0 true diff --git a/src/Seq.Api/SeqConnection.cs b/src/Seq.Api/SeqConnection.cs index 35df2ce..6032e27 100644 --- a/src/Seq.Api/SeqConnection.cs +++ b/src/Seq.Api/SeqConnection.cs @@ -149,12 +149,22 @@ public void Dispose() /// Perform operations on queries and filter expressions. /// public ExpressionsResourceGroup Expressions => new ExpressionsResourceGroup(this); + + /// + /// Perform operations on expression indexes. + /// + public ExpressionIndexesResourceGroup ExpressionIndexes => new ExpressionIndexesResourceGroup(this); /// /// Perform operations on NuGet feeds. /// public FeedsResourceGroup Feeds => new FeedsResourceGroup(this); + /// + /// Statistics about indexes. + /// + public IndexesResourceGroup Indexes => new IndexesResourceGroup(this); + /// /// Perform operations on the Seq license certificate. /// From bca7325edfea76483989d6f82d61b981c9c52a1b Mon Sep 17 00:00:00 2001 From: Liam McLennan Date: Mon, 22 Apr 2024 10:49:56 +1000 Subject: [PATCH 3/6] Updated comment. --- src/Seq.Api/Model/Indexes/IndexEntity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Seq.Api/Model/Indexes/IndexEntity.cs b/src/Seq.Api/Model/Indexes/IndexEntity.cs index 627e72f..c2ea190 100644 --- a/src/Seq.Api/Model/Indexes/IndexEntity.cs +++ b/src/Seq.Api/Model/Indexes/IndexEntity.cs @@ -1,7 +1,7 @@ -namespace Seq.Api.Model.Indexes + namespace Seq.Api.Model.Indexes { /// - /// Model type specifically for the Data > Indexes list. + /// An index over the event stream. May be one of several types discriminated by . /// public class IndexEntity: Entity { From 2d480d4991622948325c3f60265f94ce8e38a28d Mon Sep 17 00:00:00 2001 From: Liam McLennan Date: Mon, 22 Apr 2024 14:39:11 +1000 Subject: [PATCH 4/6] IndexesResourceGroup.cs Find should return an `IndexEntity`. --- src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs b/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs index 5c8038a..5ee3f74 100644 --- a/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/IndexesResourceGroup.cs @@ -18,19 +18,19 @@ internal IndexesResourceGroup(ILoadResourceGroup connection) : base("Indexes", connection) { } + /// /// Retrieve the index with the given id; throws if the entity does not exist. /// /// The id of the index. /// A allowing the operation to be canceled. /// The index. - public async Task FindAsync(string id, CancellationToken cancellationToken = default) + public async Task FindAsync(string id, CancellationToken cancellationToken = default) { if (id == null) throw new ArgumentNullException(nameof(id)); - return await GroupGetAsync("Item", new Dictionary { { "id", id } }, cancellationToken).ConfigureAwait(false); + return await GroupGetAsync("Item", new Dictionary { { "id", id } }, cancellationToken).ConfigureAwait(false); } - - + /// /// Retrieve statistics on all indexes. /// From 83a2dcaab48430e4557349ac0a385ccb0fa5d2d8 Mon Sep 17 00:00:00 2001 From: Liam McLennan Date: Tue, 23 Apr 2024 09:17:10 +1000 Subject: [PATCH 5/6] Add ExpressionIndexesResourceGroup.FindAsync --- .../ExpressionIndexesResourceGroup.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs b/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs index 5635915..fb4c550 100644 --- a/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs @@ -1,7 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Seq.Api.Model; +using Seq.Api.Model.Indexes; using Seq.Api.Model.Indexing; namespace Seq.Api.ResourceGroups @@ -24,6 +26,18 @@ public async Task> ListAsync(CancellationToken cance { return await GroupListAsync("Items", cancellationToken: cancellationToken).ConfigureAwait(false); } + + /// + /// Retrieve the expression index with the given id; throws if the entity does not exist. + /// + /// The id of the expression index. + /// A allowing the operation to be canceled. + /// The expression index. + public async Task FindAsync(string id, CancellationToken cancellationToken = default) + { + if (id == null) throw new ArgumentNullException(nameof(id)); + return await GroupGetAsync("Item", new Dictionary { { "id", id } }, cancellationToken).ConfigureAwait(false); + } /// /// Construct an expression index with server defaults pre-initialized. From 017e078113f836a0d6884b01de3a1a9a03be49c1 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Mon, 29 Apr 2024 10:36:19 +1000 Subject: [PATCH 6/6] Rename ServerMetricsEntity to ServerMetricsPart (no meaningful entity-like behavior); add indexing/write time metrics; add ExpressionIndexesResourceGroup.FindAsync() --- ...erMetricsEntity.cs => ServerMetricsPart.cs} | 18 ++++++++++++++---- src/Seq.Api/Model/Indexes/IndexEntity.cs | 2 +- .../ResourceGroups/DiagnosticsResourceGroup.cs | 4 ++-- .../ExpressionIndexesResourceGroup.cs | 1 - 4 files changed, 17 insertions(+), 8 deletions(-) rename src/Seq.Api/Model/Diagnostics/{ServerMetricsEntity.cs => ServerMetricsPart.cs} (80%) diff --git a/src/Seq.Api/Model/Diagnostics/ServerMetricsEntity.cs b/src/Seq.Api/Model/Diagnostics/ServerMetricsPart.cs similarity index 80% rename from src/Seq.Api/Model/Diagnostics/ServerMetricsEntity.cs rename to src/Seq.Api/Model/Diagnostics/ServerMetricsPart.cs index 9342d2c..9b75681 100644 --- a/src/Seq.Api/Model/Diagnostics/ServerMetricsEntity.cs +++ b/src/Seq.Api/Model/Diagnostics/ServerMetricsPart.cs @@ -13,19 +13,19 @@ // limitations under the License. using System; -using System.Collections.Generic; namespace Seq.Api.Model.Diagnostics { /// /// Metrics describing the state and performance of the Seq server. /// - public class ServerMetricsEntity : Entity + /// This information is not preserved across server restarts or fail-over. + public class ServerMetricsPart { /// - /// Construct a . + /// Construct a . /// - public ServerMetricsEntity() + public ServerMetricsPart() { } @@ -34,6 +34,16 @@ public ServerMetricsEntity() /// public long? EventStoreDiskRemainingBytes { get; set; } + /// + /// The total time spent indexing the event store in the last 24 hours. + /// + public TimeSpan EventStoreIndexingTimeLastDay { get; set; } + + /// + /// The total time spent writing events to disk in the last minute. + /// + public TimeSpan EventStoreWriteTimeLastMinute { get; set; } + /// /// The number of events that arrived at the ingestion endpoint in the past minute. /// diff --git a/src/Seq.Api/Model/Indexes/IndexEntity.cs b/src/Seq.Api/Model/Indexes/IndexEntity.cs index c2ea190..6b92295 100644 --- a/src/Seq.Api/Model/Indexes/IndexEntity.cs +++ b/src/Seq.Api/Model/Indexes/IndexEntity.cs @@ -1,4 +1,4 @@ - namespace Seq.Api.Model.Indexes +namespace Seq.Api.Model.Indexes { /// /// An index over the event stream. May be one of several types discriminated by . diff --git a/src/Seq.Api/ResourceGroups/DiagnosticsResourceGroup.cs b/src/Seq.Api/ResourceGroups/DiagnosticsResourceGroup.cs index d1616b9..5ba40d8 100644 --- a/src/Seq.Api/ResourceGroups/DiagnosticsResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/DiagnosticsResourceGroup.cs @@ -38,9 +38,9 @@ internal DiagnosticsResourceGroup(ILoadResourceGroup connection) /// /// A allowing the operation to be canceled. /// Current server metrics. - public async Task GetServerMetricsAsync(CancellationToken cancellationToken = default) + public async Task GetServerMetricsAsync(CancellationToken cancellationToken = default) { - return await GroupGetAsync("ServerMetrics", cancellationToken: cancellationToken).ConfigureAwait(false); + return await GroupGetAsync("ServerMetrics", cancellationToken: cancellationToken).ConfigureAwait(false); } /// diff --git a/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs b/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs index fb4c550..b804093 100644 --- a/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/ExpressionIndexesResourceGroup.cs @@ -3,7 +3,6 @@ using System.Threading; using System.Threading.Tasks; using Seq.Api.Model; -using Seq.Api.Model.Indexes; using Seq.Api.Model.Indexing; namespace Seq.Api.ResourceGroups