Skip to content
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
2 changes: 1 addition & 1 deletion src/Exceptionless.AppHost/Exceptionless.AppHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.0" />
<PackageReference Include="Aspire.Hosting.Azure.Storage" Version="13.1.0" />
<PackageReference Include="Aspire.Hosting.JavaScript" Version="13.1.0" />
<PackageReference Include="Aspire.Hosting.Redis" Version="13.1.0" />
<PackageReference Include="AspNetCore.HealthChecks.Elasticsearch" Version="9.0.0" />
<PackageReference Include="Foundatio.Minio" Version="13.0.0-beta1.3" />
</ItemGroup>

<ItemGroup>
Expand Down
143 changes: 0 additions & 143 deletions src/Exceptionless.AppHost/Extensions/MinIoExtensions.cs

This file was deleted.

19 changes: 14 additions & 5 deletions src/Exceptionless.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
.WithDataVolume("exceptionless.data.v1")
.WithKibana(b => b.WithLifetime(ContainerLifetime.Persistent).WithContainerName("Exceptionless-Kibana"));

var storage = builder.AddMinIo("Storage", s => s.WithCredentials("guest", "password").WithPorts(9000).WithBucket("ex-events"))
.WithLifetime(ContainerLifetime.Persistent)
.WithContainerName("Exceptionless-Storage");
var storage = builder.AddAzureStorage("Storage")
.RunAsEmulator(c =>
{
c.WithLifetime(ContainerLifetime.Persistent);
c.WithContainerName("Exceptionless-Storage");
c.WithDataVolume();
});

var storageBlobs = storage.AddBlobs("StorageBlobs");
var storageQueues = storage.AddQueues("StorageQueues");

var cache = builder.AddRedis("Redis", port: 6379)
.WithImageTag("7.4")
Expand All @@ -28,7 +35,8 @@
builder.AddProject<Projects.Exceptionless_Job>("Jobs", "AllJobs")
.WithReference(cache)
.WithReference(elastic)
.WithReference(storage, "MinIO")
.WithReference(storageBlobs, "AzureStorage")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Don't love that this matches the provider name for our configuration connection strings but it defines what it is.

