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
34 changes: 17 additions & 17 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
<AnalysisLevel>latest</AnalysisLevel>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<Deterministic>true</Deterministic>
<WarningsAsErrors>false</WarningsAsErrors>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
<AnalysisLevel>latest</AnalysisLevel>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<Deterministic>true</Deterministic>
<WarningsAsErrors>false</WarningsAsErrors>

<!-- Audit both top-level and transitive dependencies for vulnerabilities in NuGet packages. -->
<!-- https://learn.microsoft.com/en-us/nuget/concepts/auditing-packages#setting-a-security-audit-mode -->
<NuGetAuditMode>all</NuGetAuditMode>
<NuGetAuditLevel>low</NuGetAuditLevel>
</PropertyGroup>
<!-- Audit both top-level and transitive dependencies for vulnerabilities in NuGet packages. -->
<!-- https://learn.microsoft.com/en-us/nuget/concepts/auditing-packages#setting-a-security-audit-mode -->
<NuGetAuditMode>all</NuGetAuditMode>
<NuGetAuditLevel>low</NuGetAuditLevel>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" PrivateAssets="all" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" PrivateAssets="all"/>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt"/>
</ItemGroup>
</Project>
23 changes: 12 additions & 11 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<AvaloniaVersion>11.3.2</AvaloniaVersion>
<AvaloniaVersion>11.3.2</AvaloniaVersion>
</PropertyGroup>
<ItemGroup>
<!-- AspNetCore. -->
<PackageVersion Include="Markdown.Avalonia" Version="11.0.3-a1" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.19" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="System.IO.Pipelines" Version="8.0.0" />
<!-- Nostr-->
<PackageVersion Include="NNostr.Client" Version="0.0.49" />
<!-- JSON. -->
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.19" />
<!-- SQLite. -->
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.19" />
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="8.0.0" />
<!-- C# analysis. -->
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.6.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="System.Text.Json" Version="8.0.6" />
<!-- Version 4.3.0 contains a vulnerability, manually bumped to 4.3.2. -->
<!-- Core libraries. -->
<PackageVersion Include="WabiSabi" Version="1.0.1.2" />
<PackageVersion Include="NBitcoin" Version="7.0.42.2" />
<PackageVersion Include="NBitcoin" Version="9.0.0" />
<!-- Backend. -->
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<!-- UI. -->
Expand All @@ -56,10 +57,10 @@
<PackageVersion Include="Avalonia.Headless.XUnit" Version="$(AvaloniaVersion)" />
<!-- Testing. -->
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.19" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Moq" Version="[4.18.4]" />
<PackageVersion Include="xunit" Version="2.6.6" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
</ItemGroup>
</Project>
</Project>
1 change: 1 addition & 0 deletions GingerCommon/GingerCommon.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" />
<PackageReference Include="NBitcoin" />
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion GingerCommon/Logging/DiscordLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
{
try
{
var content = new { content = message };
var content = new { content = message, flags = 4 };
var json = JsonSerializer.Serialize(content);
using var data = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.PostAsync(_webhook, data);
Expand Down
63 changes: 40 additions & 23 deletions GingerCommon/Logging/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -52,23 +53,33 @@ public static void CreateLogger(LogLevel? consoleLogLevel = null, LogLevel? debu
LoggerInstance = logger;
}

public static void CreateDiscordLogger(LogLevel? logLevel, IHttpClientFactory httpClientFactory, string webhook)
public static void CreateDiscordLogger(LogLevel? logLevel, IHttpClientFactory httpClientFactory, string[]? webhooks)
{
if (logLevel == LogLevel.None || string.IsNullOrEmpty(webhook))
if (logLevel == LogLevel.None || webhooks is null || webhooks.Length == 0)
{
return;
}

logLevel ??= LogLevel.Error;

using ILoggerFactory factory = LoggerFactory.Create(builder =>
foreach (var webhookTarget in webhooks)
{
builder.ClearProviders();
builder.AddFilter<DiscordLoggerProvider>(null, (LogLevel)logLevel);
builder.AddProvider(new DiscordLoggerProvider(httpClientFactory, webhook));
});
ILogger logger = factory.CreateLogger("Discord");
DiscordLogger = logger;
var split = webhookTarget.Split("|");
var name = split.Length > 1 ? split[0] : "main";
var webhook = split.Length > 1 ? split[1] : webhookTarget;

if (!DiscordLoggers.ContainsKey(name))
{
using ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.ClearProviders();
builder.AddFilter<DiscordLoggerProvider>(null, (LogLevel)logLevel);
builder.AddProvider(new DiscordLoggerProvider(httpClientFactory, webhook));
});
ILogger logger = factory.CreateLogger(name);
DiscordLoggers.Add(name, logger);
}
}
}

public static void FinishFileLogging()
Expand All @@ -83,7 +94,7 @@ public static void FinishFileLogging()
private static ILogger? LoggerInstance = null;
private static string[]? LogLevelStrings = null;

