-
Notifications
You must be signed in to change notification settings - Fork 39
/
UnleashSettings.cs
233 lines (190 loc) · 9.37 KB
/
UnleashSettings.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using Unleash.Communication;
using Unleash.Internal;
using Unleash.Scheduling;
using Unleash.Serialization;
using Unleash.Utilities;
namespace Unleash
{
/// <summary>
/// Unleash settings
/// </summary>
public class UnleashSettings
{
internal readonly Encoding Encoding = Encoding.UTF8;
internal readonly string FeatureToggleFilename = "unleash.toggles.json";
internal readonly string EtagFilename = "unleash.etag.txt";
/// <summary>
/// Gets the version of unleash client running.
/// </summary>
public string SdkVersion { get; } = GetSdkVersion();
/// <summary>
/// Gets or set the uri for the backend unleash server.
///
/// Default: http://unleash.herokuapp.com/api/
/// </summary>
public Uri UnleashApi { get; set; } = new Uri("http://unleash.herokuapp.com/api/");
/// <summary>
/// Gets or sets an application name. Used for communication with backend api.
/// </summary>
public string AppName { get; set; } = "my-awesome-app";
/// <summary>
/// Gets or sets an environment. Used for communication with backend api.
/// </summary>
public string Environment { get; set; } = "default";
/// <summary>
/// Gets or sets an instance tag. Used for communication with backend api.
/// </summary>
public string InstanceTag { get; set; } = GetDefaultInstanceTag();
/// <summary>
/// Sets the project to fetch feature toggles for.
/// </summary>
public string ProjectId { get; set; } = null;
/// <summary>
/// Gets or sets the interval in which feature toggle changes are re-fetched.
///
/// Default: 30 seconds
/// </summary>
public TimeSpan FetchTogglesInterval { get; set; } = TimeSpan.FromSeconds(30);
/// <summary>
/// Gets or sets the interval in which metrics are sent to the server. When null, no metrics are sent.
///
/// Default: 60s
/// </summary>
public TimeSpan? SendMetricsInterval { get; set; } = TimeSpan.FromSeconds(60);
/// <summary>
/// Gets or set a directory for storing temporary files (toggles and current etag values).
///
/// Default: Path.GetTempPath()
/// </summary>
public Func<string> LocalStorageFolder { get; set; } = Path.GetTempPath;
/// <summary>
/// Gets or sets a collection of custom http headers which will be included when communicating with the backend server.
/// </summary>
public Dictionary<string, string> CustomHttpHeaders { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Gets or sets a provider that returns a dictionary of custom http headers
/// which will be included when communicating with the backend server.
/// This provider will be called before each outgoing request to the unleash server.
/// </summary>
public IUnleashCustomHttpHeaderProvider UnleashCustomHttpHeaderProvider { get; set; } = new DefaultCustomHttpHeaderProvider();
/// <summary>
/// Gets or sets the unleash context provider. This is needed when using any of the activation strategies
/// that needs application specific context like userid etc.
///
/// Default: A provider with no context.
/// </summary>
public IUnleashContextProvider UnleashContextProvider { get; set; } = new DefaultUnleashContextProvider();
/// <summary>
/// Gets or sets a json serializer.
///
/// Default: A serializer based on Newtonsoft will be used, given that these assemblies are loaded into the appdomain already.
/// </summary>
public IJsonSerializer JsonSerializer { get; set; } = new DynamicNewtonsoftJsonSerializer();
/// <summary>
/// Get or sets a factory class for creating the HttpClient instance used for communicating with the backend.
/// </summary>
public IHttpClientFactory HttpClientFactory { get; set; } = new DefaultHttpClientFactory();
/// <summary>
/// Gets or sets the scheduled task manager used for syncing feature toggles and metrics with the backend in the background.
/// Default: An implementation based on System.Threading.Timers
/// </summary>
public IUnleashScheduledTaskManager ScheduledTaskManager { get; set; } = new SystemTimerScheduledTaskManager();
/// <summary>
/// INTERNAL: Gets or sets an api client instance. Can be used for testing/mocking etc.
/// </summary>
internal IUnleashApiClient UnleashApiClient { get; set; }
/// <summary>
/// INTERNAL: Gets or sets the file system abstraction. Can be used for testing/mocking etc.
/// </summary>
internal IFileSystem FileSystem { get; set; }
/// <summary>
/// Gets or sets the toggle bootstrap provider (file, url, etc). Can be used for testing/mocking etc.
/// </summary>
public IToggleBootstrapProvider ToggleBootstrapProvider { get; set; }
/// <summary>
/// Gets or sets the override behaviour of the Bootstrap Toggles feature
/// </summary>
public bool BootstrapOverride { get; set; } = true;
/// <summary>
/// INTERNAL: Gets or sets if the feature toggle fetch should be immeditely scheduled. Used by the client factory to prevent redundant initial fetches.
/// </summary>
internal bool ScheduleFeatureToggleFetchImmediatly { get; set; } = true;
internal bool ThrowOnInitialFetchFail { get; set; }
/// <summary>
/// Disables the error message if multiple instances of Unleash were instantiated in this memory space. Generally you aim to create only a single instance of Unleash in your application.
/// </summary>
internal bool DisableSingletonWarning { get; set; } = false;
private static string GetSdkVersion()
{
var assemblyName = Assembly.GetExecutingAssembly().GetName();
var version = assemblyName.Version.ToString(3);
return $"unleash-client-dotnet:v{version}";
}
private static string GetDefaultInstanceTag()
{
var hostName = Dns.GetHostName();
return $"{hostName}-generated-{Guid.NewGuid()}";
}
/// <summary>
/// Returns info about the unleash setup.
/// </summary>
public override string ToString()
{
var sb = new StringBuilder("## Unleash settings ##");
sb.AppendLine($"Application name: {AppName}");
sb.AppendLine($"Environment: {Environment}");
sb.AppendLine($"Instance tag: {InstanceTag}");
sb.AppendLine($"Project Id: {ProjectId}");
sb.AppendLine($"Server Uri: {UnleashApi}");
sb.AppendLine($"Sdk version: {SdkVersion}");
sb.AppendLine($"Fetch toggles interval: {FetchTogglesInterval.TotalSeconds} seconds");
var metricsInterval = SendMetricsInterval.HasValue
? $"{SendMetricsInterval.Value.TotalSeconds} seconds"
: "never";
sb.AppendLine($"Send metrics interval: {metricsInterval}");
sb.AppendLine($"Local storage folder: {LocalStorageFolder()}");
sb.AppendLine($"Backup file: {FeatureToggleFilename}");
sb.AppendLine($"Etag file: {EtagFilename}");
sb.AppendLine($"HttpClient Factory: {HttpClientFactory.GetType().Name}");
sb.AppendLine($"Json serializer: {JsonSerializer.GetType().Name}");
sb.AppendLine($"Context provider: {UnleashContextProvider.GetType().Name}");
sb.AppendLine($"Bootstrap overrides: {BootstrapOverride}");
sb.AppendLine($"Bootstrap provider: {ToggleBootstrapProvider?.GetType().Name ?? "null"}");
return sb.ToString();
}
public string GetFeatureToggleFilePath()
{
var tempFolder = LocalStorageFolder();
return Path.Combine(tempFolder, PrependFileName(FeatureToggleFilename));
}
public string GetFeatureToggleETagFilePath()
{
var tempFolder = LocalStorageFolder();
return Path.Combine(tempFolder, PrependFileName(EtagFilename));
}
private string PrependFileName(string filename)
{
var invalidFileNameChars = Path.GetInvalidFileNameChars();
var extension = Path.GetExtension(filename);
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filename);
return new string($"{fileNameWithoutExtension}-{AppName}-{InstanceTag}-{SdkVersion}{extension}"
.Where(c => !invalidFileNameChars.Contains(c))
.ToArray());
}
public void UseBootstrapUrlProvider(string path, bool shouldThrowOnError, Dictionary<string, string> customHeaders = null)
{
ToggleBootstrapProvider = new ToggleBootstrapUrlProvider(path, HttpClientFactory.Create(new Uri(path)), this, shouldThrowOnError, customHeaders);
}
public void UseBootstrapFileProvider(string path)
{
ToggleBootstrapProvider = new ToggleBootstrapFileProvider(path, this);
}
}
}