diff --git a/ErsatzTV.Application/ErsatzTV.Application.csproj b/ErsatzTV.Application/ErsatzTV.Application.csproj index ff363d636..60d0189f6 100644 --- a/ErsatzTV.Application/ErsatzTV.Application.csproj +++ b/ErsatzTV.Application/ErsatzTV.Application.csproj @@ -7,6 +7,7 @@ + diff --git a/ErsatzTV.Application/Streaming/HlsSessionWorker.cs b/ErsatzTV.Application/Streaming/HlsSessionWorker.cs index a2f7b97c1..e9170eafd 100644 --- a/ErsatzTV.Application/Streaming/HlsSessionWorker.cs +++ b/ErsatzTV.Application/Streaming/HlsSessionWorker.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Timers; +using Bugsnag; using ErsatzTV.Application.Channels; using ErsatzTV.Core; using ErsatzTV.Core.Domain; @@ -122,6 +123,8 @@ public class HlsSessionWorker : IHlsSessionWorker bool realtime, CancellationToken cancellationToken) { + using IServiceScope scope = _serviceScopeFactory.CreateScope(); + try { if (!realtime) @@ -136,7 +139,6 @@ public class HlsSessionWorker : IHlsSessionWorker channelNumber); } - using IServiceScope scope = _serviceScopeFactory.CreateScope(); IMediator mediator = scope.ServiceProvider.GetRequiredService(); long ptsOffset = await GetPtsOffset(mediator, channelNumber, cancellationToken); @@ -200,6 +202,17 @@ public class HlsSessionWorker : IHlsSessionWorker catch (Exception ex) { _logger.LogError(ex, "Error transcoding channel {Channel}", channelNumber); + + try + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + catch (Exception) + { + // do nothing + } + return false; } finally diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj index d6993f80f..b722d3de4 100644 --- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj +++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj @@ -7,6 +7,7 @@ + diff --git a/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs b/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs index 92128e8e9..ad0bd863e 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using System.Security.Cryptography; using System.Text; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.FFmpeg; @@ -248,6 +249,7 @@ public class TranscodingTests new FakeStreamSelector(), imageCache.Object, new Mock().Object, + new Mock().Object, LoggerFactory.CreateLogger()); var service = new FFmpegLibraryProcessService( @@ -276,6 +278,7 @@ public class TranscodingTests var localStatisticsProvider = new LocalStatisticsProvider( metadataRepository.Object, new LocalFileSystem(LoggerFactory.CreateLogger()), + new Mock().Object, LoggerFactory.CreateLogger()); await localStatisticsProvider.RefreshStatistics( diff --git a/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs b/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs index ffbe73de7..b30e2106c 100644 --- a/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs +++ b/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs @@ -1,6 +1,8 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.Metadata; using FluentAssertions; +using Moq; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Metadata; @@ -9,7 +11,7 @@ namespace ErsatzTV.Core.Tests.Metadata; public class FallbackMetadataProviderTests { [SetUp] - public void SetUp() => _fallbackMetadataProvider = new FallbackMetadataProvider(); + public void SetUp() => _fallbackMetadataProvider = new FallbackMetadataProvider(new Mock().Object); private FallbackMetadataProvider _fallbackMetadataProvider; diff --git a/ErsatzTV.Core.Tests/Metadata/LocalStatisticsProviderTests.cs b/ErsatzTV.Core.Tests/Metadata/LocalStatisticsProviderTests.cs index 5c24cd547..c416c7d0e 100644 --- a/ErsatzTV.Core.Tests/Metadata/LocalStatisticsProviderTests.cs +++ b/ErsatzTV.Core.Tests/Metadata/LocalStatisticsProviderTests.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Metadata; @@ -20,6 +21,7 @@ public class LocalStatisticsProviderTests var provider = new LocalStatisticsProvider( new Mock().Object, new Mock().Object, + new Mock().Object, new Mock>().Object); var input = new LocalStatisticsProvider.FFprobe( diff --git a/ErsatzTV.Core.Tests/Metadata/MovieFolderScannerTests.cs b/ErsatzTV.Core.Tests/Metadata/MovieFolderScannerTests.cs index 6ab74a585..5b5bac7d1 100644 --- a/ErsatzTV.Core.Tests/Metadata/MovieFolderScannerTests.cs +++ b/ErsatzTV.Core.Tests/Metadata/MovieFolderScannerTests.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Images; @@ -587,6 +588,7 @@ public class MovieFolderScannerTests new Mock().Object, null, new Mock().Object, + new Mock().Object, new Mock>().Object ); @@ -605,6 +607,7 @@ public class MovieFolderScannerTests new Mock().Object, null, new Mock().Object, + new Mock().Object, new Mock>().Object ); } diff --git a/ErsatzTV.Core/ErsatzTV.Core.csproj b/ErsatzTV.Core/ErsatzTV.Core.csproj index caa720d1d..6d4aeded0 100644 --- a/ErsatzTV.Core/ErsatzTV.Core.csproj +++ b/ErsatzTV.Core/ErsatzTV.Core.csproj @@ -7,6 +7,7 @@ + diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs index 77b95f0c6..6a369dfc5 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Interfaces.FFmpeg; @@ -13,6 +14,7 @@ public class FFmpegProcessService : IFFmpegProcessService private readonly IFFmpegStreamSelector _ffmpegStreamSelector; private readonly IImageCache _imageCache; private readonly ITempFilePool _tempFilePool; + private readonly IClient _client; private readonly ILogger _logger; private readonly FFmpegPlaybackSettingsCalculator _playbackSettingsCalculator; @@ -21,12 +23,14 @@ public class FFmpegProcessService : IFFmpegProcessService IFFmpegStreamSelector ffmpegStreamSelector, IImageCache imageCache, ITempFilePool tempFilePool, + IClient client, ILogger logger) { _playbackSettingsCalculator = ffmpegPlaybackSettingsService; _ffmpegStreamSelector = ffmpegStreamSelector; _imageCache = imageCache; _tempFilePool = tempFilePool; + _client = client; _logger = logger; } @@ -408,6 +412,7 @@ public class FFmpegProcessService : IFFmpegProcessService catch (Exception ex) { _logger.LogWarning(ex, "Error generating song image"); + _client.Notify(ex); return Left(BaseError.New(ex.Message)); } } diff --git a/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs b/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs index 1bde3746c..98b2cb8bb 100644 --- a/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs +++ b/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs @@ -1,4 +1,5 @@ using System.Text.RegularExpressions; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Metadata; @@ -6,6 +7,13 @@ namespace ErsatzTV.Core.Metadata; public class FallbackMetadataProvider : IFallbackMetadataProvider { + private readonly IClient _client; + + public FallbackMetadataProvider(IClient client) + { + _client = client; + } + public ShowMetadata GetFallbackMetadataForShow(string showFolder) { string fileName = Path.GetFileName(showFolder); @@ -142,7 +150,7 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider return title; } - private static List GetEpisodeMetadata(string fileName, EpisodeMetadata baseMetadata) + private List GetEpisodeMetadata(string fileName, EpisodeMetadata baseMetadata) { var result = new List(); @@ -186,9 +194,9 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider return result; } } - catch (Exception) + catch (Exception ex) { - // ignored + _client.Notify(ex); } return result; @@ -208,9 +216,9 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider metadata.DateUpdated = DateTime.UtcNow; } } - catch (Exception) + catch (Exception ex) { - // ignored + _client.Notify(ex); } return metadata; @@ -232,8 +240,9 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider return metadata; } - catch (Exception) + catch (Exception ex) { + _client.Notify(ex); return None; } } @@ -269,8 +278,9 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider return metadata; } - catch (Exception) + catch (Exception ex) { + _client.Notify(ex); return None; } } @@ -306,8 +316,9 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider return metadata; } - catch (Exception) + catch (Exception ex) { + _client.Notify(ex); return None; } } @@ -326,9 +337,9 @@ public class FallbackMetadataProvider : IFallbackMetadataProvider metadata.DateUpdated = DateTime.UtcNow; } } - catch (Exception) + catch (Exception ex) { - // ignored + _client.Notify(ex); } return metadata; diff --git a/ErsatzTV.Core/Metadata/LocalFolderScanner.cs b/ErsatzTV.Core/Metadata/LocalFolderScanner.cs index ccd9c1cd4..a7daef2b0 100644 --- a/ErsatzTV.Core/Metadata/LocalFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/LocalFolderScanner.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Extensions; using ErsatzTV.Core.FFmpeg; @@ -46,6 +47,7 @@ public abstract class LocalFolderScanner private readonly IImageCache _imageCache; private readonly IFFmpegProcessServiceFactory _ffmpegProcessServiceFactory; private readonly ITempFilePool _tempFilePool; + private readonly IClient _client; private readonly ILocalFileSystem _localFileSystem; private readonly ILocalStatisticsProvider _localStatisticsProvider; @@ -61,6 +63,7 @@ public abstract class LocalFolderScanner IImageCache imageCache, IFFmpegProcessServiceFactory ffmpegProcessServiceFactory, ITempFilePool tempFilePool, + IClient client, ILogger logger) { _localFileSystem = localFileSystem; @@ -70,6 +73,7 @@ public abstract class LocalFolderScanner _imageCache = imageCache; _ffmpegProcessServiceFactory = ffmpegProcessServiceFactory; _tempFilePool = tempFilePool; + _client = client; _logger = logger; } @@ -109,6 +113,7 @@ public abstract class LocalFolderScanner } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.Message); } } @@ -258,6 +263,7 @@ public abstract class LocalFolderScanner catch (Exception ex) { _logger.LogWarning(ex, "Error refreshing artwork"); + _client.Notify(ex); } } @@ -283,6 +289,7 @@ public abstract class LocalFolderScanner } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } diff --git a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs index 2b46a3161..d2d3f2172 100644 --- a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs +++ b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs @@ -1,4 +1,5 @@ using System.Xml.Serialization; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Extensions; using ErsatzTV.Core.Interfaces.Metadata; @@ -18,6 +19,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider private readonly IArtistRepository _artistRepository; private readonly IEpisodeNfoReader _episodeNfoReader; private readonly ILocalStatisticsProvider _localStatisticsProvider; + private readonly IClient _client; private readonly IFallbackMetadataProvider _fallbackMetadataProvider; private readonly ILocalFileSystem _localFileSystem; private readonly ILogger _logger; @@ -41,6 +43,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider ILocalFileSystem localFileSystem, IEpisodeNfoReader episodeNfoReader, ILocalStatisticsProvider localStatisticsProvider, + IClient client, ILogger logger) { _metadataRepository = metadataRepository; @@ -54,6 +57,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider _localFileSystem = localFileSystem; _episodeNfoReader = episodeNfoReader; _localStatisticsProvider = localStatisticsProvider; + _client = client; _logger = logger; } @@ -189,6 +193,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider catch (Exception ex) { _logger.LogInformation(ex, "Failed to read music video nfo metadata from {Path}", nfoFileName); + _client.Notify(ex); return None; } } @@ -274,6 +279,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider catch (Exception ex) { _logger.LogInformation(ex, "Failed to read embedded song metadata from {Path}", path); + _client.Notify(ex); return None; } } @@ -839,6 +845,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider catch (Exception ex) { _logger.LogInformation(ex, "Failed to read TV show nfo metadata from {Path}", nfoFileName); + _client.Notify(ex); return None; } } @@ -867,6 +874,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider catch (Exception ex) { _logger.LogInformation(ex, "Failed to read artist nfo metadata from {Path}", nfoFileName); + _client.Notify(ex); return None; } } @@ -914,6 +922,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider catch (Exception ex) { _logger.LogInformation(ex, "Failed to read TV episode nfo metadata from {Path}", nfoFileName); + _client.Notify(ex); return _fallbackMetadataProvider.GetFallbackMetadata(episode); } } @@ -958,6 +967,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider catch (Exception ex) { _logger.LogInformation(ex, "Failed to read Movie nfo metadata from {Path}", nfoFileName); + _client.Notify(ex); return _fallbackMetadataProvider.GetFallbackMetadata(movie); } } diff --git a/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs b/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs index 9ca3e0f55..365e2c1a6 100644 --- a/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs +++ b/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using System.Globalization; using System.Text; +using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Extensions; using ErsatzTV.Core.Interfaces.Metadata; @@ -13,16 +14,19 @@ namespace ErsatzTV.Core.Metadata; public class LocalStatisticsProvider : ILocalStatisticsProvider { private readonly ILocalFileSystem _localFileSystem; + private readonly IClient _client; private readonly ILogger _logger; private readonly IMetadataRepository _metadataRepository; public LocalStatisticsProvider( IMetadataRepository metadataRepository, ILocalFileSystem localFileSystem, + IClient client, ILogger logger) { _metadataRepository = metadataRepository; _localFileSystem = localFileSystem; + _client = client; _logger = logger; } @@ -36,6 +40,7 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider catch (Exception ex) { _logger.LogWarning(ex, "Failed to refresh statistics for media item {Id}", mediaItem.Id); + _client.Notify(ex); return BaseError.New(ex.Message); } } @@ -60,6 +65,7 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider catch (Exception ex) { _logger.LogWarning(ex, "Failed to refresh statistics for media item {Id}", mediaItem.Id); + _client.Notify(ex); return BaseError.New(ex.Message); } } @@ -114,6 +120,7 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider catch (Exception ex) { _logger.LogWarning(ex, "Failed to get format tags for media item {Id}", mediaItem.Id); + _client.Notify(ex); return BaseError.New(ex.Message); } } diff --git a/ErsatzTV.Core/Metadata/MovieFolderScanner.cs b/ErsatzTV.Core/Metadata/MovieFolderScanner.cs index cb76638bf..22a02e681 100644 --- a/ErsatzTV.Core/Metadata/MovieFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/MovieFolderScanner.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Images; @@ -18,6 +19,7 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILogger _logger; private readonly IMediator _mediator; + private readonly IClient _client; private readonly IMovieRepository _movieRepository; private readonly ISearchIndex _searchIndex; private readonly ISearchRepository _searchRepository; @@ -36,6 +38,7 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner IMediator mediator, IFFmpegProcessServiceFactory ffmpegProcessServiceFactory, ITempFilePool tempFilePool, + IClient client, ILogger logger) : base( localFileSystem, @@ -45,6 +48,7 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner imageCache, ffmpegProcessServiceFactory, tempFilePool, + client, logger) { _localFileSystem = localFileSystem; @@ -54,6 +58,7 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner _searchRepository = searchRepository; _libraryRepository = libraryRepository; _mediator = mediator; + _client = client; _logger = logger; } @@ -216,6 +221,7 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } @@ -238,6 +244,7 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } diff --git a/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs b/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs index e7c87ba12..bfc50b90e 100644 --- a/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Images; @@ -18,6 +19,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILogger _logger; private readonly IMediator _mediator; + private readonly IClient _client; private readonly IMusicVideoRepository _musicVideoRepository; private readonly ISearchIndex _searchIndex; private readonly ISearchRepository _searchRepository; @@ -37,6 +39,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan IMediator mediator, IFFmpegProcessServiceFactory ffmpegProcessServiceFactory, ITempFilePool tempFilePool, + IClient client, ILogger logger) : base( localFileSystem, localStatisticsProvider, @@ -45,6 +48,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan imageCache, ffmpegProcessServiceFactory, tempFilePool, + client, logger) { _localFileSystem = localFileSystem; @@ -55,6 +59,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan _musicVideoRepository = musicVideoRepository; _libraryRepository = libraryRepository; _mediator = mediator; + _client = client; _logger = logger; } @@ -197,6 +202,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } @@ -220,6 +226,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } @@ -335,6 +342,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } @@ -384,6 +392,7 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } diff --git a/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs b/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs index 99be8eb19..a63a55b89 100644 --- a/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Images; @@ -19,6 +20,7 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan private readonly ISearchRepository _searchRepository; private readonly IOtherVideoRepository _otherVideoRepository; private readonly ILibraryRepository _libraryRepository; + private readonly IClient _client; private readonly ILogger _logger; public OtherVideoFolderScanner( @@ -35,6 +37,7 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan IMediaItemRepository mediaItemRepository, IFFmpegProcessServiceFactory ffmpegProcessServiceFactory, ITempFilePool tempFilePool, + IClient client, ILogger logger) : base( localFileSystem, localStatisticsProvider, @@ -43,6 +46,7 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan imageCache, ffmpegProcessServiceFactory, tempFilePool, + client, logger) { _localFileSystem = localFileSystem; @@ -52,6 +56,7 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan _searchRepository = searchRepository; _otherVideoRepository = otherVideoRepository; _libraryRepository = libraryRepository; + _client = client; _logger = logger; } @@ -191,6 +196,7 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } diff --git a/ErsatzTV.Core/Metadata/SongFolderScanner.cs b/ErsatzTV.Core/Metadata/SongFolderScanner.cs index b616ea713..519bd8d6b 100644 --- a/ErsatzTV.Core/Metadata/SongFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/SongFolderScanner.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.Extensions; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; @@ -20,6 +21,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner private readonly ISearchRepository _searchRepository; private readonly ISongRepository _songRepository; private readonly ILibraryRepository _libraryRepository; + private readonly IClient _client; private readonly ILogger _logger; public SongFolderScanner( @@ -36,6 +38,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner IMediaItemRepository mediaItemRepository, IFFmpegProcessServiceFactory ffmpegProcessServiceFactory, ITempFilePool tempFilePool, + IClient client, ILogger logger) : base( localFileSystem, localStatisticsProvider, @@ -44,6 +47,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner imageCache, ffmpegProcessServiceFactory, tempFilePool, + client, logger) { _localFileSystem = localFileSystem; @@ -53,6 +57,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner _searchRepository = searchRepository; _songRepository = songRepository; _libraryRepository = libraryRepository; + _client = client; _logger = logger; } @@ -200,6 +205,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } @@ -236,6 +242,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner } catch (Exception ex) { + _client.Notify(ex); return BaseError.New(ex.ToString()); } } diff --git a/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs b/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs index 8d1464b36..a36408670 100644 --- a/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using Bugsnag; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Images; @@ -36,6 +37,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan IMediator mediator, IFFmpegProcessServiceFactory ffmpegProcessServiceFactory, ITempFilePool tempFilePool, + IClient client, ILogger logger) : base( localFileSystem, localStatisticsProvider, @@ -44,6 +46,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan imageCache, ffmpegProcessServiceFactory, tempFilePool, + client, logger) { _localFileSystem = localFileSystem; diff --git a/ErsatzTV/Services/EmbyService.cs b/ErsatzTV/Services/EmbyService.cs index 7dcb3f707..6265db878 100644 --- a/ErsatzTV/Services/EmbyService.cs +++ b/ErsatzTV/Services/EmbyService.cs @@ -1,4 +1,5 @@ using System.Threading.Channels; +using Bugsnag; using ErsatzTV.Application; using ErsatzTV.Application.Emby; using ErsatzTV.Core; @@ -65,6 +66,19 @@ public class EmbyService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Failed to process Emby background service request"); + + try + { + using (IServiceScope scope = _serviceScopeFactory.CreateScope()) + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + } + catch (Exception) + { + // do nothing + } } } } diff --git a/ErsatzTV/Services/FFmpegWorkerService.cs b/ErsatzTV/Services/FFmpegWorkerService.cs index c66458f62..523642a55 100644 --- a/ErsatzTV/Services/FFmpegWorkerService.cs +++ b/ErsatzTV/Services/FFmpegWorkerService.cs @@ -1,4 +1,5 @@ using System.Threading.Channels; +using Bugsnag; using ErsatzTV.Application; using ErsatzTV.Application.Streaming; using ErsatzTV.Core.Interfaces.FFmpeg; @@ -30,10 +31,10 @@ public class FFmpegWorkerService : BackgroundService await foreach (IFFmpegWorkerRequest request in _channel.ReadAllAsync(cancellationToken)) { + using IServiceScope scope = _serviceScopeFactory.CreateScope(); + try { - using IServiceScope scope = _serviceScopeFactory.CreateScope(); - // IMediator mediator = scope.ServiceProvider.GetRequiredService(); switch (request) { @@ -49,6 +50,16 @@ public class FFmpegWorkerService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Failed to handle ffmpeg worker request"); + + try + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + catch (Exception) + { + // do nothing + } } } } diff --git a/ErsatzTV/Services/JellyfinService.cs b/ErsatzTV/Services/JellyfinService.cs index 5d5b686ff..47eeb5dd2 100644 --- a/ErsatzTV/Services/JellyfinService.cs +++ b/ErsatzTV/Services/JellyfinService.cs @@ -1,4 +1,5 @@ using System.Threading.Channels; +using Bugsnag; using ErsatzTV.Application; using ErsatzTV.Application.Jellyfin; using ErsatzTV.Core; @@ -65,6 +66,19 @@ public class JellyfinService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Failed to process Jellyfin background service request"); + + try + { + using (IServiceScope scope = _serviceScopeFactory.CreateScope()) + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + } + catch (Exception) + { + // do nothing + } } } } diff --git a/ErsatzTV/Services/PlexService.cs b/ErsatzTV/Services/PlexService.cs index 41dda9f60..04b1a8e32 100644 --- a/ErsatzTV/Services/PlexService.cs +++ b/ErsatzTV/Services/PlexService.cs @@ -1,4 +1,5 @@ using System.Threading.Channels; +using Bugsnag; using ErsatzTV.Application; using ErsatzTV.Application.Plex; using ErsatzTV.Core; @@ -65,6 +66,19 @@ public class PlexService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Failed to process plex background service request"); + + try + { + using (IServiceScope scope = _serviceScopeFactory.CreateScope()) + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + } + catch (Exception) + { + // do nothing + } } } } diff --git a/ErsatzTV/Services/SchedulerService.cs b/ErsatzTV/Services/SchedulerService.cs index 345b048d8..447ab1d76 100644 --- a/ErsatzTV/Services/SchedulerService.cs +++ b/ErsatzTV/Services/SchedulerService.cs @@ -1,4 +1,5 @@ using System.Threading.Channels; +using Bugsnag; using ErsatzTV.Application; using ErsatzTV.Application.Maintenance; using ErsatzTV.Application.MediaCollections; @@ -83,6 +84,19 @@ public class SchedulerService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Error during scheduler run"); + + try + { + using (IServiceScope scope = _serviceScopeFactory.CreateScope()) + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + } + catch (Exception) + { + // do nothing + } } } @@ -110,6 +124,19 @@ public class SchedulerService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Error during scheduler run"); + + try + { + using (IServiceScope scope = _serviceScopeFactory.CreateScope()) + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + } + catch (Exception) + { + // do nothing + } } } diff --git a/ErsatzTV/Services/WorkerService.cs b/ErsatzTV/Services/WorkerService.cs index 11392c849..02705d1c6 100644 --- a/ErsatzTV/Services/WorkerService.cs +++ b/ErsatzTV/Services/WorkerService.cs @@ -1,4 +1,5 @@ using System.Threading.Channels; +using Bugsnag; using ErsatzTV.Application; using ErsatzTV.Application.Maintenance; using ErsatzTV.Application.MediaCollections; @@ -32,9 +33,10 @@ public class WorkerService : BackgroundService await foreach (IBackgroundServiceRequest request in _channel.ReadAllAsync(cancellationToken)) { + using IServiceScope scope = _serviceScopeFactory.CreateScope(); + try { - using IServiceScope scope = _serviceScopeFactory.CreateScope(); IMediator mediator = scope.ServiceProvider.GetRequiredService(); switch (request) @@ -84,6 +86,16 @@ public class WorkerService : BackgroundService catch (Exception ex) { _logger.LogWarning(ex, "Failed to process background service request"); + + try + { + IClient client = scope.ServiceProvider.GetRequiredService(); + client.Notify(ex); + } + catch (Exception) + { + // do nothing + } } } } diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs index 20f847c48..d554f52c6 100644 --- a/ErsatzTV/Startup.cs +++ b/ErsatzTV/Startup.cs @@ -85,6 +85,7 @@ public class Startup configuration.AppVersion = Assembly.GetEntryAssembly() ?.GetCustomAttribute() ?.InformationalVersion ?? "unknown"; + configuration.AutoNotify = false; configuration.NotifyReleaseStages = new[] { "public", "develop" };