Implement telemetry system with data collection and reporting
Java CI / build (push) Successful in 56s
.NET+Docker CI/CD / Unit and Integration tests (push) Successful in 38s
.NET+Docker CI/CD / Push Docker image to ghcr.io (push) Failing after 44s

Signed-off-by: Dmitrii <computer@yawaflua.tech>

Took 20 minutes
This commit is contained in:
Dmitrii
2026-07-11 00:38:28 +03:00
parent f3a2a5d463
commit 0e53d7dd8c
33 changed files with 1245 additions and 41 deletions
@@ -20,6 +20,7 @@ namespace SpMega.Backend.Controllers.v1;
public record GetSessionIdBody(string userName, Guid userUUID);
public record ValidateSessionBody(string sessionId, Guid userUUID);
[Route("api/v1/auth")]
[ApiController]
public class AuthController(AppDbContext dbContext, TokenService tokenService, ILogger<AuthController> logger) : ControllerBase
@@ -67,7 +68,7 @@ public class AuthController(AppDbContext dbContext, TokenService tokenService, I
var resp = await httpClient.SendAsync(request);
if (resp.StatusCode != HttpStatusCode.OK) throw new Exception("Mojang response is not OK");
Console.WriteLine(await resp.Content.ReadAsStringAsync());
var dto = await resp.Content.ReadFromJsonAsync<MojangDto>();
if (dto == null || dto.Name != session.UserName || Guid.Parse(dto.Id) != session.UserId) throw new Exception("Session expired, or dto is not acceptable.");
var token = tokenService.GenerateAccessToken(session.UserName, body.userUUID);
@@ -75,6 +76,9 @@ public class AuthController(AppDbContext dbContext, TokenService tokenService, I
if (user != null)
{
user.Token = token;
user.Username = session.UserName;
user.UpdatedAt = DateTime.UtcNow;
dbContext.Update(user);
}
else
@@ -84,6 +88,7 @@ public class AuthController(AppDbContext dbContext, TokenService tokenService, I
Id = body.userUUID,
Username = session.UserName,
Token = token,
UpdatedAt = DateTime.UtcNow
};
await dbContext.AddAsync(user);
}
@@ -0,0 +1,45 @@
using System.Diagnostics;
using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SpMega.Backend.Persistent.Models.DTO;
using SpMega.Backend.Persistent.Models.Users;
namespace SpMega.Backend.Controllers.v1;
[ApiController]
[Route("api/v1/telemetry")]
public class TelemetryController : ControllerBase
{
private static readonly ActivitySource Source = new("SpMega.ModTelemetry");
[HttpPost]
[Authorize]
public IActionResult Post([FromBody] ModTelemetryBatchDto batch)
{
if (batch?.Events == null || batch.Events.Count == 0)
{
return Ok(new { received = 0 });
}
var user = HttpContext.Items["@me"] as User;
var userId = user?.Id.ToString() ?? User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "anonymous";
var sessionId = !string.IsNullOrEmpty(batch.SessionId) ? batch.SessionId : Guid.NewGuid().ToString("N");
foreach (var e in batch.Events)
{
using var activity = Source.StartActivity("mod.telemetry.event", ActivityKind.Internal);
if (activity is null) continue;
activity.SetTag("user.id", userId);
activity.SetTag("session.id", sessionId);
activity.SetTag("client.version", batch.ClientVersion ?? string.Empty);
activity.SetTag("event.type", e.EventType);
activity.SetTag("event.timestamp", e.Timestamp.ToString("O"));
activity.SetTag("event.payload", JsonSerializer.Serialize(e.Payload));
activity.SetTag("batch.sent_at", batch.SentAt.ToString("O"));
}
return Ok(new { received = batch.Events.Count });
}
}
@@ -0,0 +1,50 @@
using System.Diagnostics;
namespace SpMega.Backend.Middleware;
public class RequestTelemetryMiddleware(RequestDelegate next, ILogger<RequestTelemetryMiddleware> logger)
{
private static readonly ActivitySource Source = new("SpMega.RequestTelemetry");
private const string RequestIdHeader = "X-Request-Id";
public async Task InvokeAsync(HttpContext context)
{
var path = context.Request.Path.Value ?? string.Empty;
if (path.Equals("/api/v1/telemetry", StringComparison.OrdinalIgnoreCase)
&& context.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase))
{
await next(context);
return;
}
var requestId = context.Request.Headers[RequestIdHeader].FirstOrDefault() ?? Guid.NewGuid().ToString("N");
context.Response.Headers[RequestIdHeader] = requestId;
using var activity = Source.StartActivity("http.request", ActivityKind.Server);
activity?.SetTag("request.id", requestId);
activity?.SetTag("http.method", context.Request.Method);
activity?.SetTag("http.path", path);
activity?.SetTag("http.scheme", context.Request.Scheme);
activity?.SetTag("http.host", context.Request.Host.Value ?? string.Empty);
activity?.SetTag("client.ip", context.Connection.RemoteIpAddress?.ToString());
activity?.SetTag("http.user_agent", context.Request.Headers.UserAgent.ToString());
var stopwatch = Stopwatch.StartNew();
try
{
await next(context);
}
finally
{
stopwatch.Stop();
activity?.SetTag("http.status_code", context.Response.StatusCode);
activity?.SetTag("http.duration_ms", stopwatch.ElapsedMilliseconds);
var userId = context.User?.Identity?.IsAuthenticated == true
? context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value
: null;
if (userId is not null)
activity?.SetTag("user.id", userId);
}
}
}
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using MongoDB.EntityFrameworkCore.Extensions;
using SpMega.Backend.Persistent.Models.Telemetry;
using SpMega.Backend.Persistent.Models.Transactions;
using SpMega.Backend.Persistent.Models.Users;
using SpMega.Backend.Services;
@@ -11,6 +12,8 @@ public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(op
internal DbSet<Transaction> Transactions { get; set; }
internal DbSet<User> Users { get; set; }
internal DbSet<UserSession> UserSessions { get; set; }
internal DbSet<ModTelemetryDocument> ModTelemetry { get; set; }
internal DbSet<BackendRequestTelemetryDocument> BackendRequestTelemetry { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
@@ -0,0 +1,16 @@
using System.Text.Json;
namespace SpMega.Backend.Persistent.Models.DTO;
public record ModTelemetryEventDto(
string EventType,
DateTimeOffset Timestamp,
JsonElement Payload
);
public record ModTelemetryBatchDto(
string ClientVersion,
string SessionId,
DateTimeOffset SentAt,
List<ModTelemetryEventDto> Events
);
@@ -0,0 +1,19 @@
using MongoDB.Bson;
namespace SpMega.Backend.Persistent.Models.Telemetry;
public class BackendRequestTelemetryDocument
{
public ObjectId Id { get; set; }
public string RequestId { get; set; } = string.Empty;
public string Method { get; set; } = string.Empty;
public string Path { get; set; } = string.Empty;
public string Scheme { get; set; } = string.Empty;
public string Host { get; set; } = string.Empty;
public string? ClientIp { get; set; }
public string? UserAgent { get; set; }
public int StatusCode { get; set; }
public long DurationMs { get; set; }
public string? UserId { get; set; }
public DateTimeOffset Timestamp { get; set; } = DateTimeOffset.UtcNow;
}
@@ -0,0 +1,21 @@
using MongoDB.Bson;
namespace SpMega.Backend.Persistent.Models.Telemetry;
public class ModTelemetryDocument
{
public ObjectId Id { get; set; }
public string UserId { get; set; } = string.Empty;
public string SessionId { get; set; } = string.Empty;
public string ClientVersion { get; set; } = string.Empty;
public DateTimeOffset SentAt { get; set; }
public DateTimeOffset ReceivedAt { get; set; } = DateTimeOffset.UtcNow;
public List<ModTelemetryEventDocument> Events { get; set; } = [];
}
public class ModTelemetryEventDocument
{
public string EventType { get; set; } = string.Empty;
public DateTimeOffset Timestamp { get; set; }
public string PayloadJson { get; set; } = "{}";
}
+21 -3
View File
@@ -3,7 +3,10 @@ using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using MongoDB.Driver;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using SpMega.Backend.Authetication;
using SpMega.Backend.Middleware;
using SpMega.Backend.Persistent.Database;
using SpMega.Backend.Services;
@@ -56,18 +59,33 @@ public class Program
.RequireAuthenticatedUser()
.Build());
var serviceCollection = new ServiceCollection();
var mongoClient =
new MongoClient(builder.Configuration.GetValue<string>("Mongo") ?? "mongodb://curiosity:27018");
serviceCollection.AddSingleton<IMongoClient>(mongoClient);
builder.Services.AddSingleton<IMongoClient>(mongoClient);
builder.Services.AddDbContext<AppDbContext>((_, options) =>
{
options.UseMongoDB(mongoClient, "spmega");
});
var otlpEndpoint = conf["Otlp:Endpoint"] ?? "http://localhost:4317";
builder.Services.AddOpenTelemetry()
.ConfigureResource(res => res.AddService("SpMega.Backend"))
.WithTracing(tracing =>
{
tracing
.AddSource("SpMega.ModTelemetry")
.AddSource("SpMega.RequestTelemetry")
.AddAspNetCoreInstrumentation()
.AddOtlpExporter(opts =>
{
opts.Endpoint = new Uri(otlpEndpoint);
});
});
var app = builder.Build();
app.UseMiddleware<RequestTelemetryMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/api"), appBuilder =>
@@ -22,6 +22,9 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.9" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.19.1" />
<PackageReference Include="MongoDB.EntityFrameworkCore" Version="10.0.2" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
<PackageReference Include="spworlds-api" Version="1.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.19.1" />
</ItemGroup>
@@ -0,0 +1,317 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"SpMega.Backend/1.0.0": {
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "10.0.9",
"Microsoft.EntityFrameworkCore.Relational": "10.0.9",
"Microsoft.IdentityModel.Tokens": "8.19.1",
"MongoDB.EntityFrameworkCore": "10.0.2",
"System.IdentityModel.Tokens.Jwt": "8.19.1",
"spworlds-api": "1.0.3"
},
"runtime": {
"SpMega.Backend.dll": {}
}
},
"DnsClient/1.6.1": {
"runtime": {
"lib/net5.0/DnsClient.dll": {
"assemblyVersion": "1.6.1.0",
"fileVersion": "1.6.1.0"
}
}
},
"Microsoft.Bcl.Cryptography/10.0.2": {
"runtime": {
"lib/net10.0/Microsoft.Bcl.Cryptography.dll": {
"assemblyVersion": "10.0.0.2",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.EntityFrameworkCore/10.0.9": {
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "10.0.9"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.dll": {
"assemblyVersion": "10.0.9.0",
"fileVersion": "10.0.926.27113"
}
}
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.9": {
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Abstractions.dll": {
"assemblyVersion": "10.0.9.0",
"fileVersion": "10.0.926.27113"
}
}
},
"Microsoft.EntityFrameworkCore.Relational/10.0.9": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.9"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Relational.dll": {
"assemblyVersion": "10.0.9.0",
"fileVersion": "10.0.926.27113"
}
}
},
"Microsoft.IdentityModel.Abstractions/8.19.1": {
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "8.19.1.0",
"fileVersion": "8.19.1.26153"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/8.19.1": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "8.19.1"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "8.19.1.0",
"fileVersion": "8.19.1.26153"
}
}
},
"Microsoft.IdentityModel.Logging/8.19.1": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "8.19.1"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "8.19.1.0",
"fileVersion": "8.19.1.26153"
}
}
},
"Microsoft.IdentityModel.Tokens/8.19.1": {
"dependencies": {
"Microsoft.Bcl.Cryptography": "10.0.2",
"Microsoft.IdentityModel.Logging": "8.19.1"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "8.19.1.0",
"fileVersion": "8.19.1.26153"
}
}
},
"MongoDB.Bson/3.9.0": {
"runtime": {
"lib/net6.0/MongoDB.Bson.dll": {
"assemblyVersion": "3.9.0.0",
"fileVersion": "3.9.0.0"
}
}
},
"MongoDB.Driver/3.9.0": {
"dependencies": {
"DnsClient": "1.6.1",
"MongoDB.Bson": "3.9.0",
"SharpCompress": "0.48.1",
"Snappier": "1.3.1",
"ZstdSharp.Port": "0.7.3"
},
"runtime": {
"lib/net6.0/MongoDB.Driver.dll": {
"assemblyVersion": "3.9.0.0",
"fileVersion": "3.9.0.0"
}
}
},
"MongoDB.EntityFrameworkCore/10.0.2": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.9",
"MongoDB.Driver": "3.9.0"
},
"runtime": {
"lib/net10.0/MongoDB.EntityFrameworkCore.dll": {
"assemblyVersion": "10.0.2.0",
"fileVersion": "10.0.2.0"
}
}
},
"SharpCompress/0.48.1": {
"runtime": {
"lib/net10.0/SharpCompress.dll": {
"assemblyVersion": "0.48.1.0",
"fileVersion": "0.48.1.0"
}
}
},
"Snappier/1.3.1": {
"runtime": {
"lib/net8.0/Snappier.dll": {
"assemblyVersion": "1.3.1.0",
"fileVersion": "1.3.1.0"
}
}
},
"spworlds-api/1.0.3": {
"runtime": {
"lib/net8.0/spworlds-api.dll": {
"assemblyVersion": "1.0.3.0",
"fileVersion": "1.0.3.0"
}
}
},
"System.IdentityModel.Tokens.Jwt/8.19.1": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "8.19.1",
"Microsoft.IdentityModel.Tokens": "8.19.1"
},
"runtime": {
"lib/net10.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "8.19.1.0",
"fileVersion": "8.19.1.26153"
}
}
},
"ZstdSharp.Port/0.7.3": {
"runtime": {
"lib/net7.0/ZstdSharp.dll": {
"assemblyVersion": "0.7.3.0",
"fileVersion": "0.7.3.0"
}
}
}
}
},
"libraries": {
"SpMega.Backend/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"DnsClient/1.6.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-4H/f2uYJOZ+YObZjpY9ABrKZI+JNw3uizp6oMzTXwDw6F+2qIPhpRl/1t68O/6e98+vqNiYGu+lswmwdYUy3gg==",
"path": "dnsclient/1.6.1",
"hashPath": "dnsclient.1.6.1.nupkg.sha512"
},
"Microsoft.Bcl.Cryptography/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LG9Yll3B5aNpxv0+D47g6LiOiKBIlodhcHdQwcYzo8VeexFLGqx5ymetmA2aBRyo9cCcWsQWrFsdbsr8LvmWDw==",
"path": "microsoft.bcl.cryptography/10.0.2",
"hashPath": "microsoft.bcl.cryptography.10.0.2.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore/10.0.9": {
"type": "package",
"serviceable": true,
"sha512": "sha512-tu85SRzOT021V7EQlViCiAE7TqldVn469Y6lt5TEn/+XC4/MeNCHgMRSxqYuWqvF4zAQZUhCmtNEZuM3ss4LeA==",
"path": "microsoft.entityframeworkcore/10.0.9",
"hashPath": "microsoft.entityframeworkcore.10.0.9.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.9": {
"type": "package",
"serviceable": true,
"sha512": "sha512-GRMaiPkqYna/gCsyDffYDWmefGPC3hDrdMw+2rrGcQwhs6uZOsaMQXMJnoXQ35tx9SkBV2ieRRU9N/jLOO6BZw==",
"path": "microsoft.entityframeworkcore.abstractions/10.0.9",
"hashPath": "microsoft.entityframeworkcore.abstractions.10.0.9.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Relational/10.0.9": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dEoyYKgiaZHHgOFm1WMWm1sFEsEuhPWufX4L9PekKtqd/RaIcPjkCjvbrVvJtApErb5wPSJhYvnTlxhH+p9h2g==",
"path": "microsoft.entityframeworkcore.relational/10.0.9",
"hashPath": "microsoft.entityframeworkcore.relational.10.0.9.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/8.19.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-gFA8THIk23uNF/vMdOHnjIdXD1LyA2g12cHzMJ+Xag6WpgWLw6E/6uCXxvA0gp9d2yAvkRt3xzFzMUiO/hofnQ==",
"path": "microsoft.identitymodel.abstractions/8.19.1",
"hashPath": "microsoft.identitymodel.abstractions.8.19.1.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/8.19.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6eeY+y2QFyjj3XnCz/8gJdoP5smYHTS9ow1bw2nsZzDIPjPhBZlackYTIduSMipVpxnoT/B62LkrXX2jPggOXg==",
"path": "microsoft.identitymodel.jsonwebtokens/8.19.1",
"hashPath": "microsoft.identitymodel.jsonwebtokens.8.19.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/8.19.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-H+sMrMpdbWnwkQnpb/ESkQovtOgdefmj0ecGCcP40mDKzE5i4dUYkH6599M9mWYFNGNJnTp92l/9wLubYXWimw==",
"path": "microsoft.identitymodel.logging/8.19.1",
"hashPath": "microsoft.identitymodel.logging.8.19.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/8.19.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-KDiuSLXud2AFVNAOottd8ztVysfPeHyr4r8gofU3/VKUXlI7oytzGTnPsNJ/B3nui17rgz8wAdWNJOtzPjkUxw==",
"path": "microsoft.identitymodel.tokens/8.19.1",
"hashPath": "microsoft.identitymodel.tokens.8.19.1.nupkg.sha512"
},
"MongoDB.Bson/3.9.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-J6vB61zKwMSfxbkN+/amGvj1qVMDKrKjV3kmoOWttMcv8JJScLDCFh89FyL3f2lDUyJrnfgZCR6/KX+07e99eg==",
"path": "mongodb.bson/3.9.0",
"hashPath": "mongodb.bson.3.9.0.nupkg.sha512"
},
"MongoDB.Driver/3.9.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-XKUa+y5RtNH1iInfxj3Y7c1FN1BQ16/7hFxoqU6fzc3+BKM1D3mGa+pB/yBbAk8jNxf7+JWEnCfuQOyCo7dQLg==",
"path": "mongodb.driver/3.9.0",
"hashPath": "mongodb.driver.3.9.0.nupkg.sha512"
},
"MongoDB.EntityFrameworkCore/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-GBN9+OAoIyBEgVPlYTXW3tyIsnpGPCA5AWZPy+X7ca3zJu+2Lli9FODZWl//w0yZHqwGwsLUL6XhcPPEaBYvBQ==",
"path": "mongodb.entityframeworkcore/10.0.2",
"hashPath": "mongodb.entityframeworkcore.10.0.2.nupkg.sha512"
},
"SharpCompress/0.48.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SqGaVniGG943Gph/gHhUQUiZPyC7y0tXZyMf0/B2oGsMav9dqs7JJOuUA+xOkwKYaWM2TM7aZQjNK91f4bX71A==",
"path": "sharpcompress/0.48.1",
"hashPath": "sharpcompress.0.48.1.nupkg.sha512"
},
"Snappier/1.3.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DOdDQiO8YZ5rBtVLY+6CmR1yp9WYoJRgEEktPBrR0tEj9QO2djA/zv0O3DX0OZpEAfosbY8pytQ9tQUogwQsEA==",
"path": "snappier/1.3.1",
"hashPath": "snappier.1.3.1.nupkg.sha512"
},
"spworlds-api/1.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rLQsC3MiXBfPKf3v45Qcrj0yypfZktTPuT/eGUJpcAlSZix1FBSRUbQVtfXbA8BHGIqn7nhZMVetaP3dmk+n1g==",
"path": "spworlds-api/1.0.3",
"hashPath": "spworlds-api.1.0.3.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/8.19.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-2VHcRtT95GAcW1E3aVBLvL2rAAMxKHXKMXKXFyWzwgkdFXZPMMvP8tVOfnRydL4vTr1RirNuGC6T8VSEF2YsPQ==",
"path": "system.identitymodel.tokens.jwt/8.19.1",
"hashPath": "system.identitymodel.tokens.jwt.8.19.1.nupkg.sha512"
},
"ZstdSharp.Port/0.7.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U9Ix4l4cl58Kzz1rJzj5hoVTjmbx1qGMwzAcbv1j/d3NzrFaESIurQyg+ow4mivCgkE3S413y+U9k4WdnEIkRA==",
"path": "zstdsharp.port/0.7.3",
"hashPath": "zstdsharp.port.0.7.3.nupkg.sha512"
}
}
}
@@ -0,0 +1,20 @@
{
"runtimeOptions": {
"tfm": "net10.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "10.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "10.0.0"
}
],
"configProperties": {
"System.GC.Server": true,
"System.Reflection.NullabilityInfoContext.IsSupported": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}
@@ -0,0 +1,5 @@
{
"Version": 1,
"ManifestType": "Build",
"Endpoints": []
}
+3
View File
@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APaymentWrapper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F28d7b99649ed43d899c3d8518f41c1976400_003F94_003Fbc0e580e_003FPaymentWrapper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASPWorlds_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F28d7b99649ed43d899c3d8518f41c1976400_003F64_003Fd3041423_003FSPWorlds_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>