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

feat: automatically generated instanceId #226

Merged
merged 3 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 5 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ End Class

Dim unleashSettings As New UnleashSettings()
unleashSettings.AppName = "dotnet-test"
unleashSettings.InstanceTag = "instance z"
' add the custom http header provider to the settings
unleashSettings.UnleashCustomHttpHeaderProvider = New CustomHttpHeaderProvider()
unleashSettings.UnleashApi = new Uri("http://unleash.herokuapp.com/api/")
Expand Down Expand Up @@ -425,24 +424,13 @@ By default unleash-client fetches the feature toggles from unleash-server every
* When .json file does not exists
* When the named feature toggle does not exist in .json file

The backup file name will follow this pattern: `{fileNameWithoutExtension}-{AppName}-{InstanceTag}-{SdkVersion}.{extension}`, where InstanceTag is either what you configure on `UnleashSettings` during startup, or a formatted string with a random component following this pattern: `{Dns.GetHostName()}-generated-{Guid.NewGuid()}`.
The backup file name will follow this pattern: `{fileNameWithoutExtension}-{AppName}-{SdkVersion}.{extension}`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worth mentioning that we took this out and why

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if this is good enough or if you have a better idea: 00550c7


You can configure InstanceTag like this:
### InstanceTag

```csharp
var settings = new UnleashSettings()
{
AppName = "dotnet-test",
UnleashApi = new Uri("http://unleash.herokuapp.com/api/"),
// Set an instance tag for consistent backup file naming
InstanceTag = "CustomInstanceTag",
UnleashContextProvider = new AspNetContextProvider(),
CustomHttpHeaders = new Dictionary<string, string>()
{
{"Authorization", "API token" }
}
};
```
As of version `5.0.0`, `InstanceTag` is no longer a property of `UnleashSettings`. Instead, an internal `InstanceId` is automatically generated.

This means that the backup file names have been simplified and no longer include the `InstanceTag` property value.