.WithReference(storageQueues, "AzureQueues")
.WithEnvironment("ConnectionStrings:Email", "smtp://localhost:1025")
.WaitFor(elastic)
.WaitFor(cache)
Expand All @@ -39,7 +47,8 @@
var api = builder.AddProject<Projects.Exceptionless_Web>("Api", "Exceptionless")
.WithReference(cache)
.WithReference(elastic)
.WithReference(storage, "MinIO")
.WithReference(storageBlobs, "AzureStorage")
.WithReference(storageQueues, "AzureQueues")
.WithEnvironment("ConnectionStrings:Email", "smtp://localhost:1025")
.WithEnvironment("RunJobsInProcess", "false")
.WaitFor(elastic)
Expand Down
35 changes: 22 additions & 13 deletions src/Exceptionless.Core/Configuration/QueueOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class QueueOptions
{
public string? ConnectionString { get; internal set; }
public string? Provider { get; internal set; }
public Dictionary<string, string> Data { get; internal set; } = null!;
public Dictionary<string, string> Data { get; internal set; } = new(StringComparer.OrdinalIgnoreCase);

public string Scope { get; internal set; } = null!;
public string ScopePrefix { get; internal set; } = null!;
Expand All @@ -18,36 +18,45 @@ public class QueueOptions

public static QueueOptions ReadFromConfiguration(IConfiguration config, AppOptions appOptions)
{
var options = new QueueOptions { Scope = appOptions.AppScope };
options.ScopePrefix = !String.IsNullOrEmpty(options.Scope) ? $"{options.Scope}-" : String.Empty;
var options = new QueueOptions
{
Scope = appOptions.AppScope,
ScopePrefix = !String.IsNullOrEmpty(appOptions.AppScope) ? $"{appOptions.AppScope}-" : String.Empty,
MetricsPollingInterval = appOptions.AppMode == AppMode.Development ? TimeSpan.FromSeconds(15) : TimeSpan.FromSeconds(5)
};

string? cs = config.GetConnectionString("Queue");
if (cs != null)
if (!String.IsNullOrWhiteSpace(cs))
{
options.Data = cs.ParseConnectionString();
options.Provider = options.Data.GetString(nameof(options.Provider));
}
else
{
var redisConnectionString = config.GetConnectionString("Redis");
string? azureStorageConnectionString = config.GetConnectionString("AzureQueues");
if (!String.IsNullOrEmpty(azureStorageConnectionString))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

was forced to simplify somethings here if you have an AzureQueues connection string we just use the connection string. Noramlized Redis that way too. We need towards making our configuration easier to understand, this was required at least for queueus because if it falls through and looks up the provider connection string it will get replaced with the storage connection string (and not the queue one).

{
options.Provider = "azurestorage";
options.ConnectionString = azureStorageConnectionString;
options.Data = azureStorageConnectionString.ParseConnectionString();
return options;
}

string? redisConnectionString = config.GetConnectionString("Redis");
if (!String.IsNullOrEmpty(redisConnectionString))
{
options.Provider = "redis";
options.ConnectionString = redisConnectionString;
options.Data = redisConnectionString.ParseConnectionString();
return options;
}
}

string? providerConnectionString = !String.IsNullOrEmpty(options.Provider) ? config.GetConnectionString(options.Provider) : null;
if (!String.IsNullOrEmpty(providerConnectionString))
{
var providerOptions = providerConnectionString.ParseConnectionString(defaultKey: "server");
options.Data ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
options.Data.AddRange(providerOptions);
}
options.Data.AddRange(providerConnectionString.ParseConnectionString());
Comment thread
niemyjski marked this conversation as resolved.

options.ConnectionString = options.Data.BuildConnectionString(new HashSet<string> { nameof(options.Provider) });

options.MetricsPollingInterval = appOptions.AppMode == AppMode.Development ? TimeSpan.FromSeconds(15) : TimeSpan.FromSeconds(5);

return options;
}
}
27 changes: 14 additions & 13 deletions src/Exceptionless.Core/Configuration/StorageOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,42 @@ public class StorageOptions
{
public string? ConnectionString { get; internal set; }
public string? Provider { get; internal set; }
public Dictionary<string, string> Data { get; internal set; } = null!;
public Dictionary<string, string> Data { get; internal set; } = new(StringComparer.OrdinalIgnoreCase);

public string Scope { get; internal set; } = null!;
public string ScopePrefix { get; internal set; } = null!;

public static StorageOptions ReadFromConfiguration(IConfiguration config, AppOptions appOptions)
{
var options = new StorageOptions { Scope = appOptions.AppScope };
options.ScopePrefix = !String.IsNullOrEmpty(options.Scope) ? $"{options.Scope}-" : String.Empty;
var options = new StorageOptions
{
Scope = appOptions.AppScope,
ScopePrefix = !String.IsNullOrEmpty(appOptions.AppScope) ? $"{appOptions.AppScope}-" : String.Empty
};

string? cs = config.GetConnectionString("Storage");
if (cs != null)
if (!String.IsNullOrWhiteSpace(cs))
{
options.Data = cs.ParseConnectionString();
options.Provider = options.Data.GetString(nameof(options.Provider));
}
else
{
string? minioConnectionString = config.GetConnectionString("MinIO");
if (!String.IsNullOrEmpty(minioConnectionString))
string? azureStorageConnectionString = config.GetConnectionString("AzureStorage");
if (!String.IsNullOrEmpty(azureStorageConnectionString))
{
options.Provider = "minio";
options.Provider = "azurestorage";
options.ConnectionString = azureStorageConnectionString;
options.Data = azureStorageConnectionString.ParseConnectionString();
return options;
}
}

string? providerConnectionString = !String.IsNullOrEmpty(options.Provider) ? config.GetConnectionString(options.Provider) : null;
if (!String.IsNullOrEmpty(providerConnectionString))
{
var providerOptions = providerConnectionString.ParseConnectionString(defaultKey: "server");
options.Data ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
options.Data.AddRange(providerOptions);
}
options.Data.AddRange(providerConnectionString.ParseConnectionString());
Comment thread
niemyjski marked this conversation as resolved.

options.ConnectionString = options.Data.BuildConnectionString(new HashSet<string> { nameof(options.Provider) });

return options;
}
}
9 changes: 9 additions & 0 deletions src/Exceptionless.Core/Extensions/DictionaryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ namespace Exceptionless.Core.Extensions;

