Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/Seq.Api/Client/SeqApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using System.Threading;
using Seq.Api.Streams;
using System.Net.WebSockets;
using Seq.Api.Model.Shared;

namespace Seq.Api.Client
{
Expand All @@ -42,7 +43,7 @@ public sealed class SeqApiClient : IDisposable
// Future versions of Seq may not completely support vN-1 features, however
// providing this as an Accept header will ensure what compatibility is available
// can be utilized.
const string SeqApiV10MediaType = "application/vnd.datalust.seq.v10+json";
const string SeqApiV11MediaType = "application/vnd.datalust.seq.v11+json";

readonly CookieContainer _cookies = new();
readonly JsonSerializer _serializer = JsonSerializer.Create(
Expand Down Expand Up @@ -111,7 +112,7 @@ public SeqApiClient(string serverUrl, string apiKey = null, Func<CookieContainer

HttpClient = new HttpClient(httpMessageHandler);
HttpClient.BaseAddress = new Uri(baseAddress);
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(SeqApiV10MediaType));
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(SeqApiV11MediaType));

if (_apiKey != null)
HttpClient.DefaultRequestHeaders.Add("X-Seq-ApiKey", _apiKey);
Expand Down Expand Up @@ -372,23 +373,25 @@ async Task<string> HttpGetStringAsync(string url, CancellationToken cancellation
async Task<Stream> HttpSendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default)
{
var response = await HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
// ReSharper disable once MethodSupportsCancellation
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

if (response.IsSuccessStatusCode)
return stream;

Dictionary<string, object> payload = null;
ErrorPart error = null;
try
{
payload = _serializer.Deserialize<Dictionary<string, object>>(new JsonTextReader(new StreamReader(stream)));
error = _serializer.Deserialize<ErrorPart>(new JsonTextReader(new StreamReader(stream)));
}
// ReSharper disable once EmptyGeneralCatchClause
catch { }

if (payload != null && payload.TryGetValue("Error", out var error) && error != null)
throw new SeqApiException($"{(int)response.StatusCode} - {error}", response.StatusCode);
var exceptionMessage = $"The Seq request failed ({(int)response.StatusCode}/{response.StatusCode}).";
if (error?.Error != null)
exceptionMessage += $" {error.Error}";

throw new SeqApiException($"The Seq request failed ({(int)response.StatusCode}/{response.StatusCode}).", response.StatusCode);
throw new SeqApiException(exceptionMessage, response.StatusCode);
}

HttpContent MakeJsonContent(object content)
Expand Down
1 change: 0 additions & 1 deletion src/Seq.Api/Model/Alerting/AlertOccurrencePart.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Seq.Api.Model.AppInstances;
using Seq.Api.Model.LogEvents;
using Seq.Api.Model.Shared;

Expand Down
3 changes: 1 addition & 2 deletions src/Seq.Api/Model/Alerting/AlertOccurrenceRangePart.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Seq.Api.Model.LogEvents;
using Seq.Api.Model.Shared;
using Seq.Api.Model.Shared;

namespace Seq.Api.Model.Alerting
{
Expand Down
22 changes: 6 additions & 16 deletions src/Seq.Api/Model/Alerting/AlertStateEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using Seq.Api.Model.LogEvents;

namespace Seq.Api.Model.Alerting
{
Expand Down Expand Up @@ -41,25 +41,15 @@ public class AlertStateEntity : Entity
/// The ids of app instances that receive notifications when the alert is triggered.
/// </summary>
public List<string> NotificationAppInstanceIds { get; set; }

/// <summary>
/// The time at which the alert was last checked. Not preserved across server restarts.
/// </summary>
public DateTime? LastCheck { get; set; }

/// <summary>
/// The time at which the alert last triggered a notification. Not preserved across server restarts.
/// </summary>
public DateTime? LastNotification { get; set; }

/// <summary>
/// The time until which no further notifications will be sent by the alert.
/// A level indicating the severity or priority of the alert.
/// </summary>
public DateTime? SuppressedUntil { get; set; }
public LogEventLevel NotificationLevel { get; set; }

/// <summary>
/// <c>true</c> if the alert is in the failing state; otherwise, <c>false</c>.
/// Any recent activity for the alert.
/// </summary>
public bool IsFailing { get; set; }
public AlertActivityPart Activity { get; set; }
}
}
37 changes: 37 additions & 0 deletions src/Seq.Api/Model/Apps/AppPackageIdentityPart.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright © Datalust and contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Seq.Api.Model.Apps
{
/// <summary>
/// The data required to identify a NuGet package version.
/// </summary>
public class AppPackageIdentityPart
{
/// <summary>
/// The id of the <see cref="Seq.Api.Model.Feeds.NuGetFeedEntity"/> from which the package was installed.
/// </summary>
public string NuGetFeedId { get; set; }

/// <summary>
/// The package id, for example <c>Seq.Input.HealthCheck</c>.
/// </summary>
public string PackageId { get; set; }

/// <summary>
/// The version of the package.
/// </summary>
public string Version { get; set; }
}
}
17 changes: 1 addition & 16 deletions src/Seq.Api/Model/Apps/AppPackagePart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,8 @@ namespace Seq.Api.Model.Apps
/// <summary>
/// Describes a NuGet package containing executable app components.
/// </summary>
public class AppPackagePart
public class AppPackagePart : AppPackageIdentityPart
{
/// <summary>
/// The id of the <see cref="NuGetFeedEntity"/> from which the package was installed.
/// </summary>
public string NuGetFeedId { get; set; }

/// <summary>
/// The package id, for example <c>Seq.Input.HealthCheck</c>.
/// </summary>
public string PackageId { get; set; }

/// <summary>
/// The version of the package.
/// </summary>
public string Version { get; set; }

/// <summary>
/// Package authorship information.
/// </summary>
Expand Down
28 changes: 19 additions & 9 deletions src/Seq.Api/Model/Cluster/ClusterNodeEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,40 @@ namespace Seq.Api.Model.Cluster
public class ClusterNodeEntity : Entity
{
/// <summary>
/// The role the node is currently acting in.
/// An informational name associated with the node.
/// </summary>
public NodeRole Role { get; set; }
public string Name { get; set; }

/// <summary>
/// An informational name associated with the node.
/// The address the node will serve intra-cluster traffic on.
/// </summary>
public string Name { get; set; }

public string ClusterListenUri { get; set; }
/// <summary>
/// An informational representation of the storage generation committed to the node.
/// The address the node will serve regular API requests on.
/// </summary>
public string Generation { get; set; }
public string InternalListenUri { get; set; }

/// <summary>
/// Whether any writes have occurred since the node's last completed sync.
/// </summary>
public bool? IsUpToDate { get; set; }
public bool IsUpToDate { get; set; }

/// <summary>
/// The time since the node's last completed sync operation.
/// </summary>
public double? MillisecondsSinceLastSync { get; set; }
public double? DataAgeMilliseconds { get; set; }

/// <summary>
/// The time since the follower's active sync was started.
/// </summary>
public double? MillisecondsSinceActiveSync { get; set; }

/// <summary>
/// The time since the follower's last heartbeat.
/// </summary>
public double? MillisecondsSinceLastHeartbeat { get; set; }

/// <summary>
/// The total number of operations in the active sync.
/// </summary>
Expand All @@ -64,5 +69,10 @@ public class ClusterNodeEntity : Entity
/// information about the node is available.
/// </summary>
public string StateDescription { get; set; }

/// <summary>
/// Whether the node is currently leading the cluster.
/// </summary>
public bool IsLeading { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,18 @@
namespace Seq.Api.Model.Cluster
{
/// <summary>
/// The role a node is acting in within a cluster of connected Seq instances.
/// A result reported from a health check endpoint.
/// </summary>
public enum NodeRole
public class HealthCheckResultPart
{
/// <summary>
/// The node is not part of a cluster.
/// The status reported by the endpoint.
/// </summary>
Standalone,

/// <summary>
/// The node is a replica, following the state of a leader node.
/// </summary>
Follower,

public HealthStatus Status { get; set; }

/// <summary>
/// The node is a replication leader.
/// An informational description of the reported status.
/// </summary>
Leader
public string Description { get; set; }
}
}
39 changes: 39 additions & 0 deletions src/Seq.Api/Model/Cluster/HealthStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright Datalust and contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Seq.Api.Model.Cluster
{
/// <summary>
/// A status value returned from a health check endpoint.
/// </summary>
/// <remarks>Note that HTTP status code values returned from health checks should be inspected prior to
/// reading status information from the health check response payload.</remarks>
public enum HealthStatus
{
/// <summary>
/// The target is healthy.
/// </summary>
Healthy,

/// <summary>
/// The target is functioning in a degraded state; attention is required.
/// </summary>
Degraded,

/// <summary>
/// The target is unhealthy.
/// </summary>
Unhealthy
}
}
9 changes: 7 additions & 2 deletions src/Seq.Api/Model/Dashboarding/ChartPart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ public class ChartPart
/// The individual queries making up the chart. In most instances, only one query is currently supported
/// here.
/// </summary>
public List<ChartQueryPart> Queries { get; set; } = new List<ChartQueryPart>();
public List<ChartQueryPart> Queries { get; set; } = new();

/// <summary>
/// How the chart will appear on the dashboard.
/// </summary>
public ChartDisplayStylePart DisplayStyle { get; set; } = new ChartDisplayStylePart();
public ChartDisplayStylePart DisplayStyle { get; set; } = new();

/// <summary>
/// A short summary of the chart contents.
/// </summary>
public string Description { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/Seq.Api/Model/Dashboarding/MeasurementDisplayStylePart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public class MeasurementDisplayStylePart
/// For bar chart measurement display types, whether the sum of all bars will be shown as an overlay.
/// </summary>
public bool BarOverlaySum { get; set; }

/// <summary>
/// For heatmap measurement display types, whether the scale is logarithmic.
/// </summary>
public bool UseLogarithmicScale { get; set; }

/// <summary>
/// For measurement display types that include a legend, whether the legend will be shown.
Expand Down
7 changes: 6 additions & 1 deletion src/Seq.Api/Model/Dashboarding/MeasurementDisplayType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public enum MeasurementDisplayType
/// <summary>
/// A table of raw data values.
/// </summary>
Table
Table,

/// <summary>
/// A heatmap chart.
/// </summary>
Heatmap,
}
}
22 changes: 22 additions & 0 deletions src/Seq.Api/Model/Data/ColumnMetadataPart.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Newtonsoft.Json;

namespace Seq.Api.Model.Data
{
/// <summary>
/// The metadata that can be reported for a column.
/// </summary>
public class ColumnMetadataPart
{
/// <summary>
/// The error value for a column that is a `Bucket` expression.
/// </summary>
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal? BucketErrorParameter { get; set; }

/// <summary>
/// The time grouping in ticks.
/// </summary>
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal? IntervalTicks { get; set; }
}
}
11 changes: 11 additions & 0 deletions src/Seq.Api/Model/Data/QueryResultPart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ public class QueryResultPart
/// </summary>
public string[] Columns { get; set; }

/// <summary>
/// Metadata, grouped by column.
/// </summary>
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public Dictionary<int, ColumnMetadataPart> ColumnMetadata { get; set; }

/// <summary>
/// Metadata for the time grouping column.
/// </summary>
public ColumnMetadataPart TimeColumnMetadata { get; set; }

/// <summary>
/// Result rows.
/// </summary>
Expand Down
Loading