private static ILogger? DiscordLogger = null;
private static Dictionary<string, ILogger> DiscordLoggers = [];

private static void InitLevelStrings()
{
Expand Down Expand Up @@ -117,9 +128,12 @@ public void Dispose()
}
}

public static void LogDiscord(LogLevel level, string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1, LogLevel normalLogLevel = LogLevel.None)
public static void LogDiscord(string channel, LogLevel level, string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1, LogLevel normalLogLevel = LogLevel.None, bool rawMessage = false)
{
Log(DiscordLogger, level, message, callerFilePath, callerMemberName, callerLineNumber);
if (DiscordLoggers.TryGetValue(channel, out var discordLogger))
{
Log(discordLogger, level, message, callerFilePath, callerMemberName, callerLineNumber, rawMessage);
}
if (normalLogLevel != LogLevel.None)
{
Log(LoggerInstance, normalLogLevel, message, callerFilePath, callerMemberName, callerLineNumber);
Expand All @@ -132,7 +146,7 @@ public static void Log(LogLevel level, string message, [CallerFilePath] string c
Log(LoggerInstance, level, message, callerFilePath, callerMemberName, callerLineNumber);
}

private static void Log(ILogger? loggerInstance, LogLevel level, string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
private static void Log(ILogger? loggerInstance, LogLevel level, string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1, bool rawMessage = false)
{
try
{
Expand All @@ -142,19 +156,22 @@ private static void Log(ILogger? loggerInstance, LogLevel level, string message,
}

message = message.SafeTrim();
var category = string.IsNullOrWhiteSpace(callerFilePath) ? "" : $"{callerFilePath.ExtractFileName()}.{callerMemberName} ({callerLineNumber})";
var finalMessage = message;

var messageBuilder = new StringBuilder();
messageBuilder.Append(CultureInfo.InvariantCulture, $"{DateTime.UtcNow.ToLocalTime():yyyy-MM-dd HH:mm:ss.fff} [{Environment.CurrentManagedThreadId,2}] {GetLevelString(level)} ");

messageBuilder.Append(category);
if (message.Length > 0 && category.Length > 0)
if (!rawMessage)
{
messageBuilder.Append('\t');
var messageBuilder = new StringBuilder();
messageBuilder.Append(CultureInfo.InvariantCulture, $"{DateTime.UtcNow.ToLocalTime():yyyy-MM-dd HH:mm:ss.fff} [{Environment.CurrentManagedThreadId,2}] {GetLevelString(level)} ");

var category = string.IsNullOrWhiteSpace(callerFilePath) ? "" : $"{callerFilePath.ExtractFileName()}.{callerMemberName} ({callerLineNumber})";
messageBuilder.Append(category);
if (message.Length > 0 && category.Length > 0)
{
messageBuilder.Append('\t');
}
messageBuilder.Append(message);
finalMessage = messageBuilder.ToString();
}
messageBuilder.Append(message);

var finalMessage = messageBuilder.ToString();
loggerInstance.Log(level, finalMessage);
}
catch (Exception ex)
Expand Down
53 changes: 24 additions & 29 deletions GingerCommon/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
},
"Microsoft.Extensions.Http": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "cWz4caHwvx0emoYe7NkHPxII/KkTI8R/LC9qdqJqnKv2poTJ4e2qqPGQqvRoQ5kaSA4FU5IV3qFAuLuOhoqULQ==",
"requested": "[8.0.1, )",
"resolved": "8.0.1",
"contentHash": "kDYeKJUzh0qeg/AI+nSr3ffthmXYQTEb0nS9qRC7YhSbbuN4M4NPbaB77AJwtkTnCV9XZ7qYj3dkZaNcyl73EA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
"Microsoft.Extensions.Diagnostics": "8.0.0",
"Microsoft.Extensions.Logging": "8.0.0",
"Microsoft.Extensions.Logging.Abstractions": "8.0.0",
"Microsoft.Extensions.Options": "8.0.0"
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2",
"Microsoft.Extensions.Diagnostics": "8.0.1",
"Microsoft.Extensions.Logging": "8.0.1",
"Microsoft.Extensions.Logging.Abstractions": "8.0.2",
"Microsoft.Extensions.Options": "8.0.2"
}
},
"Microsoft.Extensions.Logging.Console": {
Expand Down Expand Up @@ -48,14 +48,20 @@
},
"NBitcoin": {
"type": "Direct",
"requested": "[7.0.42.2, )",
"resolved": "7.0.42.2",
"contentHash": "U9kvuVxKJ/xZs0ttF0ddVbkTLMZogWejYLYysuNz1n0MfjxR3diOnN2lE9pulgVclIieRRMOgZmIDB2MASIqxA==",
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "29o3gYqYehyelNs54jbvcGfOvmyx9Gr1SEN/WDqky54qpxB2U+SCs0k4ppihr5h5Sbf+NwyrHrrjiYqmIoMycQ==",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "1.0.0",
"Newtonsoft.Json": "13.0.1"
}
},
"Newtonsoft.Json": {
"type": "Direct",
"requested": "[13.0.3, )",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "8.0.0",
Expand Down Expand Up @@ -96,22 +102,21 @@
},
"Microsoft.Extensions.Diagnostics": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "3PZp/YSkIXrF7QK7PfC1bkyRYwqOHpWFad8Qx+4wkuumAeXo1NHaxpS9LboNA9OvNSAu+QOVlXbMyoY+pHSqcw==",
"resolved": "8.0.1",
"contentHash": "doVPCUUCY7c6LhBsEfiy3W1bvS7Mi6LkfQMS8nlC22jZWNxBv8VO8bdfeyvpYFst6Kxqk7HBC6lytmEoBssvSQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "8.0.0",
"Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0",
"Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1",
"Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0"
}
},
"Microsoft.Extensions.Diagnostics.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==",
"resolved": "8.0.1",
"contentHash": "elH2vmwNmsXuKmUeMQ4YW9ldXiF+gSGDgg1vORksob5POnpaI6caj1Hu8zaYbEuibhqCoWg0YRWDazBY3zjBfg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
"Microsoft.Extensions.Options": "8.0.0",
"System.Diagnostics.DiagnosticSource": "8.0.0"
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2",
"Microsoft.Extensions.Options": "8.0.2"
}
},
"Microsoft.Extensions.Logging": {
Expand Down Expand Up @@ -172,16 +177,6 @@
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
"System.Diagnostics.DiagnosticSource": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ=="
}
},
"net8.0/linux-arm64": {},
Expand Down
5 changes: 2 additions & 3 deletions WalletWasabi.Backend/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,8 @@ public Config(
[JsonProperty(PropertyName = "EnableNostrCoordinatorPublisher", DefaultValueHandling = DefaultValueHandling.Populate)]
public bool EnableNostrCoordinatorPublisher { get; internal set; }

[DefaultValue("")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string DiscordLoggerWebhook { get; internal set; } = "";
[JsonProperty]
public string[] DiscordLoggers { get; internal set; } = [];

public EndPoint GetBitcoinP2pEndPoint()
{
Expand Down
1 change: 1 addition & 0 deletions WalletWasabi.Backend/Controllers/BatchController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public async Task<IActionResult> GetSynchronizeAsync(

try
{
// We still provide it, but the client never should read it
response.AllFeeEstimate = await BlockchainController.GetAllFeeEstimateAsync(EstimateSmartFeeMode.Conservative, cancellationToken);
}
catch (Exception ex)
Expand Down
8 changes: 2 additions & 6 deletions WalletWasabi.Backend/Global.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,7 @@ public Global(string dataDir, IRPCClient rpcClient, Config config, IHttpClientFa

public void CreateDiscordLogger()
{
string discordWebhook = Config.DiscordLoggerWebhook;
if (!string.IsNullOrEmpty(discordWebhook))
{
Logger.CreateDiscordLogger(LogLevel.Information, HttpClientFactory, discordWebhook);
}
Logger.CreateDiscordLogger(LogLevel.Information, HttpClientFactory, Config.DiscordLoggers);
}

public string DataDir { get; }
Expand Down Expand Up @@ -160,7 +156,7 @@ public async Task InitializeAsync(CancellationToken cancel)

private void BlockNotifier_ExceptionThrown(object? sender, Exception e)
{
Logger.LogDiscord(LogLevel.Error, $"BlockNotifier had an exception: '{e.Message}'.", normalLogLevel: LogLevel.Error);
Logger.LogDiscord("main", LogLevel.Error, $"BlockNotifier had an exception: '{e.Message}'.", normalLogLevel: LogLevel.Error);
}

[MemberNotNull(nameof(WabiSabiCoordinator))]
Expand Down
2 changes: 1 addition & 1 deletion WalletWasabi.Backend/InitConfigStartupTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)
Global.CreateDiscordLogger();

Logger.LogSoftwareStarted("Ginger Backend");
Logger.LogDiscord(LogLevel.Information, "Ginger Backend started");
Logger.LogDiscord("main", LogLevel.Information, "Ginger Backend started");

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ private AllFeeEstimate ParseFeeEstimates(string json)
{
using var document = JsonDocument.Parse(json);
var root = document.RootElement;
var feeEstimates = new Dictionary<int, int>();
var feeEstimates = new Dictionary<int, FeeRate>();

// Blockstream.info returns a JSON object where each property name is the target confirmation block
// (e.g., "2", "3", "6", "12", etc.) and its value is the estimated fee rate.
foreach (var property in root.EnumerateObject())
{
if (int.TryParse(property.Name, out int target))
{
feeEstimates[target] = (int)Math.Ceiling(property.Value.GetDouble());
feeEstimates[target] = new FeeRate(property.Value.GetDecimal());
}
}

Expand Down
Loading
Loading