Skip to content

Commit 87ce139

Browse files
authored
Refactor feature flags to use environment variables for configuration in FeatureFlags.cs and update Workshop.md with new instructions (#17)
Signed-off-by: André Silva <[email protected]>
1 parent 40c1b69 commit 87ce139

File tree

3 files changed

+27
-24
lines changed

3 files changed

+27
-24
lines changed

Workshop.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ time with each exercise and don't hesitate to experiment!
3434

3535
- Navigate to `src/Garage.ServiceDefaults/Services/IFeatureFlags.cs`
3636
- Review the `EnableStatsHeader` flag interface
37-
- Look at `FeatureFlags.cs` to see the default implementation
37+
- Look at `FeatureFlags.cs` to see the environment variable implementation
3838

3939
2. Toggle the Statistics Header
4040

41-
- Locate where `EnableStatsHeader` is used in the web application
42-
- Change the default value from `true` to `false`
43-
- Observe the behavior change in the web frontend
44-
- Toggle it back to `true`
41+
- Locate the environment variables in `src/Garage.AppHost/Properties/launchSettings.json`
42+
- Change the `ENABLE_STATS_HEADER` environment variable from `"true"` to `"false"`
43+
- Restart the application to see the behavior change in the web frontend
44+
- Toggle it back to `"true"`
4545

4646
3. Verify the Changes
4747

@@ -52,7 +52,8 @@ time with each exercise and don't hesitate to experiment!
5252
4. Create a New Feature Flag
5353

5454
- Add a new boolean flag in `IFeatureFlags.cs` (`EnableTabs`) making sure it is `true`
55-
- Implement it in `FeatureFlags.cs`
55+
- Implement it in `FeatureFlags.cs` to read from environment variable `ENABLE_TABS`
56+
- Add the environment variable to `launchSettings.json` with value `"true"`
5657
- Use this flag in the `.collection-tabs` div in the `Home.razor` file
5758

5859
### Expected Outcome
@@ -62,6 +63,9 @@ You should see the statistics header toggle on and off based on your feature fla
6263
### Learning Outcomes
6364

6465
- Understand that feature flags are an application development practice that can be implemented basically (but as we'll see, can also become quite powerful and complex).
66+
- Learn how environment variables can be used to configure feature flags at application startup.
67+
68+
**Note**: In this initial exercise, feature flags are configured using environment variables in the `launchSettings.json` file. Changes require an application restart. Later exercises will introduce dynamic flag updates through OpenFeature.
6569

6670
---
6771

@@ -88,7 +92,7 @@ You should see the statistics header toggle on and off based on your feature fla
8892
3. Implement a Custom Provider
8993

9094
- Create a new class `CustomFeatureProvider` in `src/Garage.ServiceDefaults/Providers`
91-
- Use the `FeatureProvider` flags. Tip: You can copy the dictionary from `FeatureFlags.cs` to start and use the dictionary key as the flag key
95+
- Use the `FeatureProvider` base class. Tip: You can implement a dictionary with the same flag keys and default values as used in the environment variables
9296
- Add the provider to the OpenFeature configuration in `Extensions.cs`
9397

9498
4. Replace the IFeatureFlags dependency injection
@@ -383,10 +387,10 @@ You will have integrated telemetry for feature flags, allowing you to monitor th
383387

384388
Congratulations! You've completed the OpenFeature .NET workshop. You should now understand:
385389

386-
✅ Basic feature flag implementation
387-
✅ Performance tuning with feature flags
388-
✅ Architectural decisions using flags
389-
✅ OpenFeature provider integration
390+
✅ Basic feature flag implementation
391+
✅ Performance tuning with feature flags
392+
✅ Architectural decisions using flags
393+
✅ OpenFeature provider integration
390394
✅ Advanced targeting and evaluation
391395

392396
### Next Steps

src/Garage.AppHost/Properties/launchSettings.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
"ASPNETCORE_ENVIRONMENT": "Development",
1111
"DOTNET_ENVIRONMENT": "Development",
1212
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21198",
13-
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22178"
13+
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22178",
14+
"SLOW_OPERATION_DELAY": "1000",
15+
"ENABLE_DATABASE_WINNERS": "false",
16+
"ENABLE_STATS_HEADER": "true"
1417
}
1518
},
1619
"http": {
@@ -22,8 +25,11 @@
2225
"ASPNETCORE_ENVIRONMENT": "Development",
2326
"DOTNET_ENVIRONMENT": "Development",
2427
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19055",
25-
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20286"
28+
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20286",
29+
"SLOW_OPERATION_DELAY": "1000",
30+
"ENABLE_DATABASE_WINNERS": "false",
31+
"ENABLE_STATS_HEADER": "true"
2632
}
2733
}
2834
}
29-
}
35+
}

src/Garage.ServiceDefaults/Services/FeatureFlags.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,7 @@ namespace Garage.ServiceDefaults.Services;
22

33
public class FeatureFlags : IFeatureFlags
44
{
5-
private readonly Dictionary<string, object> _flags = new()
6-
{
7-
{ nameof(SlowOperationDelay), 1000 },
8-
{ nameof(EnableDatabaseWinners), false },
9-
{ nameof(EnableStatsHeader), true }
10-
};
11-
12-
public int SlowOperationDelay => _flags.TryGetValue(nameof(SlowOperationDelay), out var value) ? (int)value : 1000;
13-
public bool EnableDatabaseWinners => _flags.TryGetValue(nameof(EnableDatabaseWinners), out var value) && (bool)value;
14-
public bool EnableStatsHeader => _flags.TryGetValue(nameof(EnableStatsHeader), out var value) && (bool)value;
5+
public int SlowOperationDelay => int.TryParse(Environment.GetEnvironmentVariable("SLOW_OPERATION_DELAY"), out var delay) ? delay : 1000;
6+
public bool EnableDatabaseWinners => bool.TryParse(Environment.GetEnvironmentVariable("ENABLE_DATABASE_WINNERS"), out var enable) ? enable : false;
7+
public bool EnableStatsHeader => bool.TryParse(Environment.GetEnvironmentVariable("ENABLE_STATS_HEADER"), out var enable) ? enable : true; // Default to true
158
}

0 commit comments

Comments
 (0)