diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a75a444..4017a7f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -33,14 +33,21 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@07976c6290703d34c16d382cb36445f98bb43b1f # v3.2.0 + with: + log-accepted-android-sdk-licenses: false + + - name: Install .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.100 - - name: Install Android workload (macOS) + - name: Install Workloads (macOS) if: matrix.os == 'macos-latest' - run: sudo dotnet workload install maui-android + run: sudo dotnet workload restore - - name: Install Android workload (Windows/Linux) + - name: Install Workloads (Windows/Linux) if: matrix.os != 'macos-latest' - run: dotnet workload install maui-android + run: dotnet workload restore - name: Run batch build script if: matrix.os == 'windows-latest' diff --git a/global.json b/global.json new file mode 100644 index 0000000..40584df --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "9.0.100", + "rollForward": "latestMinor", + "allowPrerelease": false + } +} diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 337fb02..2988655 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -1,7 +1,7 @@ true - 4.12.0 + 5.0.0-alpha.1 diff --git a/src/SymbolCollector.Server/BatchFinalizer.cs b/src/SymbolCollector.Server/BatchFinalizer.cs index 7ed44e5..bf3c8fa 100644 --- a/src/SymbolCollector.Server/BatchFinalizer.cs +++ b/src/SymbolCollector.Server/BatchFinalizer.cs @@ -35,7 +35,6 @@ public Task CloseBatch( public class SymsorterBatchFinalizer : IBatchFinalizer { private readonly SymbolServiceOptions _options; - private readonly IMetricsPublisher _metrics; private readonly ILogger _logger; private readonly ISymbolGcsWriter _gcsWriter; private readonly BundleIdGenerator _bundleIdGenerator; @@ -43,7 +42,6 @@ public class SymsorterBatchFinalizer : IBatchFinalizer private readonly string _symsorterOutputPath; public SymsorterBatchFinalizer( - IMetricsPublisher metrics, IOptions options, ISymbolGcsWriter gcsWriter, BundleIdGenerator bundleIdGenerator, @@ -51,7 +49,6 @@ public SymsorterBatchFinalizer( ILogger logger) { _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); - _metrics = metrics; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _gcsWriter = gcsWriter ?? throw new ArgumentNullException(nameof(gcsWriter)); _bundleIdGenerator = bundleIdGenerator; @@ -89,7 +86,6 @@ traceHeader is not null ? _hub.StartTransaction("CloseBatch", "batch.close", traceHeader) : _hub.StartTransaction("CloseBatch", "batch.close"); - var handle = _metrics.BeginGcsBatchUpload(); _ = Task.Run(async () => { // get logger factory and create a logger for symsorter @@ -189,7 +185,6 @@ into fileGroup { _logger.LogError(e, "Failed attempting to delete symsorter directory."); } - handle.Dispose(); } }, gcsUploadCancellation) @@ -292,4 +287,4 @@ private bool SortSymbols(string batchLocation, SymbolUploadBatch batch, string s _logger.LogInformation("Symsorter processed: {count}", match.Groups["count"].Value); return false; } -} \ No newline at end of file +} diff --git a/src/SymbolCollector.Server/ProxyMetricsPublisher.cs b/src/SymbolCollector.Server/ProxyMetricsPublisher.cs deleted file mode 100644 index 7f47f33..0000000 --- a/src/SymbolCollector.Server/ProxyMetricsPublisher.cs +++ /dev/null @@ -1,92 +0,0 @@ -namespace SymbolCollector.Server; - -public class ProxyMetricsPublisher( - // going through property to observe a change in the instance on the client. - // ReSharper disable once SuggestBaseTypeForParameterInConstructor - StatsDMetricsPublisher metricsPublisherImplementation, - // ReSharper disable once SuggestBaseTypeForParameterInConstructor - SentryMetricsPublisher metricsPublisherImplementation2) - : IMetricsPublisher -{ - public IDisposable BeginOpenBatch() - { - return new DisposableProxy(metricsPublisherImplementation.BeginOpenBatch(), - metricsPublisherImplementation2.BeginOpenBatch()); - } - - public IDisposable BeginCloseBatch() - { - return new DisposableProxy(metricsPublisherImplementation.BeginCloseBatch(), - metricsPublisherImplementation2.BeginCloseBatch()); - } - - public IDisposable BeginSymbolMissingCheck() - { - return new DisposableProxy(metricsPublisherImplementation.BeginSymbolMissingCheck(), - metricsPublisherImplementation2.BeginSymbolMissingCheck()); - } - - public IDisposable BeginUploadSymbol() - { - return new DisposableProxy(metricsPublisherImplementation.BeginUploadSymbol(), - metricsPublisherImplementation2.BeginUploadSymbol()); - } - - public void SymbolCheckExists() - { - metricsPublisherImplementation.SymbolCheckExists(); - metricsPublisherImplementation2.SymbolCheckExists(); - } - - public void SymbolCheckMissing() - { - metricsPublisherImplementation.SymbolCheckMissing(); - metricsPublisherImplementation2.SymbolCheckMissing(); - } - - public void FileStored(long size) - { - metricsPublisherImplementation.FileStored(size); - metricsPublisherImplementation2.FileStored(size); - } - - public void FileInvalid() - { - metricsPublisherImplementation.FileInvalid(); - metricsPublisherImplementation2.FileInvalid(); - } - - public void FileKnown() - { - metricsPublisherImplementation.FileKnown(); - metricsPublisherImplementation2.FileKnown(); - } - - public void DebugIdHashConflict() - { - metricsPublisherImplementation.DebugIdHashConflict(); - metricsPublisherImplementation2.DebugIdHashConflict(); - } - - public void SentryEventProcessed() - { - metricsPublisherImplementation.SentryEventProcessed(); - metricsPublisherImplementation2.SentryEventProcessed(); - } - - public IDisposable BeginGcsBatchUpload() - { - return new DisposableProxy(metricsPublisherImplementation.BeginGcsBatchUpload(), - metricsPublisherImplementation2.BeginGcsBatchUpload()); - } - - private class DisposableProxy(IDisposable disposableImplementation, IDisposable disposableImplementation2) - : IDisposable - { - public void Dispose() - { - disposableImplementation.Dispose(); - disposableImplementation2.Dispose(); - } - } -} diff --git a/src/SymbolCollector.Server/SentryMetricsPublisher.cs b/src/SymbolCollector.Server/SentryMetricsPublisher.cs deleted file mode 100644 index fbb57b9..0000000 --- a/src/SymbolCollector.Server/SentryMetricsPublisher.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Diagnostics; -using Sentry; - -namespace SymbolCollector.Server; - -public class SentryMetricsPublisher(IHub hub) : IMetricsPublisher -{ - private const string BatchOpenCurrentCount = "batch-current"; - - private class Timer(IMetricAggregator metricAggregator, string key, Action? onDispose = null) : IDisposable - { - private readonly Stopwatch _stopwatch = Stopwatch.StartNew(); - - public void Dispose() - { - _stopwatch.Stop(); - metricAggregator.Timing(key, _stopwatch.ElapsedMilliseconds, MeasurementUnit.Duration.Millisecond); - onDispose?.Invoke(); - } - } - public IDisposable BeginOpenBatch() - { - hub.Metrics.Gauge(BatchOpenCurrentCount); - return hub.Metrics.StartTimer(BatchOpenCurrentCount); - } - - public IDisposable BeginCloseBatch() - { - return new Timer(hub.Metrics,"batch-close", - () => hub.Metrics.Gauge(BatchOpenCurrentCount, -1)); - } - - public IDisposable BeginSymbolMissingCheck() - { - return new Timer(hub.Metrics,"symbol-check"); - } - - public IDisposable BeginUploadSymbol() - { - return new Timer(hub.Metrics,"symbol-upload"); - } - - public void SymbolCheckExists() - { - hub.Metrics.Increment("symbol-check-exists"); - } - - public void SymbolCheckMissing() - { - hub.Metrics.Increment("symbol-check-missing"); - } - - public void FileStored(long size) - { - hub.Metrics.Increment("file-stored-bytes", size, MeasurementUnit.Custom("bytes")); - } - - public void FileInvalid() - { - hub.Metrics.Increment("file-invalid"); - } - - public void FileKnown() - { - hub.Metrics.Increment("file-known"); - } - - public void DebugIdHashConflict() - { - hub.Metrics.Increment("debug-id-hash-conflict"); - } - - public void SentryEventProcessed() - { - hub.Metrics.Increment("sentry-event-processed"); - } - - public IDisposable BeginGcsBatchUpload() - { - return new Timer(hub.Metrics, "gcs-upload"); - } -} diff --git a/src/SymbolCollector.Server/Startup.cs b/src/SymbolCollector.Server/Startup.cs index 878ab0b..0c5ac8e 100644 --- a/src/SymbolCollector.Server/Startup.cs +++ b/src/SymbolCollector.Server/Startup.cs @@ -75,17 +75,6 @@ public void ConfigureServices(IServiceCollection services) .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton(c => new ProxyMetricsPublisher( - c.GetRequiredService(), - c.GetRequiredService())); - services.AddOptions() .Configure((o, c) => c.Bind("StatsD", o)) .Validate(o => !string.IsNullOrWhiteSpace(o.Host), "StatD host is required."); @@ -200,22 +189,18 @@ private string GetSymsorterPath() private class SymbolServiceEventProcessor : ISentryEventProcessor { private readonly IWebHostEnvironment _environment; - private readonly IMetricsPublisher _metrics; private readonly SymbolServiceOptions _options; private readonly string _cores = Environment.ProcessorCount.ToString(); public SymbolServiceEventProcessor( IWebHostEnvironment environment, - IMetricsPublisher metrics, IOptions options) { _environment = environment; - _metrics = metrics; _options = options.Value; } public SentryEvent? Process(SentryEvent @event) { - _metrics.SentryEventProcessed(); @event.SetTag("server-endpoint", _options.BaseAddress ?? "?"); @event.Contexts["SymbolServiceOptions"] = _options; diff --git a/src/SymbolCollector.Server/StatsDMetricsPublisher.cs b/src/SymbolCollector.Server/StatsDMetricsPublisher.cs deleted file mode 100644 index 20171ea..0000000 --- a/src/SymbolCollector.Server/StatsDMetricsPublisher.cs +++ /dev/null @@ -1,78 +0,0 @@ -using JustEat.StatsD; - -namespace SymbolCollector.Server; - -public class StatsDMetricsPublisher : IMetricsPublisher -{ - private readonly IStatsDPublisher _publisher; - private const string BatchOpenCurrentCount = "batch-current"; - - public StatsDMetricsPublisher(IStatsDPublisher publisher) => _publisher = publisher; - - public void DebugIdHashConflict() => _publisher.Increment("debug-id-hash-conflict"); - - public void SentryEventProcessed() => _publisher.Increment("sentry-event-processed"); - public IDisposable BeginGcsBatchUpload() => _publisher.StartTimer("gcs-upload"); - - public IDisposable BeginOpenBatch() - { - _publisher.Increment(BatchOpenCurrentCount); - return _publisher.StartTimer("batch-open"); - } - - public IDisposable BeginCloseBatch() - { - var timing = _publisher.StartTimer("batch-close"); - - return new DisposeCallback(() => - { - _publisher.Decrement(BatchOpenCurrentCount); - timing.Dispose(); - }); - } - - private class DisposeCallback : IDisposable - { - private readonly Action _onDispose; - public DisposeCallback(Action onDispose) => _onDispose = onDispose; - public void Dispose() => _onDispose?.Invoke(); - } - - public IDisposable BeginSymbolMissingCheck() => _publisher.StartTimer("symbol-check"); - - public void SymbolCheckExists() => _publisher.Increment("symbol-check-exists"); // TODO: Could be a tag to 'symbol-check' - - public void SymbolCheckMissing() => _publisher.Increment("symbol-check-missing"); // TODO: Could be a tag to 'symbol-check' - - public IDisposable BeginUploadSymbol() => _publisher.StartTimer("symbol-upload"); - - public void FileStored(long size) => _publisher.Increment(size, "file-stored-bytes"); - - public void FileInvalid() => _publisher.Increment("file-invalid"); - - public void FileKnown() => _publisher.Increment("file-known"); -} - -public interface ISymbolControllerMetrics -{ - IDisposable BeginOpenBatch(); - IDisposable BeginCloseBatch(); - IDisposable BeginSymbolMissingCheck(); - IDisposable BeginUploadSymbol(); - void SymbolCheckExists(); - void SymbolCheckMissing(); - void FileStored(long size); - void FileInvalid(); - void FileKnown(); -} - -public interface ISymbolServiceMetrics -{ - void DebugIdHashConflict(); -} - -public interface IMetricsPublisher : ISymbolControllerMetrics, ISymbolServiceMetrics -{ - public void SentryEventProcessed(); - IDisposable BeginGcsBatchUpload(); -} diff --git a/src/SymbolCollector.Server/SymbolService.cs b/src/SymbolCollector.Server/SymbolService.cs index 4d25ffe..5b16d32 100644 --- a/src/SymbolCollector.Server/SymbolService.cs +++ b/src/SymbolCollector.Server/SymbolService.cs @@ -73,7 +73,6 @@ public string BaseWorkingPath internal class InMemorySymbolService : ISymbolService, IDisposable { - private readonly ISymbolServiceMetrics _metrics; private readonly ObjectFileParser _parser; private readonly IBatchFinalizer _batchFinalizer; private readonly SymbolServiceOptions _options; @@ -87,13 +86,11 @@ internal class InMemorySymbolService : ISymbolService, IDisposable private readonly string _conflictPath; public InMemorySymbolService( - ISymbolServiceMetrics metrics, ObjectFileParser parser, IBatchFinalizer batchFinalizer, IOptions options, ILogger logger) { - _metrics = metrics; _parser = parser; _batchFinalizer = batchFinalizer; _options = options.Value; @@ -189,8 +186,6 @@ private async Task StoreIsolated( && symbol.Hash is { } && string.CompareOrdinal(fileResult.Hash, symbol.Hash) != 0) { - _metrics.DebugIdHashConflict(); - var conflictDestination = Path.Combine( _conflictPath, fileResult.UnifiedId); @@ -354,4 +349,4 @@ private async Task GetOpenBatch(Guid batchId, CancellationTok } public void Dispose() => (_batchFinalizer as IDisposable)?.Dispose(); -} \ No newline at end of file +} diff --git a/src/SymbolCollector.Server/SymbolsController.cs b/src/SymbolCollector.Server/SymbolsController.cs index a6541b8..2c8fece 100644 --- a/src/SymbolCollector.Server/SymbolsController.cs +++ b/src/SymbolCollector.Server/SymbolsController.cs @@ -18,7 +18,6 @@ public class SymbolsController : Controller private readonly long _fileSizeLimit; private readonly IHub _hub; private readonly ISymbolService _symbolService; - private readonly ISymbolControllerMetrics _metrics; private readonly ILogger _logger; private readonly char[] _invalidChars; @@ -28,12 +27,10 @@ public SymbolsController( IHub hub, IConfiguration config, ISymbolService symbolService, - ISymbolControllerMetrics metrics, ILogger logger) { _hub = hub; _symbolService = symbolService; - _metrics = metrics; _logger = logger; _fileSizeLimit = config.GetValue("FileSizeLimitBytes"); // Don't allow file names with paths encoded. @@ -53,7 +50,6 @@ public async Task Start( [FromBody] BatchStartRequestModel model, CancellationToken token) { - using var _ = _metrics.BeginOpenBatch(); if (!ModelState.IsValid) { return BadRequest(ModelState); @@ -79,7 +75,6 @@ public async Task Start( public async Task CloseBatch([FromRoute] Guid batchId, [FromBody] BatchEndRequestModel model, CancellationToken token) { - using var _ = _metrics.BeginCloseBatch(); await ValidateBatch(batchId, ModelState, token); if (!ModelState.IsValid) @@ -103,7 +98,6 @@ public async Task IsSymbolMissing( [FromRoute] string? hash, CancellationToken token) { - using var _ = _metrics.BeginSymbolMissingCheck(); await ValidateBatch(batchId, ModelState, token); if (!ModelState.IsValid) @@ -121,7 +115,6 @@ public async Task IsSymbolMissing( { _logger.LogDebug("{batchId} looked for {unifiedId} and {hash} which is a missing symbol.", batchId, unifiedId, hash); - _metrics.SymbolCheckMissing(); return Ok(); } @@ -149,7 +142,6 @@ public async Task IsSymbolMissing( await _symbolService.Relate(batchId, symbol, token); } - _metrics.SymbolCheckExists(); return Conflict(); } @@ -173,7 +165,6 @@ public async Task UploadSymbol( [FromRoute] Guid batchId, CancellationToken token) { - using var _ = _metrics.BeginUploadSymbol(); await ValidateBatch(batchId, ModelState, token); if (!ModelState.IsValid) @@ -231,22 +222,8 @@ public async Task UploadSymbol( data, token); - switch (fileStoreResult) - { - case StoreResult.Invalid: - _metrics.FileInvalid(); - break; - case StoreResult.Created: - _metrics.FileStored(data.Length); - break; - case StoreResult.AlreadyExisted: - _metrics.FileKnown(); - break; - } - results.Add((fileName, fileStoreResult)); - await data.DisposeAsync(); } else @@ -413,4 +390,4 @@ public static bool HasFileContentDisposition(ContentDispositionHeaderValue conte && (!string.IsNullOrEmpty(contentDisposition.FileName.Value) || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value)); } -} \ No newline at end of file +} diff --git a/test/SymbolCollector.Android.UITests/Tests.cs b/test/SymbolCollector.Android.UITests/Tests.cs index 010f678..aff373f 100644 --- a/test/SymbolCollector.Android.UITests/Tests.cs +++ b/test/SymbolCollector.Android.UITests/Tests.cs @@ -16,7 +16,7 @@ public void BeforeEachTest() { var setup = ConfigureApp.Android; // local testing - const string apkPath = "../../../../../src/SymbolCollector.Android/bin/Release/net8.0-android/io.sentry.symbolcollector.android-Signed.apk"; + const string apkPath = "../../../../../src/SymbolCollector.Android/bin/Release/net9.0-android/io.sentry.symbolcollector.android-Signed.apk"; if (File.Exists(apkPath)) { setup = setup.ApkFile(apkPath); @@ -94,4 +94,4 @@ public void Flush() CollectSymbolSuccess = null; } -} \ No newline at end of file +}