From 23bfb355b58682a374a4bd41487d15823c6e95d8 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 16 May 2017 21:24:33 +1000 Subject: [PATCH 01/10] Dev version bump [Skip CI] --- src/Seq.Api/Seq.Api.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index 4490b55..110a003 100644 --- a/src/Seq.Api/Seq.Api.csproj +++ b/src/Seq.Api/Seq.Api.csproj @@ -1,8 +1,8 @@ - + Client library for the Seq HTTP API. - 4.0.0 + 4.0.1 Datalust;Contributors netstandard1.3;net45 $(NoWarn);CS1591 From 377cc0d3cc2795cc4aee5a6c731bf939b466d635 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 15 Nov 2017 12:44:59 +1000 Subject: [PATCH 02/10] Update dev version to 4.1, will now align API major.minor with corresponding Seq version [Skip CI] --- src/Seq.Api/Seq.Api.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index 110a003..884295b 100644 --- a/src/Seq.Api/Seq.Api.csproj +++ b/src/Seq.Api/Seq.Api.csproj @@ -2,7 +2,7 @@ Client library for the Seq HTTP API. - 4.0.1 + 4.1.0 Datalust;Contributors netstandard1.3;net45 $(NoWarn);CS1591 From 1f5ba0eeab9fa3ed32acb695299bbd2ca54df5c9 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 15 Nov 2017 12:46:56 +1000 Subject: [PATCH 03/10] Aligning to 4.2 - no 4.1 related changes to push out [Skip CI] --- src/Seq.Api/Seq.Api.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index 884295b..2a8796d 100644 --- a/src/Seq.Api/Seq.Api.csproj +++ b/src/Seq.Api/Seq.Api.csproj @@ -2,7 +2,7 @@ Client library for the Seq HTTP API. - 4.1.0 + 4.2.0 Datalust;Contributors netstandard1.3;net45 $(NoWarn);CS1591 From c4e082ff8910b70924830722d68b07a5464aa398 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 7 Dec 2017 11:00:59 +1000 Subject: [PATCH 04/10] Update to match Seq 4.2 * Signal expressions everywhere - apps, dashboards, retention policies, events and data, `signal=expression` instead of `intersect=ids` in URI params * `SignalEntity.Grouping` and `ExplicitGroupName` * New "v5" media type to reflect incompatibility of signal expressions with old APIs * Project, packaging and folder layout improvements * App instance rate per minute * Correct diagnostics properties * Fixed/strongly-typed `DeleteResultPart` * `LicenseEntity.CanRenewOnlineNow` * `ChartDisplayStylePart` * Fixed `ChartQueryPart.DisplayStyle` (property now, not field) * `OrangePurple` measurement palette * Value measurement display type --- src/Seq.Api/Api/Model/Backups/BackupEntity.cs | 11 --- .../Api/ResourceGroups/DataResourceGroup.cs | 64 ------------- src/Seq.Api/{Api => }/Client/SeqApiClient.cs | 4 +- .../{Api => }/Client/SeqApiException.cs | 0 .../Model/AppInstances/AppInstanceEntity.cs | 11 ++- src/Seq.Api/{Api => }/Model/Apps/AppEntity.cs | 0 .../{Api => }/Model/Apps/AppPackagePart.cs | 0 .../{Api => }/Model/Apps/AppSettingPart.cs | 0 .../Data/QueryExecutionStatisticsPart.cs | 0 .../{Api => }/Model/Data/QueryResultPart.cs | 0 .../{Api => }/Model/Data/TimeSlicePart.cs | 0 .../{Api => }/Model/Data/TimeseriesPart.cs | 0 .../Model/Diagnostics/RunningTaskPart.cs | 0 .../Model/Diagnostics/ServerMetricsEntity.cs | 5 +- .../Model/Diagnostics/ServerStatusPart.cs | 0 .../Model/Diagnostics/StatusMessagePart.cs | 0 src/Seq.Api/{Api => }/Model/Entity.cs | 0 src/Seq.Api/Model/Events/DeleteResultPart.cs | 7 ++ .../{Api => }/Model/Events/EventEntity.cs | 0 .../Model/Events/EventInputResultPart.cs | 0 .../Model/Events/EventPropertyPart.cs | 0 .../Model/Events/MessageTemplateTokenPart.cs | 0 .../{Api => }/Model/Events/ResultSetPart.cs | 0 .../Model/Expressions/ExpressionPart.cs | 0 .../Model/Expressions/SqlExpressionPart.cs | 0 .../{Api => }/Model/Feeds/NuGetFeedEntity.cs | 0 src/Seq.Api/{Api => }/Model/ILinked.cs | 0 .../{Api => }/Model/Inputs/ApiKeyEntity.cs | 0 .../Model/Inputs/ApiKeyMetricsPart.cs | 0 .../Model/Inputs/InputAppliedPropertyPart.cs | 0 .../{Api => }/Model/License/LicenseEntity.cs | 1 + src/Seq.Api/{Api => }/Model/Link.cs | 0 src/Seq.Api/{Api => }/Model/LinkCollection.cs | 0 .../Model/LogEvents/LogEventLevel.cs | 0 .../{Api => }/Model/Monitoring/AlertPart.cs | 0 .../Model/Monitoring/ChartDisplayStylePart.cs | 8 ++ .../{Api => }/Model/Monitoring/ChartPart.cs | 7 +- .../Model/Monitoring/ChartQueryPart.cs | 5 +- .../Model/Monitoring/DashboardEntity.cs | 3 +- .../Monitoring/MeasurementDisplayPalette.cs | 3 +- .../Monitoring/MeasurementDisplayStylePart.cs | 0 .../Monitoring/MeasurementDisplayType.cs | 3 +- .../Model/Monitoring/MeasurementPart.cs | 0 .../Model/Permalinks/PermalinkEntity.cs | 0 src/Seq.Api/{Api => }/Model/ResourceGroup.cs | 0 .../Model/Retention/RetentionPolicyEntity.cs | 4 + .../{Api => }/Model/Root/RootEntity.cs | 0 .../{Api => }/Model/Settings/SettingEntity.cs | 2 +- .../{Api => }/Model/Settings/SettingName.cs | 0 .../Model/Shared/DeferredRequestEntity.cs | 0 .../{Api => }/Model/Shared/ResultSetStatus.cs | 0 .../{Api => }/Model/Shared/StatisticsPart.cs | 0 .../{Api => }/Model/Signals/SignalEntity.cs | 4 + .../Model/Signals/SignalExpressionKind.cs | 10 +++ .../Model/Signals/SignalExpressionPart.cs | 90 +++++++++++++++++++ .../Model/Signals/SignalFilterPart.cs | 0 src/Seq.Api/Model/Signals/SignalGrouping.cs | 9 ++ .../Model/Signals/TaggedPropertyPart.cs | 0 .../Model/SqlQueries/SqlQueryEntity.cs | 0 .../Model/Updates/AvailableUpdateEntity.cs | 0 .../Model/Users/AuthProviderInfoPart.cs | 0 .../Model/Users/AuthProvidersPart.cs | 0 .../{Api => }/Model/Users/CredentialsPart.cs | 0 .../Model/Users/SearchHistoryEntity.cs | 0 .../Model/Users/SearchHistoryItemPart.cs | 0 .../Model/Users/SearchHistoryItemStatus.cs | 0 .../{Api => }/Model/Users/UserEntity.cs | 0 src/Seq.Api/Properties/AssemblyInfo.cs | 10 --- .../ResourceGroups/ApiKeysResourceGroup.cs | 0 .../ResourceGroups/ApiResourceGroup.cs | 5 ++ .../AppInstancesResourceGroup.cs | 0 .../ResourceGroups/AppsResourceGroup.cs | 0 .../ResourceGroups/BackupsResourceGroup.cs | 0 .../ResourceGroups/DashboardsResourceGroup.cs | 0 .../ResourceGroups/DataResourceGroup.cs | 86 ++++++++++++++++++ .../DiagnosticsResourceGroup.cs | 0 .../ResourceGroups/EntityResourceGroup.cs | 21 +++++ .../ResourceGroups/EventsResourceGroup.cs | 74 ++++++++++----- .../ExpressionsResourceGroup.cs | 0 .../ResourceGroups/FeedsResourceGroup.cs | 0 .../ResourceGroups/ISeqConnection.cs | 0 .../ResourceGroups/LicensesResourceGroup.cs | 0 .../ResourceGroups/PermalinksResourceGroup.cs | 0 .../RetentionPoliciesResourceGroup.cs | 0 .../ResourceGroups/SettingsResourceGroup.cs | 0 .../ResourceGroups/SignalsResourceGroup.cs | 4 +- .../ResourceGroups/SqlQueriesResourceGroup.cs | 0 .../ResourceGroups/UpdatesResourceGroup.cs | 0 .../ResourceGroups/UsersResourceGroup.cs | 0 src/Seq.Api/Seq.Api.csproj | 43 ++++----- src/Seq.Api/{Api => }/SeqConnection.cs | 1 - .../Serialization/LinkCollectionConverter.cs | 0 .../Streams/ObservableStream.Unsubscriber.cs | 0 .../{Api => }/Streams/ObservableStream.cs | 0 94 files changed, 342 insertions(+), 153 deletions(-) delete mode 100644 src/Seq.Api/Api/Model/Backups/BackupEntity.cs delete mode 100644 src/Seq.Api/Api/ResourceGroups/DataResourceGroup.cs rename src/Seq.Api/{Api => }/Client/SeqApiClient.cs (98%) rename src/Seq.Api/{Api => }/Client/SeqApiException.cs (100%) rename src/Seq.Api/{Api => }/Model/AppInstances/AppInstanceEntity.cs (76%) rename src/Seq.Api/{Api => }/Model/Apps/AppEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Apps/AppPackagePart.cs (100%) rename src/Seq.Api/{Api => }/Model/Apps/AppSettingPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Data/QueryExecutionStatisticsPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Data/QueryResultPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Data/TimeSlicePart.cs (100%) rename src/Seq.Api/{Api => }/Model/Data/TimeseriesPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Diagnostics/RunningTaskPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Diagnostics/ServerMetricsEntity.cs (87%) rename src/Seq.Api/{Api => }/Model/Diagnostics/ServerStatusPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Diagnostics/StatusMessagePart.cs (100%) rename src/Seq.Api/{Api => }/Model/Entity.cs (100%) create mode 100644 src/Seq.Api/Model/Events/DeleteResultPart.cs rename src/Seq.Api/{Api => }/Model/Events/EventEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Events/EventInputResultPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Events/EventPropertyPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Events/MessageTemplateTokenPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Events/ResultSetPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Expressions/ExpressionPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Expressions/SqlExpressionPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Feeds/NuGetFeedEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/ILinked.cs (100%) rename src/Seq.Api/{Api => }/Model/Inputs/ApiKeyEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Inputs/ApiKeyMetricsPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Inputs/InputAppliedPropertyPart.cs (100%) rename src/Seq.Api/{Api => }/Model/License/LicenseEntity.cs (86%) rename src/Seq.Api/{Api => }/Model/Link.cs (100%) rename src/Seq.Api/{Api => }/Model/LinkCollection.cs (100%) rename src/Seq.Api/{Api => }/Model/LogEvents/LogEventLevel.cs (100%) rename src/Seq.Api/{Api => }/Model/Monitoring/AlertPart.cs (100%) create mode 100644 src/Seq.Api/Model/Monitoring/ChartDisplayStylePart.cs rename src/Seq.Api/{Api => }/Model/Monitoring/ChartPart.cs (59%) rename src/Seq.Api/{Api => }/Model/Monitoring/ChartQueryPart.cs (68%) rename src/Seq.Api/{Api => }/Model/Monitoring/DashboardEntity.cs (75%) rename src/Seq.Api/{Api => }/Model/Monitoring/MeasurementDisplayPalette.cs (79%) rename src/Seq.Api/{Api => }/Model/Monitoring/MeasurementDisplayStylePart.cs (100%) rename src/Seq.Api/{Api => }/Model/Monitoring/MeasurementDisplayType.cs (80%) rename src/Seq.Api/{Api => }/Model/Monitoring/MeasurementPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Permalinks/PermalinkEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/ResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/Model/Retention/RetentionPolicyEntity.cs (56%) rename src/Seq.Api/{Api => }/Model/Root/RootEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Settings/SettingEntity.cs (71%) rename src/Seq.Api/{Api => }/Model/Settings/SettingName.cs (100%) rename src/Seq.Api/{Api => }/Model/Shared/DeferredRequestEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Shared/ResultSetStatus.cs (100%) rename src/Seq.Api/{Api => }/Model/Shared/StatisticsPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Signals/SignalEntity.cs (85%) create mode 100644 src/Seq.Api/Model/Signals/SignalExpressionKind.cs create mode 100644 src/Seq.Api/Model/Signals/SignalExpressionPart.cs rename src/Seq.Api/{Api => }/Model/Signals/SignalFilterPart.cs (100%) create mode 100644 src/Seq.Api/Model/Signals/SignalGrouping.cs rename src/Seq.Api/{Api => }/Model/Signals/TaggedPropertyPart.cs (100%) rename src/Seq.Api/{Api => }/Model/SqlQueries/SqlQueryEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Updates/AvailableUpdateEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/AuthProviderInfoPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/AuthProvidersPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/CredentialsPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/SearchHistoryEntity.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/SearchHistoryItemPart.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/SearchHistoryItemStatus.cs (100%) rename src/Seq.Api/{Api => }/Model/Users/UserEntity.cs (100%) delete mode 100644 src/Seq.Api/Properties/AssemblyInfo.cs rename src/Seq.Api/{Api => }/ResourceGroups/ApiKeysResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/ApiResourceGroup.cs (94%) rename src/Seq.Api/{Api => }/ResourceGroups/AppInstancesResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/AppsResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/BackupsResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/DashboardsResourceGroup.cs (100%) create mode 100644 src/Seq.Api/ResourceGroups/DataResourceGroup.cs rename src/Seq.Api/{Api => }/ResourceGroups/DiagnosticsResourceGroup.cs (100%) create mode 100644 src/Seq.Api/ResourceGroups/EntityResourceGroup.cs rename src/Seq.Api/{Api => }/ResourceGroups/EventsResourceGroup.cs (66%) rename src/Seq.Api/{Api => }/ResourceGroups/ExpressionsResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/FeedsResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/ISeqConnection.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/LicensesResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/PermalinksResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/RetentionPoliciesResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/SettingsResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/SignalsResourceGroup.cs (88%) rename src/Seq.Api/{Api => }/ResourceGroups/SqlQueriesResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/UpdatesResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/ResourceGroups/UsersResourceGroup.cs (100%) rename src/Seq.Api/{Api => }/SeqConnection.cs (99%) rename src/Seq.Api/{Api => }/Serialization/LinkCollectionConverter.cs (100%) rename src/Seq.Api/{Api => }/Streams/ObservableStream.Unsubscriber.cs (100%) rename src/Seq.Api/{Api => }/Streams/ObservableStream.cs (100%) diff --git a/src/Seq.Api/Api/Model/Backups/BackupEntity.cs b/src/Seq.Api/Api/Model/Backups/BackupEntity.cs deleted file mode 100644 index a59bd0b..0000000 --- a/src/Seq.Api/Api/Model/Backups/BackupEntity.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Seq.Api.Model.Backups -{ - public class BackupEntity : Entity - { - public string CreatedAt { get; set; } - public string Filename { get; set; } - public long FileSizeBytes { get; set; } - } -} diff --git a/src/Seq.Api/Api/ResourceGroups/DataResourceGroup.cs b/src/Seq.Api/Api/ResourceGroups/DataResourceGroup.cs deleted file mode 100644 index 99d0259..0000000 --- a/src/Seq.Api/Api/ResourceGroups/DataResourceGroup.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Seq.Api.Model.Data; -using Seq.Api.Model.Signals; - -namespace Seq.Api.ResourceGroups -{ - public class DataResourceGroup : ApiResourceGroup - { - internal DataResourceGroup(ISeqConnection connection) - : base("Data", connection) - { - } - - public async Task QueryAsync( - string query, - DateTime rangeStartUtc, - DateTime? rangeEndUtc = null, - SignalEntity signal = null, - string[] intersectIds = null) - { - SignalEntity body; - Dictionary parameters; - MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, intersectIds, out body, out parameters); - return await GroupPostAsync("Query", body, parameters).ConfigureAwait(false); - } - - public async Task QueryCsvAsync( - string query, - DateTime rangeStartUtc, - DateTime? rangeEndUtc = null, - SignalEntity signal = null, - string[] intersectIds = null) - { - SignalEntity body; - Dictionary parameters; - MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, intersectIds, out body, out parameters); - parameters.Add("format", "text/csv"); - return await GroupPostReadStringAsync("Query", body, parameters).ConfigureAwait(false); - } - - static void MakeParameters(string query, DateTime rangeStartUtc, DateTime? rangeEndUtc, SignalEntity signal, - string[] intersectIds, out SignalEntity body, out Dictionary parameters) - { - parameters = new Dictionary - { - {"q", query}, - {nameof(rangeStartUtc), rangeStartUtc} - }; - - if (rangeEndUtc != null) - { - parameters.Add(nameof(rangeEndUtc), rangeEndUtc.Value); - } - if (intersectIds != null && intersectIds.Length > 0) - { - parameters.Add(nameof(intersectIds), string.Join(",", intersectIds)); - } - - body = signal ?? new SignalEntity(); - } - } -} diff --git a/src/Seq.Api/Api/Client/SeqApiClient.cs b/src/Seq.Api/Client/SeqApiClient.cs similarity index 98% rename from src/Seq.Api/Api/Client/SeqApiClient.cs rename to src/Seq.Api/Client/SeqApiClient.cs index e118117..2963a58 100644 --- a/src/Seq.Api/Api/Client/SeqApiClient.cs +++ b/src/Seq.Api/Client/SeqApiClient.cs @@ -26,7 +26,7 @@ public class SeqApiClient : IDisposable // Future versions of Seq may not completely support v1 features, however // providing this as an Accept header will ensure what compatibility is available // can be utilised. - const string SeqApiV4MediaType = "application/vnd.continuousit.seq.v4+json"; + const string SeqApiV5MediaType = "application/vnd.datalust.seq.v5+json"; readonly HttpClient _httpClient; readonly CookieContainer _cookies = new CookieContainer(); @@ -170,7 +170,7 @@ async Task HttpSendAsync(HttpRequestMessage request) if (_apiKey != null) request.Headers.Add("X-Seq-ApiKey", _apiKey); - request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(SeqApiV4MediaType)); + request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(SeqApiV5MediaType)); var response = await _httpClient.SendAsync(request).ConfigureAwait(false); var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/src/Seq.Api/Api/Client/SeqApiException.cs b/src/Seq.Api/Client/SeqApiException.cs similarity index 100% rename from src/Seq.Api/Api/Client/SeqApiException.cs rename to src/Seq.Api/Client/SeqApiException.cs diff --git a/src/Seq.Api/Api/Model/AppInstances/AppInstanceEntity.cs b/src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs similarity index 76% rename from src/Seq.Api/Api/Model/AppInstances/AppInstanceEntity.cs rename to src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs index 3d21a7d..67ae606 100644 --- a/src/Seq.Api/Api/Model/AppInstances/AppInstanceEntity.cs +++ b/src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Seq.Api.Model.Signals; namespace Seq.Api.Model.AppInstances { @@ -8,8 +9,10 @@ public class AppInstanceEntity : Entity public AppInstanceEntity() { Settings = new Dictionary(); - SignalIds = new List(); EventsPerSuppressionWindow = 1; +#pragma warning disable 618 + SignalIds = new List(); +#pragma warning restore 618 } public string Title { get; set; } @@ -17,10 +20,14 @@ public AppInstanceEntity() public string AppId { get; set; } public Dictionary Settings { get; set; } public TimeSpan? ArrivalWindow { get; set; } - public List SignalIds { get; set; } + public SignalExpressionPart InputSignalExpression { get; set; } public bool DisallowManualInput { get; set; } public int ChannelCapacity { get; set; } public TimeSpan SuppressionTime { get; set; } public int EventsPerSuppressionWindow { get; set; } + public int? ProcessedEventsPerMinute { get; set; } + + [Obsolete("Replaced by InputSignalExpression.")] + public List SignalIds { get; set; } } } diff --git a/src/Seq.Api/Api/Model/Apps/AppEntity.cs b/src/Seq.Api/Model/Apps/AppEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Apps/AppEntity.cs rename to src/Seq.Api/Model/Apps/AppEntity.cs diff --git a/src/Seq.Api/Api/Model/Apps/AppPackagePart.cs b/src/Seq.Api/Model/Apps/AppPackagePart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Apps/AppPackagePart.cs rename to src/Seq.Api/Model/Apps/AppPackagePart.cs diff --git a/src/Seq.Api/Api/Model/Apps/AppSettingPart.cs b/src/Seq.Api/Model/Apps/AppSettingPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Apps/AppSettingPart.cs rename to src/Seq.Api/Model/Apps/AppSettingPart.cs diff --git a/src/Seq.Api/Api/Model/Data/QueryExecutionStatisticsPart.cs b/src/Seq.Api/Model/Data/QueryExecutionStatisticsPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Data/QueryExecutionStatisticsPart.cs rename to src/Seq.Api/Model/Data/QueryExecutionStatisticsPart.cs diff --git a/src/Seq.Api/Api/Model/Data/QueryResultPart.cs b/src/Seq.Api/Model/Data/QueryResultPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Data/QueryResultPart.cs rename to src/Seq.Api/Model/Data/QueryResultPart.cs diff --git a/src/Seq.Api/Api/Model/Data/TimeSlicePart.cs b/src/Seq.Api/Model/Data/TimeSlicePart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Data/TimeSlicePart.cs rename to src/Seq.Api/Model/Data/TimeSlicePart.cs diff --git a/src/Seq.Api/Api/Model/Data/TimeseriesPart.cs b/src/Seq.Api/Model/Data/TimeseriesPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Data/TimeseriesPart.cs rename to src/Seq.Api/Model/Data/TimeseriesPart.cs diff --git a/src/Seq.Api/Api/Model/Diagnostics/RunningTaskPart.cs b/src/Seq.Api/Model/Diagnostics/RunningTaskPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Diagnostics/RunningTaskPart.cs rename to src/Seq.Api/Model/Diagnostics/RunningTaskPart.cs diff --git a/src/Seq.Api/Api/Model/Diagnostics/ServerMetricsEntity.cs b/src/Seq.Api/Model/Diagnostics/ServerMetricsEntity.cs similarity index 87% rename from src/Seq.Api/Api/Model/Diagnostics/ServerMetricsEntity.cs rename to src/Seq.Api/Model/Diagnostics/ServerMetricsEntity.cs index dba4d1c..f46dcb9 100644 --- a/src/Seq.Api/Api/Model/Diagnostics/ServerMetricsEntity.cs +++ b/src/Seq.Api/Model/Diagnostics/ServerMetricsEntity.cs @@ -10,11 +10,10 @@ public ServerMetricsEntity() RunningTasks = new List(); } - public double EventStoreDaysRecorded { get; set; } public double EventStoreDaysCached { get; set; } public int EventStoreEventsCached { get; set; } - public DateTime? EventStoreFirstSegmentDateUtc { get; set; } - public DateTime? EventStoreLastSegmentDateUtc { get; set; } + public DateTime? EventStoreFirstExtentRangeStartUtc { get; set; } + public DateTime? EventStoreLastExtentRangeEndUtc { get; set; } public long EventStoreDiskRemainingBytes { get; set; } public int EndpointArrivalsPerMinute { get; set; } diff --git a/src/Seq.Api/Api/Model/Diagnostics/ServerStatusPart.cs b/src/Seq.Api/Model/Diagnostics/ServerStatusPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Diagnostics/ServerStatusPart.cs rename to src/Seq.Api/Model/Diagnostics/ServerStatusPart.cs diff --git a/src/Seq.Api/Api/Model/Diagnostics/StatusMessagePart.cs b/src/Seq.Api/Model/Diagnostics/StatusMessagePart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Diagnostics/StatusMessagePart.cs rename to src/Seq.Api/Model/Diagnostics/StatusMessagePart.cs diff --git a/src/Seq.Api/Api/Model/Entity.cs b/src/Seq.Api/Model/Entity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Entity.cs rename to src/Seq.Api/Model/Entity.cs diff --git a/src/Seq.Api/Model/Events/DeleteResultPart.cs b/src/Seq.Api/Model/Events/DeleteResultPart.cs new file mode 100644 index 0000000..f9e6e43 --- /dev/null +++ b/src/Seq.Api/Model/Events/DeleteResultPart.cs @@ -0,0 +1,7 @@ +namespace Seq.Api.Model.Events +{ + public class DeleteResultPart + { + public long DeletedEventCount { get; set; } + } +} diff --git a/src/Seq.Api/Api/Model/Events/EventEntity.cs b/src/Seq.Api/Model/Events/EventEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Events/EventEntity.cs rename to src/Seq.Api/Model/Events/EventEntity.cs diff --git a/src/Seq.Api/Api/Model/Events/EventInputResultPart.cs b/src/Seq.Api/Model/Events/EventInputResultPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Events/EventInputResultPart.cs rename to src/Seq.Api/Model/Events/EventInputResultPart.cs diff --git a/src/Seq.Api/Api/Model/Events/EventPropertyPart.cs b/src/Seq.Api/Model/Events/EventPropertyPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Events/EventPropertyPart.cs rename to src/Seq.Api/Model/Events/EventPropertyPart.cs diff --git a/src/Seq.Api/Api/Model/Events/MessageTemplateTokenPart.cs b/src/Seq.Api/Model/Events/MessageTemplateTokenPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Events/MessageTemplateTokenPart.cs rename to src/Seq.Api/Model/Events/MessageTemplateTokenPart.cs diff --git a/src/Seq.Api/Api/Model/Events/ResultSetPart.cs b/src/Seq.Api/Model/Events/ResultSetPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Events/ResultSetPart.cs rename to src/Seq.Api/Model/Events/ResultSetPart.cs diff --git a/src/Seq.Api/Api/Model/Expressions/ExpressionPart.cs b/src/Seq.Api/Model/Expressions/ExpressionPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Expressions/ExpressionPart.cs rename to src/Seq.Api/Model/Expressions/ExpressionPart.cs diff --git a/src/Seq.Api/Api/Model/Expressions/SqlExpressionPart.cs b/src/Seq.Api/Model/Expressions/SqlExpressionPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Expressions/SqlExpressionPart.cs rename to src/Seq.Api/Model/Expressions/SqlExpressionPart.cs diff --git a/src/Seq.Api/Api/Model/Feeds/NuGetFeedEntity.cs b/src/Seq.Api/Model/Feeds/NuGetFeedEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Feeds/NuGetFeedEntity.cs rename to src/Seq.Api/Model/Feeds/NuGetFeedEntity.cs diff --git a/src/Seq.Api/Api/Model/ILinked.cs b/src/Seq.Api/Model/ILinked.cs similarity index 100% rename from src/Seq.Api/Api/Model/ILinked.cs rename to src/Seq.Api/Model/ILinked.cs diff --git a/src/Seq.Api/Api/Model/Inputs/ApiKeyEntity.cs b/src/Seq.Api/Model/Inputs/ApiKeyEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Inputs/ApiKeyEntity.cs rename to src/Seq.Api/Model/Inputs/ApiKeyEntity.cs diff --git a/src/Seq.Api/Api/Model/Inputs/ApiKeyMetricsPart.cs b/src/Seq.Api/Model/Inputs/ApiKeyMetricsPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Inputs/ApiKeyMetricsPart.cs rename to src/Seq.Api/Model/Inputs/ApiKeyMetricsPart.cs diff --git a/src/Seq.Api/Api/Model/Inputs/InputAppliedPropertyPart.cs b/src/Seq.Api/Model/Inputs/InputAppliedPropertyPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Inputs/InputAppliedPropertyPart.cs rename to src/Seq.Api/Model/Inputs/InputAppliedPropertyPart.cs diff --git a/src/Seq.Api/Api/Model/License/LicenseEntity.cs b/src/Seq.Api/Model/License/LicenseEntity.cs similarity index 86% rename from src/Seq.Api/Api/Model/License/LicenseEntity.cs rename to src/Seq.Api/Model/License/LicenseEntity.cs index f9a30f8..a071676 100644 --- a/src/Seq.Api/Api/Model/License/LicenseEntity.cs +++ b/src/Seq.Api/Model/License/LicenseEntity.cs @@ -7,5 +7,6 @@ public class LicenseEntity : Entity public bool IsSingleUser { get; set; } public string StatusDescription { get; set; } public bool IsWarning { get; set; } + public bool CanRenewOnlineNow { get; set; } } } diff --git a/src/Seq.Api/Api/Model/Link.cs b/src/Seq.Api/Model/Link.cs similarity index 100% rename from src/Seq.Api/Api/Model/Link.cs rename to src/Seq.Api/Model/Link.cs diff --git a/src/Seq.Api/Api/Model/LinkCollection.cs b/src/Seq.Api/Model/LinkCollection.cs similarity index 100% rename from src/Seq.Api/Api/Model/LinkCollection.cs rename to src/Seq.Api/Model/LinkCollection.cs diff --git a/src/Seq.Api/Api/Model/LogEvents/LogEventLevel.cs b/src/Seq.Api/Model/LogEvents/LogEventLevel.cs similarity index 100% rename from src/Seq.Api/Api/Model/LogEvents/LogEventLevel.cs rename to src/Seq.Api/Model/LogEvents/LogEventLevel.cs diff --git a/src/Seq.Api/Api/Model/Monitoring/AlertPart.cs b/src/Seq.Api/Model/Monitoring/AlertPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Monitoring/AlertPart.cs rename to src/Seq.Api/Model/Monitoring/AlertPart.cs diff --git a/src/Seq.Api/Model/Monitoring/ChartDisplayStylePart.cs b/src/Seq.Api/Model/Monitoring/ChartDisplayStylePart.cs new file mode 100644 index 0000000..16729e1 --- /dev/null +++ b/src/Seq.Api/Model/Monitoring/ChartDisplayStylePart.cs @@ -0,0 +1,8 @@ +namespace Seq.Api.Model.Monitoring +{ + public class ChartDisplayStylePart + { + public int WidthColumns { get; set; } = 6; + public int HeightRows { get; set; } = 1; + } +} diff --git a/src/Seq.Api/Api/Model/Monitoring/ChartPart.cs b/src/Seq.Api/Model/Monitoring/ChartPart.cs similarity index 59% rename from src/Seq.Api/Api/Model/Monitoring/ChartPart.cs rename to src/Seq.Api/Model/Monitoring/ChartPart.cs index 3bc4fb7..3b6be33 100644 --- a/src/Seq.Api/Api/Model/Monitoring/ChartPart.cs +++ b/src/Seq.Api/Model/Monitoring/ChartPart.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; +using Seq.Api.Model.Signals; namespace Seq.Api.Model.Monitoring { public class ChartPart { public string Id { get; set; } - public string Title { get; set; } - - public List SignalIds { get; set; } = new List(); - + public SignalExpressionPart SignalExpression { get; set; } public List Queries { get; set; } = new List(); + public ChartDisplayStylePart DisplayStyle { get; set; } = new ChartDisplayStylePart(); } } diff --git a/src/Seq.Api/Api/Model/Monitoring/ChartQueryPart.cs b/src/Seq.Api/Model/Monitoring/ChartQueryPart.cs similarity index 68% rename from src/Seq.Api/Api/Model/Monitoring/ChartQueryPart.cs rename to src/Seq.Api/Model/Monitoring/ChartQueryPart.cs index 33ca75c..b3800b7 100644 --- a/src/Seq.Api/Api/Model/Monitoring/ChartQueryPart.cs +++ b/src/Seq.Api/Model/Monitoring/ChartQueryPart.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Seq.Api.Model.Signals; namespace Seq.Api.Model.Monitoring { @@ -7,9 +8,9 @@ public class ChartQueryPart public string Id { get; set; } public List Measurements { get; set; } = new List(); public string Where { get; set; } - public List SignalIds { get; set; } = new List(); + public SignalExpressionPart SignalExpression { get; set; } public List GroupBy { get; set; } = new List(); - public MeasurementDisplayStylePart DisplayStyle = new MeasurementDisplayStylePart(); + public MeasurementDisplayStylePart DisplayStyle { get; set; } = new MeasurementDisplayStylePart(); public List Alerts { get; set; } = new List(); } } diff --git a/src/Seq.Api/Api/Model/Monitoring/DashboardEntity.cs b/src/Seq.Api/Model/Monitoring/DashboardEntity.cs similarity index 75% rename from src/Seq.Api/Api/Model/Monitoring/DashboardEntity.cs rename to src/Seq.Api/Model/Monitoring/DashboardEntity.cs index 7158a11..a94b268 100644 --- a/src/Seq.Api/Api/Model/Monitoring/DashboardEntity.cs +++ b/src/Seq.Api/Model/Monitoring/DashboardEntity.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Seq.Api.Model.Signals; namespace Seq.Api.Model.Monitoring { @@ -8,7 +9,7 @@ public class DashboardEntity : Entity public string Title { get; set; } - public List SignalIds { get; set; } = new List(); + public SignalExpressionPart SignalExpression { get; set; } public List Charts { get; set; } = new List(); } diff --git a/src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayPalette.cs b/src/Seq.Api/Model/Monitoring/MeasurementDisplayPalette.cs similarity index 79% rename from src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayPalette.cs rename to src/Seq.Api/Model/Monitoring/MeasurementDisplayPalette.cs index 97bd1b4..2206eb8 100644 --- a/src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayPalette.cs +++ b/src/Seq.Api/Model/Monitoring/MeasurementDisplayPalette.cs @@ -5,6 +5,7 @@ public enum MeasurementDisplayPalette Default, Reds, Greens, - Blues + Blues, + OrangePurple } } diff --git a/src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayStylePart.cs b/src/Seq.Api/Model/Monitoring/MeasurementDisplayStylePart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayStylePart.cs rename to src/Seq.Api/Model/Monitoring/MeasurementDisplayStylePart.cs diff --git a/src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayType.cs b/src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs similarity index 80% rename from src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayType.cs rename to src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs index f92f0f7..12f5a59 100644 --- a/src/Seq.Api/Api/Model/Monitoring/MeasurementDisplayType.cs +++ b/src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs @@ -4,6 +4,7 @@ public enum MeasurementDisplayType { Line, Bar, - Point + Point, + Value } } diff --git a/src/Seq.Api/Api/Model/Monitoring/MeasurementPart.cs b/src/Seq.Api/Model/Monitoring/MeasurementPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Monitoring/MeasurementPart.cs rename to src/Seq.Api/Model/Monitoring/MeasurementPart.cs diff --git a/src/Seq.Api/Api/Model/Permalinks/PermalinkEntity.cs b/src/Seq.Api/Model/Permalinks/PermalinkEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Permalinks/PermalinkEntity.cs rename to src/Seq.Api/Model/Permalinks/PermalinkEntity.cs diff --git a/src/Seq.Api/Api/Model/ResourceGroup.cs b/src/Seq.Api/Model/ResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/Model/ResourceGroup.cs rename to src/Seq.Api/Model/ResourceGroup.cs diff --git a/src/Seq.Api/Api/Model/Retention/RetentionPolicyEntity.cs b/src/Seq.Api/Model/Retention/RetentionPolicyEntity.cs similarity index 56% rename from src/Seq.Api/Api/Model/Retention/RetentionPolicyEntity.cs rename to src/Seq.Api/Model/Retention/RetentionPolicyEntity.cs index cadabcc..09f4a2b 100644 --- a/src/Seq.Api/Api/Model/Retention/RetentionPolicyEntity.cs +++ b/src/Seq.Api/Model/Retention/RetentionPolicyEntity.cs @@ -1,4 +1,5 @@ using System; +using Seq.Api.Model.Signals; namespace Seq.Api.Model.Retention { @@ -6,6 +7,9 @@ public class RetentionPolicyEntity : Entity { public TimeSpan RetentionTime { get; set; } + public SignalExpressionPart RemovedSignalExpression { get; set; } + + [Obsolete("Replaced by RemovedSignalExpression.")] public string SignalId { get; set; } } } diff --git a/src/Seq.Api/Api/Model/Root/RootEntity.cs b/src/Seq.Api/Model/Root/RootEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Root/RootEntity.cs rename to src/Seq.Api/Model/Root/RootEntity.cs diff --git a/src/Seq.Api/Api/Model/Settings/SettingEntity.cs b/src/Seq.Api/Model/Settings/SettingEntity.cs similarity index 71% rename from src/Seq.Api/Api/Model/Settings/SettingEntity.cs rename to src/Seq.Api/Model/Settings/SettingEntity.cs index 98c5d74..9f4c5d5 100644 --- a/src/Seq.Api/Api/Model/Settings/SettingEntity.cs +++ b/src/Seq.Api/Model/Settings/SettingEntity.cs @@ -1,6 +1,6 @@ namespace Seq.Api.Model.Settings { - public class SettingEntity : Seq.Api.Model.Entity + public class SettingEntity : Entity { public string Name { get; set; } public object Value { get; set; } diff --git a/src/Seq.Api/Api/Model/Settings/SettingName.cs b/src/Seq.Api/Model/Settings/SettingName.cs similarity index 100% rename from src/Seq.Api/Api/Model/Settings/SettingName.cs rename to src/Seq.Api/Model/Settings/SettingName.cs diff --git a/src/Seq.Api/Api/Model/Shared/DeferredRequestEntity.cs b/src/Seq.Api/Model/Shared/DeferredRequestEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Shared/DeferredRequestEntity.cs rename to src/Seq.Api/Model/Shared/DeferredRequestEntity.cs diff --git a/src/Seq.Api/Api/Model/Shared/ResultSetStatus.cs b/src/Seq.Api/Model/Shared/ResultSetStatus.cs similarity index 100% rename from src/Seq.Api/Api/Model/Shared/ResultSetStatus.cs rename to src/Seq.Api/Model/Shared/ResultSetStatus.cs diff --git a/src/Seq.Api/Api/Model/Shared/StatisticsPart.cs b/src/Seq.Api/Model/Shared/StatisticsPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Shared/StatisticsPart.cs rename to src/Seq.Api/Model/Shared/StatisticsPart.cs diff --git a/src/Seq.Api/Api/Model/Signals/SignalEntity.cs b/src/Seq.Api/Model/Signals/SignalEntity.cs similarity index 85% rename from src/Seq.Api/Api/Model/Signals/SignalEntity.cs rename to src/Seq.Api/Model/Signals/SignalEntity.cs index d61fbca..d8c4004 100644 --- a/src/Seq.Api/Api/Model/Signals/SignalEntity.cs +++ b/src/Seq.Api/Model/Signals/SignalEntity.cs @@ -22,5 +22,9 @@ public SignalEntity() public bool IsWatched { get; set; } public bool IsRestricted { get; set; } + + public SignalGrouping Grouping { get; set; } + + public string ExplicitGroupName { get; set; } } } diff --git a/src/Seq.Api/Model/Signals/SignalExpressionKind.cs b/src/Seq.Api/Model/Signals/SignalExpressionKind.cs new file mode 100644 index 0000000..f4df442 --- /dev/null +++ b/src/Seq.Api/Model/Signals/SignalExpressionKind.cs @@ -0,0 +1,10 @@ +namespace Seq.Api.Model.Signals +{ + public enum SignalExpressionKind + { + None, + Signal, + Intersection, + Union + } +} diff --git a/src/Seq.Api/Model/Signals/SignalExpressionPart.cs b/src/Seq.Api/Model/Signals/SignalExpressionPart.cs new file mode 100644 index 0000000..c0615e3 --- /dev/null +++ b/src/Seq.Api/Model/Signals/SignalExpressionPart.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; + +namespace Seq.Api.Model.Signals +{ + public class SignalExpressionPart + { + public SignalExpressionKind Kind { get; set; } + + // SignalExpressionKind.Signal + + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string SignalId { get; set; } + + // SignalExpressionKind.Intersection, SignalExpressionKind.Union + + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public SignalExpressionPart Left { get; set; } + + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public SignalExpressionPart Right { get; set; } + + public static SignalExpressionPart Signal(string signalId) + { + if (signalId == null) throw new ArgumentNullException(nameof(signalId)); + return new SignalExpressionPart {Kind = SignalExpressionKind.Signal, SignalId = signalId}; + } + + public static SignalExpressionPart Intersection(SignalExpressionPart left, SignalExpressionPart right) + { + if (left == null) throw new ArgumentNullException(nameof(left)); + if (right == null) throw new ArgumentNullException(nameof(right)); + + return new SignalExpressionPart + { + Kind = SignalExpressionKind.Intersection, + Left = left, + Right = right + }; + } + + public static SignalExpressionPart Union(SignalExpressionPart left, SignalExpressionPart right) + { + if (left == null) throw new ArgumentNullException(nameof(left)); + if (right == null) throw new ArgumentNullException(nameof(right)); + + return new SignalExpressionPart + { + Kind = SignalExpressionKind.Union, + Left = left, + Right = right + }; + } + + public static SignalExpressionPart FromIntersectedIds(IEnumerable intersectIds) + { + if (intersectIds == null) throw new ArgumentNullException(nameof(intersectIds)); + + if (!intersectIds.Any()) + return null; + + var first = Signal(intersectIds.First()); + return intersectIds.Skip(1).Aggregate(first, (lhs, rhs) => Intersection(lhs, Signal(rhs))); + } + + public override string ToString() + { + if (Kind == SignalExpressionKind.Signal) + return SignalId; + + if (Kind == SignalExpressionKind.Intersection) + return $"{Group(Left)},{Group(Right)}"; + + if (Kind == SignalExpressionKind.Union) + return $"{Group(Left)}+{Group(Right)}"; + + throw new InvalidOperationException("Invalid signal expression kind."); + } + + static string Group(SignalExpressionPart signalExpression) + { + if (signalExpression.Kind == SignalExpressionKind.Signal) + return signalExpression.ToString(); + + return $"({signalExpression})"; + } + } +} diff --git a/src/Seq.Api/Api/Model/Signals/SignalFilterPart.cs b/src/Seq.Api/Model/Signals/SignalFilterPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Signals/SignalFilterPart.cs rename to src/Seq.Api/Model/Signals/SignalFilterPart.cs diff --git a/src/Seq.Api/Model/Signals/SignalGrouping.cs b/src/Seq.Api/Model/Signals/SignalGrouping.cs new file mode 100644 index 0000000..0fc356c --- /dev/null +++ b/src/Seq.Api/Model/Signals/SignalGrouping.cs @@ -0,0 +1,9 @@ +namespace Seq.Api.Model.Signals +{ + public enum SignalGrouping + { + Inferred, + Explicit, + None + } +} diff --git a/src/Seq.Api/Api/Model/Signals/TaggedPropertyPart.cs b/src/Seq.Api/Model/Signals/TaggedPropertyPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Signals/TaggedPropertyPart.cs rename to src/Seq.Api/Model/Signals/TaggedPropertyPart.cs diff --git a/src/Seq.Api/Api/Model/SqlQueries/SqlQueryEntity.cs b/src/Seq.Api/Model/SqlQueries/SqlQueryEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/SqlQueries/SqlQueryEntity.cs rename to src/Seq.Api/Model/SqlQueries/SqlQueryEntity.cs diff --git a/src/Seq.Api/Api/Model/Updates/AvailableUpdateEntity.cs b/src/Seq.Api/Model/Updates/AvailableUpdateEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Updates/AvailableUpdateEntity.cs rename to src/Seq.Api/Model/Updates/AvailableUpdateEntity.cs diff --git a/src/Seq.Api/Api/Model/Users/AuthProviderInfoPart.cs b/src/Seq.Api/Model/Users/AuthProviderInfoPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/AuthProviderInfoPart.cs rename to src/Seq.Api/Model/Users/AuthProviderInfoPart.cs diff --git a/src/Seq.Api/Api/Model/Users/AuthProvidersPart.cs b/src/Seq.Api/Model/Users/AuthProvidersPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/AuthProvidersPart.cs rename to src/Seq.Api/Model/Users/AuthProvidersPart.cs diff --git a/src/Seq.Api/Api/Model/Users/CredentialsPart.cs b/src/Seq.Api/Model/Users/CredentialsPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/CredentialsPart.cs rename to src/Seq.Api/Model/Users/CredentialsPart.cs diff --git a/src/Seq.Api/Api/Model/Users/SearchHistoryEntity.cs b/src/Seq.Api/Model/Users/SearchHistoryEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/SearchHistoryEntity.cs rename to src/Seq.Api/Model/Users/SearchHistoryEntity.cs diff --git a/src/Seq.Api/Api/Model/Users/SearchHistoryItemPart.cs b/src/Seq.Api/Model/Users/SearchHistoryItemPart.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/SearchHistoryItemPart.cs rename to src/Seq.Api/Model/Users/SearchHistoryItemPart.cs diff --git a/src/Seq.Api/Api/Model/Users/SearchHistoryItemStatus.cs b/src/Seq.Api/Model/Users/SearchHistoryItemStatus.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/SearchHistoryItemStatus.cs rename to src/Seq.Api/Model/Users/SearchHistoryItemStatus.cs diff --git a/src/Seq.Api/Api/Model/Users/UserEntity.cs b/src/Seq.Api/Model/Users/UserEntity.cs similarity index 100% rename from src/Seq.Api/Api/Model/Users/UserEntity.cs rename to src/Seq.Api/Model/Users/UserEntity.cs diff --git a/src/Seq.Api/Properties/AssemblyInfo.cs b/src/Seq.Api/Properties/AssemblyInfo.cs deleted file mode 100644 index f219e5d..0000000 --- a/src/Seq.Api/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Reflection; - -[assembly: AssemblyTitle("Seq.Api")] -[assembly: AssemblyDescription("Seq HTTP API Client")] -[assembly: AssemblyCompany("Continuous IT Pty Ltd")] -[assembly: AssemblyProduct("http://getseq.net")] -[assembly: AssemblyCopyright("Copyright © Continuous IT 2014")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: AssemblyInformationalVersion("1.0.0.0")] diff --git a/src/Seq.Api/Api/ResourceGroups/ApiKeysResourceGroup.cs b/src/Seq.Api/ResourceGroups/ApiKeysResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/ApiKeysResourceGroup.cs rename to src/Seq.Api/ResourceGroups/ApiKeysResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/ApiResourceGroup.cs b/src/Seq.Api/ResourceGroups/ApiResourceGroup.cs similarity index 94% rename from src/Seq.Api/Api/ResourceGroups/ApiResourceGroup.cs rename to src/Seq.Api/ResourceGroups/ApiResourceGroup.cs index 6616712..42cc2e9 100644 --- a/src/Seq.Api/Api/ResourceGroups/ApiResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/ApiResourceGroup.cs @@ -78,5 +78,10 @@ protected async Task GroupDeleteAsync(string link var group = await LoadGroupAsync().ConfigureAwait(false); return await Client.DeleteAsync(group, link, content, parameters).ConfigureAwait(false); } + + protected string GetLink(TEntity entity, string link, string orElse) where TEntity : ILinked + { + return entity.Links.ContainsKey(link) ? link : orElse; + } } } diff --git a/src/Seq.Api/Api/ResourceGroups/AppInstancesResourceGroup.cs b/src/Seq.Api/ResourceGroups/AppInstancesResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/AppInstancesResourceGroup.cs rename to src/Seq.Api/ResourceGroups/AppInstancesResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/AppsResourceGroup.cs b/src/Seq.Api/ResourceGroups/AppsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/AppsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/AppsResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/BackupsResourceGroup.cs b/src/Seq.Api/ResourceGroups/BackupsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/BackupsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/BackupsResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/DashboardsResourceGroup.cs b/src/Seq.Api/ResourceGroups/DashboardsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/DashboardsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/DashboardsResourceGroup.cs diff --git a/src/Seq.Api/ResourceGroups/DataResourceGroup.cs b/src/Seq.Api/ResourceGroups/DataResourceGroup.cs new file mode 100644 index 0000000..c046d9b --- /dev/null +++ b/src/Seq.Api/ResourceGroups/DataResourceGroup.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Seq.Api.Model.Data; +using Seq.Api.Model.Signals; + +namespace Seq.Api.ResourceGroups +{ + public class DataResourceGroup : ApiResourceGroup + { + internal DataResourceGroup(ISeqConnection connection) + : base("Data", connection) + { + } + + /// + /// Execute an SQL query and retrieve the result set as a structured . + /// + /// The query to execute. + /// The earliest timestamp from which to include events in the query result. + /// The exclusive latest timestamp to which events are included in the query result. The default is the current time. + /// A signal expression over which the query will be executed. + /// A constructed signal that may not appear on the server, for example, a that has been + /// created but not saved, a signal from another server, or the modified representation of an entity already persisted. + /// A structured result set. + public async Task QueryAsync( + string query, + DateTime rangeStartUtc, + DateTime? rangeEndUtc = null, + SignalExpressionPart signal = null, + SignalEntity unsavedSignal = null) + { + MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, unsavedSignal, out var body, out var parameters); + return await GroupPostAsync("Query", body, parameters).ConfigureAwait(false); + } + + /// + /// Execute an SQL query and retrieve the result set as a structured . + /// + /// The query to execute. + /// The earliest timestamp from which to include events in the query result. + /// The exclusive latest timestamp to which events are included in the query result. The default is the current time. + /// A signal expression over which the query will be executed. + /// A constructed signal that may not appear on the server, for example, a that has been + /// created but not saved, a signal from another server, or the modified representation of an entity already persisted. + /// A CSV result set. + public async Task QueryCsvAsync( + string query, + DateTime rangeStartUtc, + DateTime? rangeEndUtc = null, + SignalExpressionPart signal = null, + SignalEntity unsavedSignal = null) + { + MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, unsavedSignal, out var body, out var parameters); + parameters.Add("format", "text/csv"); + return await GroupPostReadStringAsync("Query", body, parameters).ConfigureAwait(false); + } + + static void MakeParameters( + string query, + DateTime rangeStartUtc, + DateTime? rangeEndUtc, + SignalExpressionPart signal, + SignalEntity unsavedSignal, + out SignalEntity body, + out Dictionary parameters) + { + parameters = new Dictionary + { + {"q", query}, + {nameof(rangeStartUtc), rangeStartUtc} + }; + + if (rangeEndUtc != null) + { + parameters.Add(nameof(rangeEndUtc), rangeEndUtc.Value); + } + if (signal != null) + { + parameters.Add(nameof(signal), signal.ToString()); + } + + body = unsavedSignal ?? new SignalEntity(); + } + } +} diff --git a/src/Seq.Api/Api/ResourceGroups/DiagnosticsResourceGroup.cs b/src/Seq.Api/ResourceGroups/DiagnosticsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/DiagnosticsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/DiagnosticsResourceGroup.cs diff --git a/src/Seq.Api/ResourceGroups/EntityResourceGroup.cs b/src/Seq.Api/ResourceGroups/EntityResourceGroup.cs new file mode 100644 index 0000000..e1e51da --- /dev/null +++ b/src/Seq.Api/ResourceGroups/EntityResourceGroup.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Seq.Api.Model; + +namespace Seq.Api.ResourceGroups +{ + public class EntityResourceGroup : ApiResourceGroup + { + internal EntityResourceGroup(string name, ISeqConnection connection) : base(name, connection) + { + } + + protected async Task GroupCreateAsync(TEntity entity, + IDictionary parameters = null) where TEntity : ILinked + { + var link = entity.Links.ContainsKey("Create") ? "Create" : "Items"; + var group = await LoadGroupAsync().ConfigureAwait(false); + return await Client.PostAsync(group, link, entity, parameters).ConfigureAwait(false); + } + } +} \ No newline at end of file diff --git a/src/Seq.Api/Api/ResourceGroups/EventsResourceGroup.cs b/src/Seq.Api/ResourceGroups/EventsResourceGroup.cs similarity index 66% rename from src/Seq.Api/Api/ResourceGroups/EventsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/EventsResourceGroup.cs index 8610b36..8468974 100644 --- a/src/Seq.Api/Api/ResourceGroups/EventsResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/EventsResourceGroup.cs @@ -26,7 +26,7 @@ public async Task FindAsync(string id) /// Retrieve a list of events that match a set of conditions. The complete result is buffered into memory, /// so if a large result set is expected, use InSignalAsync() and lastReadEventId to page the results. /// - /// If provided, a list of signal ids whose intersection will be filtered for the result. + /// If provided, a signal expression describing the set of events that will be filtered for the result. /// A strict Seq filter expression to match (text expressions must be in double quotes). To /// convert a "fuzzy" filter into a strict one the way the Seq UI does, use connection.Expressions.ToStrictAsync(). /// The number of events to retrieve. If not specified will default to 30. @@ -40,7 +40,7 @@ public async Task FindAsync(string id) /// batch processing scenarios. /// The complete list of events, ordered from least to most recent. public async Task> ListAsync( - string[] intersectIds = null, + SignalExpressionPart signal = null, string filter = null, int count = 30, string startAtId = null, @@ -51,7 +51,7 @@ public async Task> ListAsync( int? shortCircuitAfter = null) { var parameters = new Dictionary { { "count", count } }; - if (intersectIds != null && intersectIds.Length > 0) { parameters.Add("intersectIds", string.Join(",", intersectIds)); } + if (signal != null) { parameters.Add("signal", signal.ToString()); } if (filter != null) { parameters.Add("filter", filter); } if (startAtId != null) { parameters.Add("startAtId", startAtId); } if (afterId != null) { parameters.Add("afterId", afterId); } @@ -86,9 +86,28 @@ public async Task> ListAsync( return result; } + /// + /// Retrieve a list of events that match a set of conditions. The complete result is buffered into memory, + /// so if a large result set is expected, use InSignalAsync() and lastReadEventId to page the results. + /// + /// A constructed signal that may not appear on the server, for example, a that has been + /// created but not saved, a signal from another server, or the modified representation of an entity already persisted. + /// If provided, a signal expression describing the set of events that will be filtered for the result. + /// A strict Seq filter expression to match (text expressions must be in double quotes). To + /// convert a "fuzzy" filter into a strict one the way the Seq UI does, use connection.Expressions.ToStrictAsync(). + /// The number of events to retrieve. If not specified will default to 30. + /// An event id from which to start searching (inclusively). + /// An event id to search after (exclusively). + /// If specified, the event's message template and properties will be rendered into its RenderedMessage property. + /// Earliest (inclusive) date/time from which to search. + /// Latest (exclusive) date/time from which to search. + /// If specified, the number of events after the first match to keep searching before a partial + /// result set is returned. Used to improve responsiveness when the result is displayed in a user interface, not typically used in + /// batch processing scenarios. + /// The complete list of events, ordered from least to most recent. public async Task InSignalAsync( - SignalEntity signal = null, - string[] intersectIds = null, + SignalEntity unsavedSignal = null, + SignalExpressionPart signal = null, string filter = null, int count = 30, string startAtId = null, @@ -99,7 +118,7 @@ public async Task InSignalAsync( int? shortCircuitAfter = null) { var parameters = new Dictionary{{ "count", count }}; - if (intersectIds != null && intersectIds.Length > 0) { parameters.Add("intersectIds", string.Join(",", intersectIds)); } + if (signal != null) { parameters.Add("signal", signal.ToString()); } if (filter != null) { parameters.Add("filter", filter); } if (startAtId != null) { parameters.Add("startAtId", startAtId); } if (afterId != null) { parameters.Add("afterId", afterId); } @@ -108,12 +127,12 @@ public async Task InSignalAsync( if (toDateUtc != null) { parameters.Add("toDateUtc", toDateUtc.Value); } if (shortCircuitAfter != null) { parameters.Add("shortCircuitAfter", shortCircuitAfter.Value); } - var body = signal ?? new SignalEntity(); + var body = unsavedSignal ?? new SignalEntity(); return await GroupPostAsync("InSignal", body, parameters).ConfigureAwait(false); } public async Task InSignalAsync( - string[] intersectIds, + SignalExpressionPart signal, string filter = null, int count = 30, string startAtId = null, @@ -123,11 +142,11 @@ public async Task InSignalAsync( DateTime? toDateUtc = null, int? shortCircuitAfter = null) { - if (intersectIds == null) throw new ArgumentNullException(nameof(intersectIds)); + if (signal == null) throw new ArgumentNullException(nameof(signal)); var parameters = new Dictionary { - { "intersectIds", string.Join(",", intersectIds) }, + { "signal", signal.ToString() }, { "count", count } }; if (filter != null) { parameters.Add("filter", filter); } @@ -141,38 +160,49 @@ public async Task InSignalAsync( return await GroupGetAsync("InSignal", parameters).ConfigureAwait(false); } - public async Task DeleteInSignalAsync( - SignalEntity signal = null, - string[] intersectIds = null, + /// + /// Delete matching events from the stream. + /// + /// A constructed signal that may not appear on the server, for example, a that has been + /// created but not saved, a signal from another server, or the modified representation of an entity already persisted. + /// If provided, a signal expression describing the set of events that will be filtered for the result. + /// A strict Seq filter expression to match (text expressions must be in double quotes). To + /// convert a "fuzzy" filter into a strict one the way the Seq UI does, use connection.Expressions.ToStrictAsync(). + /// Earliest (inclusive) date/time from which to delete. + /// Latest (exclusive) date/time from which to delete. + /// A result carrying the count of events deleted. + public async Task DeleteInSignalAsync( + SignalEntity unsavedSignal = null, + SignalExpressionPart signal = null, string filter = null, DateTime? fromDateUtc = null, DateTime? toDateUtc = null) { var parameters = new Dictionary(); - if (intersectIds != null && intersectIds.Length > 0) { parameters.Add("intersectIds", string.Join(",", intersectIds)); } + if (signal != null) { parameters.Add("signal", signal.ToString()); } if (filter != null) { parameters.Add("filter", filter); } if (fromDateUtc != null) { parameters.Add("fromDateUtc", fromDateUtc.Value); } if (toDateUtc != null) { parameters.Add("toDateUtc", toDateUtc.Value); } - var body = signal ?? new SignalEntity(); - return await GroupDeleteAsync("DeleteInSignal", body, parameters).ConfigureAwait(false); + var body = unsavedSignal ?? new SignalEntity(); + return await GroupDeleteAsync("DeleteInSignal", body, parameters).ConfigureAwait(false); } /// /// Connect to the live event stream. Dispose the resulting stream to disconnect. /// /// The type into which events should be deserialized. - /// If provided, a list of signal ids whose intersection will be filtered for the result. + /// If provided, a signal expression describing the set of events that will be filtered for the result. /// A strict Seq filter expression to match (text expressions must be in double quotes). To /// convert a "fuzzy" filter into a strict one the way the Seq UI does, use connection.Expressions.ToStrictAsync(). /// An observable that will stream events from the server to subscribers. Events will be buffered server-side until the first /// subscriber connects, ensure at least one subscription is made in order to avoid event loss. public async Task> StreamAsync( - string[] intersectIds = null, + SignalExpressionPart signal = null, string filter = null) { var parameters = new Dictionary(); - if (intersectIds != null && intersectIds.Length > 0) { parameters.Add("intersectIds", string.Join(",", intersectIds)); } + if (signal != null) { parameters.Add("signal", signal.ToString()); } if (filter != null) { parameters.Add("filter", filter); } var group = await LoadGroupAsync().ConfigureAwait(false); @@ -183,17 +213,17 @@ public async Task> StreamAsync( /// Retrieve a list of events that match a set of conditions. The complete result is buffered into memory, /// so if a large result set is expected, use InSignalAsync() and lastReadEventId to page the results. /// - /// If provided, a list of signal ids whose intersection will be filtered for the result. + /// If provided, a signal expression describing the set of events that will be filtered for the result. /// A strict Seq filter expression to match (text expressions must be in double quotes). To /// convert a "fuzzy" filter into a strict one the way the Seq UI does, use connection.Expressions.ToStrictAsync(). /// An observable that will stream events from the server to subscribers. Events will be buffered server-side until the first /// subscriber connects, ensure at least one subscription is made in order to avoid event loss. public async Task> StreamDocumentsAsync( - string[] intersectIds = null, + SignalExpressionPart signal = null, string filter = null) { var parameters = new Dictionary(); - if (intersectIds != null && intersectIds.Length > 0) { parameters.Add("intersectIds", string.Join(",", intersectIds)); } + if (signal != null) { parameters.Add("signal", signal.ToString()); } if (filter != null) { parameters.Add("filter", filter); } var group = await LoadGroupAsync().ConfigureAwait(false); diff --git a/src/Seq.Api/Api/ResourceGroups/ExpressionsResourceGroup.cs b/src/Seq.Api/ResourceGroups/ExpressionsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/ExpressionsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/ExpressionsResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/FeedsResourceGroup.cs b/src/Seq.Api/ResourceGroups/FeedsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/FeedsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/FeedsResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/ISeqConnection.cs b/src/Seq.Api/ResourceGroups/ISeqConnection.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/ISeqConnection.cs rename to src/Seq.Api/ResourceGroups/ISeqConnection.cs diff --git a/src/Seq.Api/Api/ResourceGroups/LicensesResourceGroup.cs b/src/Seq.Api/ResourceGroups/LicensesResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/LicensesResourceGroup.cs rename to src/Seq.Api/ResourceGroups/LicensesResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/PermalinksResourceGroup.cs b/src/Seq.Api/ResourceGroups/PermalinksResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/PermalinksResourceGroup.cs rename to src/Seq.Api/ResourceGroups/PermalinksResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/RetentionPoliciesResourceGroup.cs b/src/Seq.Api/ResourceGroups/RetentionPoliciesResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/RetentionPoliciesResourceGroup.cs rename to src/Seq.Api/ResourceGroups/RetentionPoliciesResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/SettingsResourceGroup.cs b/src/Seq.Api/ResourceGroups/SettingsResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/SettingsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/SettingsResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/SignalsResourceGroup.cs b/src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs similarity index 88% rename from src/Seq.Api/Api/ResourceGroups/SignalsResourceGroup.cs rename to src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs index 6bc8cdb..9a4f178 100644 --- a/src/Seq.Api/Api/ResourceGroups/SignalsResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/SignalsResourceGroup.cs @@ -5,7 +5,7 @@ namespace Seq.Api.ResourceGroups { - public class SignalsResourceGroup : ApiResourceGroup + public class SignalsResourceGroup : EntityResourceGroup { internal SignalsResourceGroup(ISeqConnection connection) : base("Signals", connection) @@ -30,7 +30,7 @@ public async Task TemplateAsync() public async Task AddAsync(SignalEntity entity) { - return await Client.PostAsync(entity, "Create", entity).ConfigureAwait(false); + return await GroupCreateAsync(entity).ConfigureAwait(false); } public async Task RemoveAsync(SignalEntity entity) diff --git a/src/Seq.Api/Api/ResourceGroups/SqlQueriesResourceGroup.cs b/src/Seq.Api/ResourceGroups/SqlQueriesResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/SqlQueriesResourceGroup.cs rename to src/Seq.Api/ResourceGroups/SqlQueriesResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/UpdatesResourceGroup.cs b/src/Seq.Api/ResourceGroups/UpdatesResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/UpdatesResourceGroup.cs rename to src/Seq.Api/ResourceGroups/UpdatesResourceGroup.cs diff --git a/src/Seq.Api/Api/ResourceGroups/UsersResourceGroup.cs b/src/Seq.Api/ResourceGroups/UsersResourceGroup.cs similarity index 100% rename from src/Seq.Api/Api/ResourceGroups/UsersResourceGroup.cs rename to src/Seq.Api/ResourceGroups/UsersResourceGroup.cs diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index 2a8796d..d300f75 100644 --- a/src/Seq.Api/Seq.Api.csproj +++ b/src/Seq.Api/Seq.Api.csproj @@ -1,46 +1,37 @@ - - + Client library for the Seq HTTP API. - 4.2.0 + 4.2.1000 Datalust;Contributors - netstandard1.3;net45 + netstandard1.3;net452 $(NoWarn);CS1591 true true Seq.Api Seq.Api seq - https://getseq.net/images/seq-nuget.pngg + Copyright © 2014-2017 Datalust Pty Ltd and Contributors + https://getseq.net/images/seq-nuget.png https://github.com/datalust/seq-api http://www.apache.org/licenses/LICENSE-2.0 - 1.6.1 - false - false - false - false - false - false - false - false - Seq + Seq.Api + + + true - - + - - - - + + + - - - + + + - - + \ No newline at end of file diff --git a/src/Seq.Api/Api/SeqConnection.cs b/src/Seq.Api/SeqConnection.cs similarity index 99% rename from src/Seq.Api/Api/SeqConnection.cs rename to src/Seq.Api/SeqConnection.cs index 8c7c39b..5d611b2 100644 --- a/src/Seq.Api/Api/SeqConnection.cs +++ b/src/Seq.Api/SeqConnection.cs @@ -20,7 +20,6 @@ public SeqConnection(string serverUrl, string apiKey = null) _client = new SeqApiClient(serverUrl, apiKey); _root = new Lazy>(() => _client.GetRootAsync()); - } public ApiKeysResourceGroup ApiKeys => new ApiKeysResourceGroup(this); diff --git a/src/Seq.Api/Api/Serialization/LinkCollectionConverter.cs b/src/Seq.Api/Serialization/LinkCollectionConverter.cs similarity index 100% rename from src/Seq.Api/Api/Serialization/LinkCollectionConverter.cs rename to src/Seq.Api/Serialization/LinkCollectionConverter.cs diff --git a/src/Seq.Api/Api/Streams/ObservableStream.Unsubscriber.cs b/src/Seq.Api/Streams/ObservableStream.Unsubscriber.cs similarity index 100% rename from src/Seq.Api/Api/Streams/ObservableStream.Unsubscriber.cs rename to src/Seq.Api/Streams/ObservableStream.Unsubscriber.cs diff --git a/src/Seq.Api/Api/Streams/ObservableStream.cs b/src/Seq.Api/Streams/ObservableStream.cs similarity index 100% rename from src/Seq.Api/Api/Streams/ObservableStream.cs rename to src/Seq.Api/Streams/ObservableStream.cs From ebebe6dd76cbeca2245619d0242b8484de41a6d2 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 7 Dec 2017 13:04:42 +1000 Subject: [PATCH 05/10] Add a note on package versioning to the README --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e53d6d..baaff62 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This library includes: It's useful for querying events and working with configuration data - *everything you can do using the Seq web UI*, you can do programmatically via the API. -If you want to *write events* to Seq, use one of the logging framework clients, such as _Serilog.Sinks.Seq_ or _Seq.Client.Slab_ instead. +If you want to *write events* to Seq, use one of the logging framework clients, such as _Serilog.Sinks.Seq_ or _NLog.Targets.Seq_ instead. ### Getting started @@ -136,3 +136,7 @@ var matched = await client.List( foreach (var match in matched) Console.WriteLine(matched.RenderedMessage); ``` + +### Package versioning + +This package does not follow the SemVer rule of major version increments for breaking changes. Instead, the package version tracks the Seq version it supports. From f1ec6e67c82360b0889e5374e4395e9dbd62bdeb Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 7 Dec 2017 13:09:42 +1000 Subject: [PATCH 06/10] Only ignore backups created in the root of the project --- .gitignore | 2 +- src/Seq.Api/Model/Backups/BackupEntity.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/Seq.Api/Model/Backups/BackupEntity.cs diff --git a/.gitignore b/.gitignore index f1e3d20..dc64607 100644 --- a/.gitignore +++ b/.gitignore @@ -204,7 +204,7 @@ Generated_Code/ # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ -Backup*/ +/Backup*/ UpgradeLog*.XML UpgradeLog*.htm diff --git a/src/Seq.Api/Model/Backups/BackupEntity.cs b/src/Seq.Api/Model/Backups/BackupEntity.cs new file mode 100644 index 0000000..a59bd0b --- /dev/null +++ b/src/Seq.Api/Model/Backups/BackupEntity.cs @@ -0,0 +1,11 @@ +using System; + +namespace Seq.Api.Model.Backups +{ + public class BackupEntity : Entity + { + public string CreatedAt { get; set; } + public string Filename { get; set; } + public long FileSizeBytes { get; set; } + } +} From ba7c343bf9828db7b18042221492319ca2da4998 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 7 Dec 2017 13:25:14 +1000 Subject: [PATCH 07/10] New NuGet.org API key --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a485dc2..7c59646 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: 7AS4wbHVs08D6so0JGAVczexCX9ST6CRbNToHZC08rtPqkQENpyNhhSAIX0FShzh + secure: luVm1C63eoBD+VuUPGu66KsalR39FTAbnQtRgs8HmO21D53xm/I6o0eIN7Tm0Y83 skip_symbols: true on: branch: /^(master|dev)$/ From b4aec156c03d827132e762adca5e8e1feca9e4f4 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 7 Dec 2017 15:31:25 +1000 Subject: [PATCH 08/10] Found another way around Seq.Api versioning - un-listing the .1000 version --- src/Seq.Api/Seq.Api.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index d300f75..03a7adc 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. - 4.2.1000 + 4.2.0 Datalust;Contributors netstandard1.3;net452 $(NoWarn);CS1591 @@ -34,4 +34,4 @@ - \ No newline at end of file + From e8288c83bbc5c04838f425d9bb3da330743e79ab Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 10 Jan 2018 11:31:45 +1000 Subject: [PATCH 09/10] Update to match latest Seq 4.2 preview API --- src/Seq.Api/Client/SeqApiClient.cs | 8 ++++---- .../Model/AppInstances/AppInstanceEntity.cs | 6 ++++++ src/Seq.Api/Model/Monitoring/AlertPart.cs | 9 +++++++++ .../Model/Monitoring/MeasurementDisplayType.cs | 3 ++- .../InternalErrorReportingSettingsPart.cs | 8 ++++++++ .../ResourceGroups/AppInstancesResourceGroup.cs | 14 +++++++++++++- src/Seq.Api/ResourceGroups/DataResourceGroup.cs | 17 +++++++++++++---- src/Seq.Api/Seq.Api.csproj | 2 +- 8 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 src/Seq.Api/Model/Settings/InternalErrorReportingSettingsPart.cs diff --git a/src/Seq.Api/Client/SeqApiClient.cs b/src/Seq.Api/Client/SeqApiClient.cs index 2963a58..b684fbf 100644 --- a/src/Seq.Api/Client/SeqApiClient.cs +++ b/src/Seq.Api/Client/SeqApiClient.cs @@ -204,7 +204,7 @@ static string ResolveLink(ILinked entity, string link, IDictionary p.Key).Except(template.GetParameterNames()).ToArray(); if (missing.Any()) - throw new ArgumentException("The URI template '" + expression + "' does not contain parameter: " + string.Join(",", missing)); + throw new ArgumentException($"The URI template `{expression}` does not contain parameter: `{string.Join("`, `", missing)}`."); foreach (var parameter in parameters) { - var value = parameter.Value is DateTime - ? ((DateTime) parameter.Value).ToString("O") + var value = parameter.Value is DateTime time + ? time.ToString("O") : parameter.Value; template.SetParameter(parameter.Key, value); diff --git a/src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs b/src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs index 67ae606..f4921c5 100644 --- a/src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs +++ b/src/Seq.Api/Model/AppInstances/AppInstanceEntity.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Seq.Api.Model.Apps; using Seq.Api.Model.Signals; namespace Seq.Api.Model.AppInstances @@ -9,6 +10,8 @@ public class AppInstanceEntity : Entity public AppInstanceEntity() { Settings = new Dictionary(); + InvocationOverridableSettings = new List(); + InvocationOverridableSettingDefinitions = new List(); EventsPerSuppressionWindow = 1; #pragma warning disable 618 SignalIds = new List(); @@ -19,6 +22,7 @@ public AppInstanceEntity() public bool IsManualInputOnly { get; set; } public string AppId { get; set; } public Dictionary Settings { get; set; } + public List InvocationOverridableSettings { get; set; } public TimeSpan? ArrivalWindow { get; set; } public SignalExpressionPart InputSignalExpression { get; set; } public bool DisallowManualInput { get; set; } @@ -29,5 +33,7 @@ public AppInstanceEntity() [Obsolete("Replaced by InputSignalExpression.")] public List SignalIds { get; set; } + + public List InvocationOverridableSettingDefinitions { get; set; } } } diff --git a/src/Seq.Api/Model/Monitoring/AlertPart.cs b/src/Seq.Api/Model/Monitoring/AlertPart.cs index 36cd15d..6e3b8c0 100644 --- a/src/Seq.Api/Model/Monitoring/AlertPart.cs +++ b/src/Seq.Api/Model/Monitoring/AlertPart.cs @@ -1,10 +1,13 @@ using Seq.Api.Model.LogEvents; using System; +using System.Collections.Generic; namespace Seq.Api.Model.Monitoring { public class AlertPart { + Dictionary _notificationAppSettingOverrides = new Dictionary(); + public string Id { get; set; } public string Condition { get; set; } public TimeSpan MeasurementWindow { get; set; } @@ -12,5 +15,11 @@ public class AlertPart public TimeSpan SuppressionTime { get; set; } public LogEventLevel Level { get; set; } = LogEventLevel.Warning; public string NotificationAppInstanceId { get; set; } + + public Dictionary NotificationAppSettingOverrides + { + get => _notificationAppSettingOverrides; + set => _notificationAppSettingOverrides = value ?? new Dictionary(); + } } } diff --git a/src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs b/src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs index 12f5a59..cc7e0d0 100644 --- a/src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs +++ b/src/Seq.Api/Model/Monitoring/MeasurementDisplayType.cs @@ -5,6 +5,7 @@ public enum MeasurementDisplayType Line, Bar, Point, - Value + Value, + Pie } } diff --git a/src/Seq.Api/Model/Settings/InternalErrorReportingSettingsPart.cs b/src/Seq.Api/Model/Settings/InternalErrorReportingSettingsPart.cs new file mode 100644 index 0000000..deaf7bf --- /dev/null +++ b/src/Seq.Api/Model/Settings/InternalErrorReportingSettingsPart.cs @@ -0,0 +1,8 @@ +namespace Seq.Api.Model.Settings +{ + public class InternalErrorReportingSettingsPart + { + public bool InternalErrorReportingEnabled { get; set; } + public string ReplyEmail { get; set; } + } +} diff --git a/src/Seq.Api/ResourceGroups/AppInstancesResourceGroup.cs b/src/Seq.Api/ResourceGroups/AppInstancesResourceGroup.cs index ca0c303..fe64248 100644 --- a/src/Seq.Api/ResourceGroups/AppInstancesResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/AppInstancesResourceGroup.cs @@ -31,17 +31,29 @@ public async Task TemplateAsync(string appId) public async Task AddAsync(AppInstanceEntity entity, bool runOnExisting = false) { + if (entity == null) throw new ArgumentNullException(nameof(entity)); return await Client.PostAsync(entity, "Create", entity, new Dictionary { { "runOnExisting", runOnExisting } }).ConfigureAwait(false); } public async Task RemoveAsync(AppInstanceEntity entity) { + if (entity == null) throw new ArgumentNullException(nameof(entity)); await Client.DeleteAsync(entity, "Self", entity).ConfigureAwait(false); } public async Task UpdateAsync(AppInstanceEntity entity) { + if (entity == null) throw new ArgumentNullException(nameof(entity)); await Client.PutAsync(entity, "Self", entity).ConfigureAwait(false); } + + public async Task InvokeAsync(AppInstanceEntity entity, string eventId, IReadOnlyDictionary settingOverrides) + { + if (entity == null) throw new ArgumentNullException(nameof(entity)); + if (eventId == null) throw new ArgumentNullException(nameof(eventId)); + + var postedSettings = settingOverrides ?? new Dictionary(); + await Client.PostAsync(entity, "Invoke", postedSettings, new Dictionary{{"eventId", eventId}}); + } } -} \ No newline at end of file +} diff --git a/src/Seq.Api/ResourceGroups/DataResourceGroup.cs b/src/Seq.Api/ResourceGroups/DataResourceGroup.cs index c046d9b..08ab59a 100644 --- a/src/Seq.Api/ResourceGroups/DataResourceGroup.cs +++ b/src/Seq.Api/ResourceGroups/DataResourceGroup.cs @@ -22,15 +22,17 @@ internal DataResourceGroup(ISeqConnection connection) /// A signal expression over which the query will be executed. /// A constructed signal that may not appear on the server, for example, a that has been /// created but not saved, a signal from another server, or the modified representation of an entity already persisted. + /// The query timeout; if not specified, the query will run until completion. /// A structured result set. public async Task QueryAsync( string query, DateTime rangeStartUtc, DateTime? rangeEndUtc = null, SignalExpressionPart signal = null, - SignalEntity unsavedSignal = null) + SignalEntity unsavedSignal = null, + TimeSpan? timeout = null) { - MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, unsavedSignal, out var body, out var parameters); + MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, unsavedSignal, timeout, out var body, out var parameters); return await GroupPostAsync("Query", body, parameters).ConfigureAwait(false); } @@ -43,15 +45,17 @@ public async Task QueryAsync( /// A signal expression over which the query will be executed. /// A constructed signal that may not appear on the server, for example, a that has been /// created but not saved, a signal from another server, or the modified representation of an entity already persisted. + /// The query timeout; if not specified, the query will run until completion. /// A CSV result set. public async Task QueryCsvAsync( string query, DateTime rangeStartUtc, DateTime? rangeEndUtc = null, SignalExpressionPart signal = null, - SignalEntity unsavedSignal = null) + SignalEntity unsavedSignal = null, + TimeSpan? timeout = null) { - MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, unsavedSignal, out var body, out var parameters); + MakeParameters(query, rangeStartUtc, rangeEndUtc, signal, unsavedSignal, timeout, out var body, out var parameters); parameters.Add("format", "text/csv"); return await GroupPostReadStringAsync("Query", body, parameters).ConfigureAwait(false); } @@ -62,6 +66,7 @@ static void MakeParameters( DateTime? rangeEndUtc, SignalExpressionPart signal, SignalEntity unsavedSignal, + TimeSpan? timeout, out SignalEntity body, out Dictionary parameters) { @@ -79,6 +84,10 @@ static void MakeParameters( { parameters.Add(nameof(signal), signal.ToString()); } + if (timeout != null) + { + parameters.Add("timeoutMS", timeout.Value.TotalMilliseconds.ToString("0")); + } body = unsavedSignal ?? new SignalEntity(); } diff --git a/src/Seq.Api/Seq.Api.csproj b/src/Seq.Api/Seq.Api.csproj index 03a7adc..f28982b 100644 --- a/src/Seq.Api/Seq.Api.csproj +++ b/src/Seq.Api/Seq.Api.csproj @@ -34,4 +34,4 @@ - + \ No newline at end of file From 5276b44caac5fc72e545d1b44bd01538462da47f Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 16 Jan 2018 08:49:32 +1000 Subject: [PATCH 10/10] Empty version suffix fix --- Build.ps1 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Build.ps1 b/Build.ps1 index d782ff9..035b540 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -20,9 +20,13 @@ echo "build: Version suffix is $suffix" foreach ($src in ls src/*) { Push-Location $src - echo "build: Packaging project in $src" + echo "build: Packaging project in $src" - & dotnet pack -c Release -o ..\..\artifacts --version-suffix=$suffix + if ($suffix) { + & dotnet pack -c Release -o ..\..\artifacts --version-suffix=$suffix + } else { + & dotnet pack -c Release -o ..\..\artifacts + } if($LASTEXITCODE -ne 0) { exit 1 } Pop-Location @@ -31,7 +35,7 @@ foreach ($src in ls src/*) { foreach ($test in ls test/*.Benchmarks) { Push-Location $test - echo "build: Building performance test project in $test" + echo "build: Building performance test project in $test" & dotnet build -c Release if($LASTEXITCODE -ne 0) { exit 2 } @@ -42,7 +46,7 @@ foreach ($test in ls test/*.Benchmarks) { foreach ($test in ls test/*.Tests) { Push-Location $test - echo "build: Testing project in $test" + echo "build: Testing project in $test" & dotnet test -c Release if($LASTEXITCODE -ne 0) { exit 3 }