public static class DictionaryExtensions
{
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue>? dictionary, IDictionary<TKey, TValue>? range)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We were using the Foundatio.Repositories AddRange (we need to internalize that..) And that was throwing duplicate key because it was calling add on KVP. This is last in wins.

{
if (dictionary is null || range is null)
return;

foreach (var r in range)
dictionary[r.Key] = r.Value;
}

public static void Trim(this HashSet<string?> items, Predicate<string?> itemsToRemove, Predicate<string?> itemsToAlwaysInclude, int maxLength)
{
items.RemoveWhere(itemsToRemove);
Expand Down
11 changes: 0 additions & 11 deletions src/Exceptionless.Insulation/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,17 +230,6 @@ private static void RegisterStorage(IServiceCollection container, StorageOptions
return storage;
});
}
else if (String.Equals(options.Provider, "minio"))
{
container.ReplaceSingleton<IFileStorage>(s => new MinioFileStorage(new MinioFileStorageOptions
{
ConnectionString = options.ConnectionString,
Serializer = s.GetRequiredService<ITextSerializer>(),
TimeProvider = s.GetRequiredService<TimeProvider>(),
ResiliencePolicyProvider = s.GetRequiredService<IResiliencePolicyProvider>(),
LoggerFactory = s.GetRequiredService<ILoggerFactory>()
}));
}
else if (String.Equals(options.Provider, "s3"))
{
container.ReplaceSingleton<IFileStorage>(s => new S3FileStorage(o => o
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<PackageReference Include="Foundatio.Aliyun" Version="13.0.0-beta1.3" />
<PackageReference Include="Foundatio.AWS" Version="13.0.0-beta1.11" />
<PackageReference Include="Foundatio.AzureStorage" Version="13.0.0-beta1.3" />
<PackageReference Include="Foundatio.Minio" Version="13.0.0-beta1.3" />
<PackageReference Include="Foundatio.RabbitMQ" Version="13.0.0-beta1.24" />
<PackageReference Include="Foundatio.Redis" Version="13.0.0-beta1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="10.0.2" />
Expand Down
3 changes: 3 additions & 0 deletions src/Exceptionless.Web/ClientApp/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ yarn.lock
# Generated files
src/lib/generated

# Third-party
.agents/

# UI components (shadcn)
src/lib/features/shared/components/ui
2 changes: 1 addition & 1 deletion src/Exceptionless.Web/ClientApp/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default ts.config(
}
},
{
ignores: ['build/', '.svelte-kit/', 'dist/', 'src/lib/generated/', 'src/lib/features/shared/components/ui/']
ignores: ['.agents/', 'build/', '.svelte-kit/', 'dist/', 'src/lib/generated/', 'src/lib/features/shared/components/ui/']
},
{
rules: {
Expand Down
2 changes: 1 addition & 1 deletion src/Exceptionless.Web/Exceptionless.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageReference Include="MiniValidation" Version="0.9.2" />
<PackageReference Include="NEST.JsonNetSerializer" Version="7.17.5" />
<PackageReference Include="OAuth2" Version="0.10.3" />
<PackageReference Include="Scalar.AspNetCore" Version="2.12.33" />
<PackageReference Include="Scalar.AspNetCore" Version="2.12.35" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
Expand Down
Loading