diff --git a/src/Elastic.Clients.Elasticsearch/Core/Infer/Metric/Metrics.cs b/src/Elastic.Clients.Elasticsearch/Core/Infer/Metric/Metrics.cs index 5bfcad4e8d3..808bc73c7cd 100644 --- a/src/Elastic.Clients.Elasticsearch/Core/Infer/Metric/Metrics.cs +++ b/src/Elastic.Clients.Elasticsearch/Core/Infer/Metric/Metrics.cs @@ -3,51 +3,87 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; +using System.Linq; using Elastic.Transport; namespace Elastic.Clients.Elasticsearch; +/// +/// Represents a collection of unique metric names to be included in URL paths to limit the request. +/// public sealed class Metrics : IEquatable, IUrlParameter { - // TODO: Complete this + private static readonly HashSet EmptyMetrics = new(); - //internal Metrics(IndicesStatsMetric metric) => Value = metric; + /// + /// An instance of representing all statistics. + /// + public static Metrics All { get; } = new("_all"); - //internal Metrics(NodesStatsMetric metric) => Value = metric; + /// + /// Initializes a new instance of the class containing a single metric name. + /// + public Metrics(string metric) + { + if (string.IsNullOrEmpty(metric)) + Values = EmptyMetrics; - //internal Metrics(NodesInfoMetric metric) => Value = metric; + Values = new HashSet() + { + metric + }; + } - //internal Metrics(ClusterStateMetric metric) => Value = metric; + /// + /// Initializes a new instance of the class containing a collection of metric names. + /// + public Metrics(IEnumerable metrics) + { + if (metrics is null) + Values = EmptyMetrics; - //internal Metrics(WatcherStatsMetric metric) => Value = metric; + Values = new HashSet(metrics); + } - //internal Metrics(NodesUsageMetric metric) => Value = metric; + private HashSet Values { get; } - internal Enum Value { get; } + /// + public bool Equals(Metrics other) + { + if (other is null) return false; - public bool Equals(Metrics other) => Value.Equals(other.Value); + // Equality is true when the metrics names in both instances are equal, regardless of their order in the set. + return Values.OrderBy(t => t).SequenceEqual(other.Values.OrderBy(t => t)); + } - string IUrlParameter.GetString(ITransportConfiguration settings) => string.Empty; // TODO Value.GetStringValue(); + string IUrlParameter.GetString(ITransportConfiguration settings) => GetString(); - //public static implicit operator Metrics(IndicesStatsMetric metric) => new Metrics(metric); + /// + public override string ToString() => GetString(); - //public static implicit operator Metrics(NodesStatsMetric metric) => new Metrics(metric); + private string GetString() + { + if (Values == EmptyMetrics) + return string.Empty; - //public static implicit operator Metrics(NodesInfoMetric metric) => new Metrics(metric); + return string.Join(",", Values); + } - //public static implicit operator Metrics(ClusterStateMetric metric) => new Metrics(metric); + /// + public override int GetHashCode() => Values != null ? Values.GetHashCode() : 0; - //public static implicit operator Metrics(WatcherStatsMetric metric) => new Metrics(metric); - - //public static implicit operator Metrics(NodesUsageMetric metric) => new Metrics(metric); - - public bool Equals(Enum other) => Value.Equals(other); - - public override bool Equals(object obj) => obj is Enum e ? Equals(e) : obj is Metrics m && Equals(m.Value); + public static bool operator ==(Metrics left, Metrics right) => Equals(left, right); + public static bool operator !=(Metrics left, Metrics right) => !Equals(left, right); - public override int GetHashCode() => Value != null ? Value.GetHashCode() : 0; + public static implicit operator Metrics(string metric) => new(metric); + public static implicit operator Metrics(string[] metrics) => new(metrics); - public static bool operator ==(Metrics left, Metrics right) => Equals(left, right); + /// + public override bool Equals(object obj) + { + if (obj is not Metrics metrics) return false; - public static bool operator !=(Metrics left, Metrics right) => !Equals(left, right); + return Equals(metrics); + } } diff --git a/tests/Tests/Common/UrlParameters/Metrics/MetricsTests.cs b/tests/Tests/Common/UrlParameters/Metrics/MetricsTests.cs new file mode 100644 index 00000000000..d784e2129c8 --- /dev/null +++ b/tests/Tests/Common/UrlParameters/Metrics/MetricsTests.cs @@ -0,0 +1,67 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +using Tests.Core.Extensions; + +using M = Elastic.Clients.Elasticsearch.Metrics; + +namespace Tests.Common.UrlParameters.Metrics; + +public class MetricsTests +{ + [U] + public void Equal() + { + var metrics = M.All; + + M[] equal = { M.All }; + + foreach (var value in equal) + { + (value == metrics).ShouldBeTrue(value); + value.Should().Be(metrics); + } + + metrics.Should().Be(M.All); + } + + [U] + public void SequenceEqual() + { + M metricsOne = new[] { "completion", "merge" }; + M metricsTwo = new[] { "merge", "completion" }; + + (metricsOne == metricsTwo).Should().BeTrue(); + metricsOne.Should().Be(metricsTwo); + } + + [U] + public void ToStringOverride() + { + M metrics = new[] { "completion", "merge" }; + metrics.ToString().Should().Be("completion,merge"); + } + + [U] + public void NotEqual() + { + var metrics = M.All; + + M[] notEqual = { "completion", "merge" }; + + foreach (var value in notEqual) + { + (value != metrics).ShouldBeTrue(value); + value.Should().NotBe(metrics); + } + } + + [U] + public void Null() + { + var value = M.All; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } +}