Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature-based Injection #335

Merged
merged 31 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
57d2243
init
zhiyuanliang-ms Dec 19, 2023
f9506c9
draft
zhiyuanliang-ms Dec 19, 2023
f9c1484
Merge branch 'preview' into zhiyuanliang/feature-based-injection
zhiyuanliang-ms Dec 19, 2023
5edd9be
use ValueTask
zhiyuanliang-ms Dec 19, 2023
06f410b
Merge branch 'preview' of https://github.com/microsoft/FeatureManagem…
zhiyuanliang-ms Dec 20, 2023
e1b2450
support factory method
zhiyuanliang-ms Dec 25, 2023
f497405
add example
zhiyuanliang-ms Dec 25, 2023
2b7ad46
Merge branch 'preview' of https://github.com/microsoft/FeatureManagem…
zhiyuanliang-ms Jan 8, 2024
d89abc8
update
zhiyuanliang-ms Jan 9, 2024
ca772ec
Update
zhiyuanliang-ms Jan 9, 2024
3710dab
Merge branch 'preview' into zhiyuanliang/feature-based-injection
zhiyuanliang-ms Jan 9, 2024
b92fefb
Update
zhiyuanliang-ms Jan 9, 2024
f3926f8
update example
zhiyuanliang-ms Jan 9, 2024
0d0f3f3
match variant name or configuration value
zhiyuanliang-ms Jan 9, 2024
176cf78
update to the latest design
zhiyuanliang-ms Jan 10, 2024
a7b8f0f
merge with preview branch
zhiyuanliang-ms Jan 18, 2024
73aac10
resolve comments
zhiyuanliang-ms Jan 18, 2024
25f91e9
remove check for variant value
zhiyuanliang-ms Jan 19, 2024
3ed4c4c
rename to VariantService
zhiyuanliang-ms Jan 19, 2024
941c7a1
update & add comments
zhiyuanliang-ms Jan 19, 2024
18ae0eb
remove POC example
zhiyuanliang-ms Jan 19, 2024
f48767c
add testcases & use method name GetServiceAsync
zhiyuanliang-ms Jan 22, 2024
1556c0d
update comments
zhiyuanliang-ms Jan 22, 2024
7120abd
add variant service cache
zhiyuanliang-ms Jan 29, 2024
1a4e0fa
resolve comments
zhiyuanliang-ms Jan 31, 2024
926182a
throw exception for duplicated registration
zhiyuanliang-ms Feb 1, 2024
1065d76
add testcase
zhiyuanliang-ms Feb 1, 2024
37cda1b
remove unused package
zhiyuanliang-ms Feb 7, 2024
df47105
update comment
zhiyuanliang-ms Feb 7, 2024
cbda0c6
set feature name in constructor
zhiyuanliang-ms Feb 9, 2024
6488a81
Merge branch 'preview' into zhiyuanliang/feature-based-injection
zhiyuanliang-ms Feb 9, 2024
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
7 changes: 7 additions & 0 deletions Microsoft.FeatureManagement.sln
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.FeatureManagement
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EvaluationDataToApplicationInsights", "examples\EvaluationDataToApplicationInsights\EvaluationDataToApplicationInsights.csproj", "{1502529E-47E9-4306-98C4-BF6CF7C7C275}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FeatureBasedInjectionPOC", "examples\FeatureBasedInjectionPOC\FeatureBasedInjectionPOC.csproj", "{6655016D-900B-42D2-AA43-C33B0E161D6B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -73,6 +75,10 @@ Global
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Release|Any CPU.Build.0 = Release|Any CPU
{6655016D-900B-42D2-AA43-C33B0E161D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6655016D-900B-42D2-AA43-C33B0E161D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6655016D-900B-42D2-AA43-C33B0E161D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6655016D-900B-42D2-AA43-C33B0E161D6B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -85,6 +91,7 @@ Global
{DACAB624-4611-42E8-844C-529F93A54980} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{283D3EBB-4716-4F1D-BA51-A435F7E2AB82} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{1502529E-47E9-4306-98C4-BF6CF7C7C275} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{6655016D-900B-42D2-AA43-C33B0E161D6B} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {84DA6C54-F140-4518-A1B4-E4CF42117FBD}
Expand Down
12 changes: 12 additions & 0 deletions examples/FeatureBasedInjectionPOC/AlgorithmAlpha.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace FeatureBasedInjectionPOC
{
internal class AlgorithmAlpha : IAlgorithm
{
public string Name { get; set; }

public AlgorithmAlpha()
{
Name = "Alpha";
}
}
}
12 changes: 12 additions & 0 deletions examples/FeatureBasedInjectionPOC/AlgorithmBeta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace FeatureBasedInjectionPOC
{
internal class AlgorithmBeta : IAlgorithm
{
public string Name { get; set; }

public AlgorithmBeta()
{
Name = "Beta";
}
}
}
15 changes: 15 additions & 0 deletions examples/FeatureBasedInjectionPOC/AlgorithmOmega.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.FeatureManagement;

namespace FeatureBasedInjectionPOC
{
[FeaturedServiceAlias("Omega")]
class AlgorithmOmega : IAlgorithm
{
public string Name { get; set; }

public AlgorithmOmega(string name)
{
Name = name;
}
}
}
12 changes: 12 additions & 0 deletions examples/FeatureBasedInjectionPOC/AlgorithmSigma.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace FeatureBasedInjectionPOC
{
internal class AlgorithmSigma : IAlgorithm
{
public string Name { get; set; }

public AlgorithmSigma()
{
Name = "Sigma";
}
}
}
25 changes: 25 additions & 0 deletions examples/FeatureBasedInjectionPOC/FeatureBasedInjectionPOC.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.FeatureManagement\Microsoft.FeatureManagement.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions examples/FeatureBasedInjectionPOC/IAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FeatureBasedInjectionPOC
{
public interface IAlgorithm
{
public string Name { get; }
zhiyuanliang-ms marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.FeatureManagement.FeatureFilters;

namespace FeatureBasedInjectionPOC
{
class OnDemandTargetingContextAccessor : ITargetingContextAccessor
{
public TargetingContext Current { get; set; }

public ValueTask<TargetingContext> GetContextAsync()
{
return new ValueTask<TargetingContext>(Current);
}
}
}
48 changes: 48 additions & 0 deletions examples/FeatureBasedInjectionPOC/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.FeatureManagement;
using Microsoft.FeatureManagement.FeatureFilters;
using FeatureBasedInjectionPOC;


IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();

IServiceCollection services = new ServiceCollection();

services.AddSingleton<IAlgorithm, AlgorithmAlpha>();
services.AddSingleton<IAlgorithm, AlgorithmBeta>();
services.AddSingleton<IAlgorithm, AlgorithmSigma>();
services.AddSingleton<IAlgorithm>(sp => new AlgorithmOmega("Omega"));

services.AddSingleton(configuration)
.AddFeatureManagement()
.AddFeatureFilter<TargetingFilter>()
.AddFeaturedService<IAlgorithm>("MyFeature");

var targetingContextAccessor = new OnDemandTargetingContextAccessor();

services.AddSingleton<ITargetingContextAccessor>(targetingContextAccessor);

using ServiceProvider serviceProvider = services.BuildServiceProvider();

IVariantFeatureManager featureManager = serviceProvider.GetRequiredService<IVariantFeatureManager>();

IFeaturedService<IAlgorithm> featuredAlgorithm = serviceProvider.GetRequiredService<IFeaturedService<IAlgorithm>>();

string[] userIds = { "Guest", "UserBeta", "UserSigma", "UserOmega" };

foreach (string userId in userIds)
{
targetingContextAccessor.Current = new TargetingContext
{
UserId = userId
};

IAlgorithm algorithm = await featuredAlgorithm.GetAsync(CancellationToken.None);

Variant variant = await featureManager.GetVariantAsync("MyFeature", CancellationToken.None);

Console.WriteLine($"Get algorithm {algorithm?.Name ?? "Null"} because the feature variant is {variant?.Name ?? "Null"}");
}
52 changes: 52 additions & 0 deletions examples/FeatureBasedInjectionPOC/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"FeatureManagement": {
"MyFeature": {
"EnabledFor": [
{
"Name": "Targeting",
"Parameters": {
"Audience": {
"Users": [
"UserOmega", "UserSigma", "UserBeta"
]
}
}
}
],
"Variants": [
{
"Name": "AlgorithmBeta"
},
{
"Name": "Sigma",
"ConfigurationValue": "AlgorithmSigma"
},
{
"Name": "Omega"
}
],
"Allocation": {
"User": [
{
"Variant": "AlgorithmBeta",
"Users": [
"UserBeta"
]
},
{
"Variant": "Omega",
"Users": [
"UserOmega"
]
},
{
"Variant": "Sigma",
"Users": [
"UserSigma"
]
}
]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation.
zhiyuanliang-ms marked this conversation as resolved.
Show resolved Hide resolved
// Licensed under the MIT license.
//
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.FeatureManagement.FeatureFilters;

namespace Microsoft.FeatureManagement.Telemetry.ApplicationInsights
{
/// <summary>
/// Provides extension methods for tracking events with <see cref="TargetingContext"/>.
/// </summary>
public static class TelemetryClientExtensions
{
/// <summary>
/// Extension method to track an event with <see cref="TargetingContext"/>.
/// </summary>
public static void TrackEvent(this TelemetryClient telemetryClient, string eventName, TargetingContext targetingContext, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
ValidateTargetingContext(targetingContext);

if (properties == null)
{
properties = new Dictionary<string, string>();
}

properties["TargetingId"] = targetingContext.UserId;

telemetryClient.TrackEvent(eventName, properties, metrics);
}

/// <summary>
/// Extension method to track an <see cref="EventTelemetry"/> with <see cref="TargetingContext"/>.
/// </summary>
public static void TrackEvent(this TelemetryClient telemetryClient, EventTelemetry telemetry, TargetingContext targetingContext)
{
ValidateTargetingContext(targetingContext);

if (telemetry == null)
{
telemetry = new EventTelemetry();
}

telemetry.Properties["TargetingId"] = targetingContext.UserId;

telemetryClient.TrackEvent(telemetry);
}

private static void ValidateTargetingContext(TargetingContext targetingContext)
{
if (targetingContext == null)
{
throw new ArgumentNullException(nameof(targetingContext));
}
}
}
}
Loading