## Bootstrapping
* Unleash supports bootstrapping from a JSON string.
Expand Down
1 change: 0 additions & 1 deletion samples/WebApp/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ protected void Application_Start()
UnleashApi = new Uri("http://unleash.herokuapp.com/api/"),
//UnleashApi = new Uri("http://localhost:4242/api/"),
AppName = "dotnet-api-test",
InstanceTag = "instance 1",
SendMetricsInterval = TimeSpan.FromSeconds(20),
UnleashContextProvider = new AspNetContextProvider(),
//JsonSerializer = new JsonNetSerializer()
Expand Down
1 change: 0 additions & 1 deletion samples/WebApplication/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public void ConfigureServices(IServiceCollection services)
{
UnleashApi = new Uri("http://localhost:4242/api"),
AppName = "variant-sample",
InstanceTag = "instance 1",
SendMetricsInterval = TimeSpan.FromSeconds(10),
FetchTogglesInterval = TimeSpan.FromSeconds(10),
});
Expand Down
1 change: 0 additions & 1 deletion samples/WinFormsApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ static void Main()
UnleashApi = new Uri("http://unleash.herokuapp.com/api/"),
//UnleashApi = new Uri("http://localhost:4242/api/"),
AppName = "dotnet-forms-test",
InstanceTag = "instance 1",
SendMetricsInterval = TimeSpan.FromSeconds(5),
FetchTogglesInterval = TimeSpan.FromSeconds(10),
UnleashContextProvider = new WinFormsContextProvider(form),
Expand Down
4 changes: 2 additions & 2 deletions src/Unleash/Communication/UnleashApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public async Task<bool> SendMetrics(ThreadSafeMetricsBucket metrics, Cancellatio
jsonSerializer.Serialize(memoryStream, new ClientMetrics
{
AppName = clientRequestHeaders.AppName,
InstanceId = clientRequestHeaders.InstanceTag,
InstanceId = clientRequestHeaders.InstanceId,
Bucket = bucket
});
}
Expand Down Expand Up @@ -290,7 +290,7 @@ private static void SetRequestHeaders(HttpRequestMessage requestMessage, Unleash

requestMessage.Headers.TryAddWithoutValidation(appNameHeader, headers.AppName);
requestMessage.Headers.TryAddWithoutValidation(userAgentHeader, headers.AppName);
requestMessage.Headers.TryAddWithoutValidation(instanceIdHeader, headers.InstanceTag);
requestMessage.Headers.TryAddWithoutValidation(instanceIdHeader, headers.InstanceId);
requestMessage.Headers.TryAddWithoutValidation(supportedSpecVersionHeader, headers.SupportedSpecVersion);

SetCustomHeaders(requestMessage, headers.CustomHttpHeaders);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Unleash.Communication
internal class UnleashApiClientRequestHeaders
{
public string AppName { get; set; }
public string InstanceTag { get; set; }
public string InstanceId { get; set; }
public Dictionary<string,string> CustomHttpHeaders { get; set; }
public IUnleashCustomHttpHeaderProvider CustomHttpHeaderProvider { get; set; }
public string SupportedSpecVersion { get; internal set; }
Expand Down
7 changes: 1 addition & 6 deletions src/Unleash/Events/ErrorType.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Unleash.Events
namespace Unleash.Events
{
public enum ErrorType
{
Client,
TogglesBackup,
Bootstrap,
ImpressionEvent,
FileCache
Expand Down
2 changes: 1 addition & 1 deletion src/Unleash/Internal/UnleashServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public UnleashServices(UnleashSettings settings, EventCallbackConfig eventConfig
apiClient = new UnleashApiClient(httpClient, settings.JsonSerializer, new UnleashApiClientRequestHeaders()
{
AppName = settings.AppName,
InstanceTag = settings.InstanceTag,
InstanceId = settings.InstanceId,
CustomHttpHeaders = settings.CustomHttpHeaders,
CustomHttpHeaderProvider = settings.UnleashCustomHttpHeaderProvider,
SupportedSpecVersion = supportedSpecVersion
Expand Down
3 changes: 0 additions & 3 deletions src/Unleash/Internal/UnleashSettingsValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ public void Validate(UnleashSettings settings)
if (settings.AppName == null)
throw new UnleashException("You are required to specify an appName");

if (settings.InstanceTag == null)
throw new UnleashException("You are required to specify an instance id");

if (settings.JsonSerializer == null)
throw new UnleashException("You are required to specify an json serializer");

Expand Down
2 changes: 1 addition & 1 deletion src/Unleash/Scheduling/ClientRegistrationBackgroundTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)
var clientRegistration = new ClientRegistration
{
AppName = settings.AppName,
InstanceId = settings.InstanceTag,
InstanceId = settings.InstanceId,
Interval = (long)settings.SendMetricsInterval.Value.TotalMilliseconds,
SdkVersion = settings.SdkVersion,
Started = DateTimeOffset.UtcNow,
Expand Down
2 changes: 0 additions & 2 deletions src/Unleash/Scheduling/FetchFeatureTogglesTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)
catch (IOException ex)
{
Logger.Warn(() => $"UNLEASH: Exception when writing to toggle file '{toggleFile}'.", ex);
eventConfig?.RaiseError(new ErrorEvent() { ErrorType = ErrorType.TogglesBackup, Error = ex });
}

Etag = result.Etag;
Expand All @@ -101,7 +100,6 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)
catch (IOException ex)
{
Logger.Warn(() => $"UNLEASH: Exception when writing to ETag file '{etagFile}'.", ex);
eventConfig?.RaiseError(new ErrorEvent() { ErrorType = ErrorType.TogglesBackup, Error = ex });
}
}

Expand Down
15 changes: 4 additions & 11 deletions src/Unleash/UnleashSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ public class UnleashSettings
public string Environment { get; set; } = "default";

/// <summary>
/// Gets or sets an instance tag. Used for communication with backend api.
/// INTERNAL: Gets or sets an instance id. Used for communication with backend api.
/// </summary>
public string InstanceTag { get; set; } = GetDefaultInstanceTag();
internal string InstanceId { get; set; } = Guid.NewGuid().ToString();

/// <summary>
/// Sets the project to fetch feature toggles for.
Expand Down Expand Up @@ -150,13 +150,6 @@ private static string GetSdkVersion()
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>
Expand All @@ -166,7 +159,7 @@ public override string ToString()

sb.AppendLine($"Application name: {AppName}");
sb.AppendLine($"Environment: {Environment}");
sb.AppendLine($"Instance tag: {InstanceTag}");
sb.AppendLine($"Instance Id: {InstanceId}");
sb.AppendLine($"Project Id: {ProjectId}");
sb.AppendLine($"Server Uri: {UnleashApi}");
sb.AppendLine($"Sdk version: {SdkVersion}");
Expand Down Expand Up @@ -210,7 +203,7 @@ private string PrependFileName(string filename)
var extension = Path.GetExtension(filename);
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filename);

return new string($"{fileNameWithoutExtension}-{AppName}-{InstanceTag}-{SdkVersion}{extension}"
return new string($"{fileNameWithoutExtension}-{AppName}-{SdkVersion}{extension}"
.Where(c => !invalidFileNameChars.Contains(c))
.ToArray());
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Unleash.Tests/ClientFactory/SyncStartupUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class SyncStartupUnitTest
public void Setup()
{
mockApiClient = A.Fake<IUnleashApiClient>();
settings = new MockedUnleashSettings(instanceTag: "test instance SyncStartupUnitTest");
settings = new MockedUnleashSettings();
unleashFactory = new UnleashClientFactory();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ private static IUnleashApiClient CreateApiClient()
var requestHeaders = new UnleashApiClientRequestHeaders
{
AppName = "api-test-client",
InstanceTag = "instance1",
CustomHttpHeaders = new Dictionary<string, string>()
{
// "Test" token from 21.10.2021
Expand Down
1 change: 0 additions & 1 deletion tests/Unleash.Tests/Communication/CustomHeadersUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ private IUnleashApiClient CreateApiClient()
var requestHeaders = new UnleashApiClientRequestHeaders
{
AppName = "api-test-client",
InstanceTag = "instance1",
CustomHttpHeaders = httpHeaders,
CustomHttpHeaderProvider = httpHeadersProvider
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ private UnleashApiClient NewTestableClient(string project, MockHttpMessageHandle
var requestHeaders = new UnleashApiClientRequestHeaders
{
AppName = "api-test-client",
InstanceTag = "instance1",
CustomHttpHeaders = null,
CustomHttpHeaderProvider = null
};
Expand Down
2 changes: 1 addition & 1 deletion tests/Unleash.Tests/ExampleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ExampleTests
public async Task Setup()
{
var factory = new UnleashClientFactory();
unleash = await factory.CreateClientAsync(new MockedUnleashSettings(instanceTag: "test instance ExampleTests"), true);
unleash = await factory.CreateClientAsync(new MockedUnleashSettings(), true);
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion tests/Unleash.Tests/IOTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private static void LockFile(object data)
[Test]
public async Task GracefullyFailsWhenFileLocked()
{
var settings = new MockedUnleashSettings(false, "test instance IOTests");
var settings = new MockedUnleashSettings(false);

var toggleFile = settings.GetFeatureToggleFilePath();
var eTagFile = settings.GetFeatureToggleETagFilePath();
Expand Down
69 changes: 0 additions & 69 deletions tests/Unleash.Tests/Internal/ErrorEvents_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,75 +116,6 @@ public void FetchFeatureToggleTask_HttpRequestException_Raises_ErrorEvent()
thrownException.Should().NotBeNull();
}

[Test]
public void FetchFeatureToggleTask_Serialization_Throws_Raises_ErrorEvent()
{
// Arrange
ErrorEvent callbackEvent = null;
var exceptionMessage = "Serialization failed";
var callbackConfig = new EventCallbackConfig()
{
ErrorEvent = evt => { callbackEvent = evt; }
};

var fakeApiClient = A.Fake<IUnleashApiClient>();
A.CallTo(() => fakeApiClient.FetchToggles(A<string>._, A<CancellationToken>._, false))
.Returns(Task.FromResult(new FetchTogglesResult() { HasChanged = true, ToggleCollection = new ToggleCollection(), Etag = "one" }));

var collection = new ThreadSafeToggleCollection();
var serializer = A.Fake<IJsonSerializer>();
A.CallTo(() => serializer.Serialize(A<Stream>._, A<ToggleCollection>._))
.Throws(() => new IOException(exceptionMessage));

var filesystem = new MockFileSystem();
var tokenSource = new CancellationTokenSource();
var task = new FetchFeatureTogglesTask(fakeApiClient, collection, serializer, filesystem, callbackConfig, "togglefile.txt", "etagfile.txt", false);

// Act
Task.WaitAll(task.ExecuteAsync(tokenSource.Token));

// Assert
callbackEvent.Should().NotBeNull();
callbackEvent.Error.Should().NotBeNull();
callbackEvent.Error.Message.Should().Be(exceptionMessage);
callbackEvent.ErrorType.Should().Be(ErrorType.TogglesBackup);
}

[Test]
public void FetchFeatureToggleTask_Etag_Writing_Throws_Raises_ErrorEvent()
{
// Arrange
ErrorEvent callbackEvent = null;
var exceptionMessage = "Writing failed";
var callbackConfig = new EventCallbackConfig()
{
ErrorEvent = evt => { callbackEvent = evt; }
};

var fakeApiClient = A.Fake<IUnleashApiClient>();
A.CallTo(() => fakeApiClient.FetchToggles(A<string>._, A<CancellationToken>._, false))
.Returns(Task.FromResult(new FetchTogglesResult() { HasChanged = true, ToggleCollection = new ToggleCollection(), Etag = "one" }));

var collection = new ThreadSafeToggleCollection();
var serializer = A.Fake<IJsonSerializer>();

var filesystem = A.Fake<IFileSystem>();
A.CallTo(() => filesystem.WriteAllText(A<string>._, A<string>._))
.Throws(() => new IOException(exceptionMessage));

var tokenSource = new CancellationTokenSource();
var task = new FetchFeatureTogglesTask(fakeApiClient, collection, serializer, filesystem, callbackConfig, "togglefile.txt", "etagfile.txt", false);

// Act
Task.WaitAll(task.ExecuteAsync(tokenSource.Token));

// Assert
callbackEvent.Should().NotBeNull();
callbackEvent.Error.Should().NotBeNull();
callbackEvent.Error.Message.Should().Be(exceptionMessage);
callbackEvent.ErrorType.Should().Be(ErrorType.TogglesBackup);
}

[Test]
public void CachedFilesLoader_Raises_ErrorEvent()
{
Expand Down
3 changes: 1 addition & 2 deletions tests/Unleash.Tests/MockedUnleashSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ namespace Unleash.Tests
{
public class MockedUnleashSettings : UnleashSettings
{
public MockedUnleashSettings(bool mockFileSystem = true, string instanceTag = "test instance 1")
public MockedUnleashSettings(bool mockFileSystem = true)
{
AppName = "test";
InstanceTag = instanceTag;
UnleashApi = new Uri("http://localhost:4242/");

UnleashApiClient = new MockApiClient();
Expand Down
Loading