Skip to content

Commit

Permalink
feat: Flag metadata (open-feature#223)
Browse files Browse the repository at this point in the history
Signed-off-by: Artyom Tonoyan <[email protected]>
  • Loading branch information
askpt authored and arttonoyan committed Nov 17, 2024
1 parent 351d4af commit 403c40f
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 4 deletions.
76 changes: 76 additions & 0 deletions src/OpenFeature/Model/BaseMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;

#nullable enable
namespace OpenFeature.Model;

/// <summary>
/// Represents the base class for metadata objects.
/// </summary>
public abstract class BaseMetadata
{
private readonly ImmutableDictionary<string, object> _metadata;

internal BaseMetadata(Dictionary<string, object> metadata)
{
this._metadata = metadata.ToImmutableDictionary();
}

/// <summary>
/// Gets the boolean value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The boolean value associated with the key, or null if the key is not found.</returns>
public virtual bool? GetBool(string key)
{
return this.GetValue<bool>(key);
}

/// <summary>
/// Gets the integer value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The integer value associated with the key, or null if the key is not found.</returns>
public virtual int? GetInt(string key)
{
return this.GetValue<int>(key);
}

/// <summary>
/// Gets the double value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The double value associated with the key, or null if the key is not found.</returns>
public virtual double? GetDouble(string key)
{
return this.GetValue<double>(key);
}

/// <summary>
/// Gets the string value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The string value associated with the key, or null if the key is not found.</returns>
public virtual string? GetString(string key)
{
var hasValue = this._metadata.TryGetValue(key, out var value);
if (!hasValue)
{
return null;
}

return value as string ?? null;
}

private T? GetValue<T>(string key) where T : struct
{
var hasValue = this._metadata.TryGetValue(key, out var value);
if (!hasValue)
{
return null;
}

return value is T tValue ? tValue : null;
}
}
11 changes: 9 additions & 2 deletions src/OpenFeature/Model/FlagEvaluationDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace OpenFeature.Model
/// The contract returned to the caller that describes the result of the flag evaluation process.
/// </summary>
/// <typeparam name="T">Flag value type</typeparam>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.5.2/specification/types.md#evaluation-details"/>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#evaluation-details"/>
public sealed class FlagEvaluationDetails<T>
{
/// <summary>
Expand Down Expand Up @@ -45,6 +45,11 @@ public sealed class FlagEvaluationDetails<T>
/// </summary>
public string Variant { get; }

/// <summary>
/// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number.
/// </summary>
public FlagMetadata FlagMetadata { get; }

/// <summary>
/// Initializes a new instance of the <see cref="FlagEvaluationDetails{T}"/> class.
/// </summary>
Expand All @@ -54,15 +59,17 @@ public sealed class FlagEvaluationDetails<T>
/// <param name="reason">Reason</param>
/// <param name="variant">Variant</param>
/// <param name="errorMessage">Error message</param>
/// <param name="flagMetadata">Flag metadata</param>
public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, string reason, string variant,
string errorMessage = null)
string errorMessage = null, FlagMetadata flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
this.ErrorType = errorType;
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
this.FlagMetadata = flagMetadata;
}
}
}
28 changes: 28 additions & 0 deletions src/OpenFeature/Model/FlagMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;

#nullable enable
namespace OpenFeature.Model;

/// <summary>
/// Represents the metadata associated with a feature flag.
/// </summary>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#flag-metadata"/>
public sealed class FlagMetadata : BaseMetadata
{
/// <summary>
/// Constructor for the <see cref="BaseMetadata"/> class.
/// </summary>
public FlagMetadata() : this([])
{
}

/// <summary>
/// Constructor for the <see cref="BaseMetadata"/> class.
/// </summary>
/// <param name="metadata">The dictionary containing the metadata.</param>
public FlagMetadata(Dictionary<string, object> metadata) : base(metadata)
{
}
}
1 change: 1 addition & 0 deletions src/OpenFeature/Model/ProviderEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class ProviderEventPayload
/// <summary>
/// Metadata information for the event.
/// </summary>
// TODO: This needs to be changed to a EventMetadata object
public Dictionary<string, object> EventMetadata { get; set; }
}
}
11 changes: 9 additions & 2 deletions src/OpenFeature/Model/ResolutionDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace OpenFeature.Model
/// Describes the details of the feature flag being evaluated
/// </summary>
/// <typeparam name="T">Flag value type</typeparam>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.5.2/specification/types.md#resolution-details"/>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#resolution-details"/>
public sealed class ResolutionDetails<T>
{
/// <summary>
Expand Down Expand Up @@ -44,6 +44,11 @@ public sealed class ResolutionDetails<T>
/// </summary>
public string Variant { get; }

/// <summary>
/// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number.
/// </summary>
public FlagMetadata FlagMetadata { get; }

/// <summary>
/// Initializes a new instance of the <see cref="ResolutionDetails{T}"/> class.
/// </summary>
Expand All @@ -53,15 +58,17 @@ public sealed class ResolutionDetails<T>
/// <param name="reason">Reason</param>
/// <param name="variant">Variant</param>
/// <param name="errorMessage">Error message</param>
/// <param name="flagMetadata">Flag metadata</param>
public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorType.None, string reason = null,
string variant = null, string errorMessage = null)
string variant = null, string errorMessage = null, FlagMetadata flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
this.ErrorType = errorType;
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
this.FlagMetadata = flagMetadata;
}
}
}
Loading

0 comments on commit 403c40f

Please sign in to comment.