Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
kiss
  • Loading branch information
bitsandfoxes committed Sep 23, 2024
commit 9f77eb7580a169ed432053eed4d13d2a631c3dac
61 changes: 0 additions & 61 deletions samples/Sentry.Samples.Console.Basic/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,64 +35,3 @@
options.TracesSampleRate = 1.0;
});

// This starts a new transaction and attaches it to the scope.
var transaction = SentrySdk.StartTransaction("Program Main", "function");
SentrySdk.ConfigureScope(scope => scope.Transaction = transaction);

// Do some work. (This is where you'd have your own application logic.)
await FirstFunction();
await SecondFunction();
await ThirdFunction();

// Always try to finish the transaction successfully.
// Unhandled exceptions will fail the transaction automatically.
// Optionally, you can try/catch the exception, and call transaction.Finish(exception) on failure.
transaction.Finish();

async Task FirstFunction()
{
// This is an example of making an HttpRequest. A trace us automatically captured by Sentry for this.
var messageHandler = new SentryHttpMessageHandler();
var httpClient = new HttpClient(messageHandler, true);
var html = await httpClient.GetStringAsync("https://example.com/");
Console.WriteLine(html);
}

async Task SecondFunction()
{
var span = transaction.StartChild("function", nameof(SecondFunction));

try
{
// Simulate doing some work
await Task.Delay(100);

// Throw an exception
throw new ApplicationException("Something happened!");
}
catch (Exception exception)
{
// This is an example of capturing a handled exception.
SentrySdk.CaptureException(exception);
span.Finish(exception);
}

span.Finish();
}

async Task ThirdFunction()
{
var span = transaction.StartChild("function", nameof(ThirdFunction));
try
{
// Simulate doing some work
await Task.Delay(100);

// This is an example of an unhandled exception. It will be captured automatically.
throw new InvalidOperationException("Something happened that crashed the app!");
}
finally
{
span.Finish();
}
}
2 changes: 1 addition & 1 deletion src/Sentry/ISentryJsonSerializable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface ISentryJsonSerializable

internal static class JsonSerializableExtensions
{
public static void WriteToFile(this ISentryJsonSerializable serializable, ISentryFileSystem fileSystem, string filePath, IDiagnosticLogger? logger)
public static void WriteToFile(this ISentryJsonSerializable serializable, IFileSystem fileSystem, string filePath, IDiagnosticLogger? logger)
{
using var file = fileSystem.CreateFileForWriting(filePath);
if (file == Stream.Null)
Expand Down
114 changes: 114 additions & 0 deletions src/Sentry/Internal/FileSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using Sentry.Extensibility;

namespace Sentry.Internal;

internal class FileSystem : IFileSystem
{
private readonly SentryOptions? _options;

public FileSystem(SentryOptions? options)
{
_options = options;
}

public IEnumerable<string> EnumerateFiles(string path) => Directory.EnumerateFiles(path);

public IEnumerable<string> EnumerateFiles(string path, string searchPattern) =>
Directory.EnumerateFiles(path, searchPattern);

public IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOption) =>
Directory.EnumerateFiles(path, searchPattern, searchOption);

public bool CreateDirectory(string path)
{
if (!_options?.DisableFileWrite is false)
{
_options?.LogDebug("Skipping creating directory. Writing to file system has been explicitly disabled.");
return false;
}

Directory.CreateDirectory(path);
return true;
}

public bool DeleteDirectory(string path, bool recursive = false)
{
if (!_options?.DisableFileWrite is false)
{
_options?.LogDebug("Skipping deleting directory. Writing to file system has been explicitly disabled.");
return false;
}

Directory.Delete(path, recursive);
return true;
}

public bool DirectoryExists(string path) => Directory.Exists(path);

public bool FileExists(string path) => File.Exists(path);

public bool MoveFile(string sourceFileName, string destFileName, bool overwrite = false)
{
if (!_options?.DisableFileWrite is false)
{
_options?.LogDebug("Skipping moving file. Writing to file system has been explicitly disabled.");
return false;
}

#if NETCOREAPP3_0_OR_GREATER
File.Move(sourceFileName, destFileName, overwrite);
#else
if (overwrite)
{
File.Copy(sourceFileName, destFileName, overwrite: true);
File.Delete(sourceFileName);
}
else
{
File.Move(sourceFileName, destFileName);
}
#endif
return true;
}

public bool DeleteFile(string path)
{
if (!_options?.DisableFileWrite is false)
{
_options?.LogDebug("Skipping deleting file. Writing to file system has been explicitly disabled.");
return false;
}

File.Delete(path);
return true;
}

public DateTimeOffset GetFileCreationTime(string path) => new FileInfo(path).CreationTimeUtc;

public string ReadAllTextFromFile(string path) => File.ReadAllText(path);

public Stream OpenFileForReading(string path) => File.OpenRead(path);

public Stream CreateFileForWriting(string path)
{
if (!_options?.DisableFileWrite is false)
{
_options?.LogDebug("Skipping file for writing. Writing to file system has been explicitly disabled.");
return Stream.Null;
}

return File.Create(path);
}

public bool WriteAllTextToFile(string path, string contents)
{
if (!_options?.DisableFileWrite is false)
{
_options?.LogDebug("Skipping writing all text to file. Writing to file system has been explicitly disabled.");
return false;
}

File.WriteAllText(path, contents);
return true;
}
}
2 changes: 1 addition & 1 deletion src/Sentry/Internal/Http/CachingTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal class CachingTransport : ITransport, IDisposable
// Inner transport exposed internally primarily for testing
internal ITransport InnerTransport => _innerTransport;

private readonly ISentryFileSystem _fileSystem;
private readonly IFileSystem _fileSystem;

public static CachingTransport Create(ITransport innerTransport, SentryOptions options,
bool startWorker = true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Sentry.Internal;

internal interface ISentryFileSystem
internal interface IFileSystem
{
// Note: This is not comprehensive. If you need other filesystem methods, add to this interface,
// then implement in both Sentry.Internal.FileSystem and Sentry.Testing.FakeFileSystem.
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/Internal/Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static T Parse<T>(string json, Func<JsonElement, T> factory)
return factory.Invoke(jsonDocument.RootElement);
}

public static T Load<T>(ISentryFileSystem fileSystem, string filePath, Func<JsonElement, T> factory)
public static T Load<T>(IFileSystem fileSystem, string filePath, Func<JsonElement, T> factory)
{
using var file = fileSystem.OpenFileForReading(filePath);
using var jsonDocument = JsonDocument.Parse(file);
Expand Down
8 changes: 0 additions & 8 deletions src/Sentry/Sentry.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@
</Compile>
</ItemGroup>

<!--
We use TestableIO to be able to mock the FileSystem during tests
https://github.com/TestableIO/System.IO.Abstractions
-->
<ItemGroup>
<PackageReference Include="TestableIO.System.IO.Abstractions.TestingHelpers" Version="20.0.4" PrivateAssets="all" />
</ItemGroup>

<!--
We use Simon Cropp's Polyfill source-only package to access APIs in lower targets.
https://github.com/SimonCropp/Polyfill
Expand Down
6 changes: 3 additions & 3 deletions src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -723,10 +723,10 @@ public IList<SubstringOrRegexPattern> FailedRequestTargets
}

/// <summary>
/// Sets the filesystem instance to use. Defaults to the actual <see cref="SentryFileSystem"/>.
/// Sets the filesystem instance to use. Defaults to the actual <see cref="Internal.FileSystem"/>.
/// Used for testing.
/// </summary>
internal ISentryFileSystem FileSystem { get; set; }
internal IFileSystem FileSystem { get; set; }

/// <summary>
/// Allows to disable the SDKs writing to disk operations
Expand Down Expand Up @@ -1184,7 +1184,7 @@ public bool JsonPreserveReferences
/// </summary>
public SentryOptions()
{
FileSystem = new SentryFileSystem(this);
FileSystem = new FileSystem(this);
SettingLocator = new SettingLocator(this);
_lazyInstallationId = new(() => new InstallationIdHelper(this).TryGetInstallationId());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ async Task VerifyAsync(HttpRequestMessage message)
ProfilesSampleRate = 1.0,
};

// This keeps all writing-to-file opterations in memory instead of actually writing to disk
options.FileSystem = new SentryFileSystem(options, new MockFileSystem());
// This keeps all writing-to-file operations in memory instead of actually writing to disk
options.FileSystem = new FakeFileSystem(options);

// Disable process exit flush to resolve "There is no currently active test." errors.
options.DisableAppDomainProcessExitFlush();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
using System.IO.Abstractions;
using Sentry.Extensibility;
using System.IO.Abstractions.TestingHelpers;

namespace Sentry.Internal;

internal class SentryFileSystem : ISentryFileSystem
internal class FakeFileSystem : IFileSystem
{
private readonly SentryOptions? _options;
private readonly SentryOptions _options;

private readonly IFileSystem _fileSystem;
private readonly MockFileSystem _fileSystem;

public SentryFileSystem(SentryOptions? options, IFileSystem? fileSystem = null)
public FakeFileSystem(SentryOptions options)
{
_options = options;
_fileSystem = fileSystem ?? new FileSystem();
_fileSystem = new MockFileSystem();
}

public IEnumerable<string> EnumerateFiles(string path) => _fileSystem.Directory.EnumerateFiles(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
namespace Sentry.Tests;

public class SentryFileSystemTests
public class FileSystemTests
{
private class Fixture
{
public SentryOptions Options;

public Fixture() => Options = new SentryOptions { Dsn = ValidDsn };

public SentryFileSystem GetSut() => new(Options);
public FileSystem GetSut() => new(Options);
}

private readonly Fixture _fixture = new();
Expand Down
4 changes: 2 additions & 2 deletions test/Sentry.Tests/GlobalSessionManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public Fixture(Action<SentryOptions> configureOptions = null)
CacheDirectoryPath = CacheDirectory.Path,
};

// This keeps all writing-to-file opterations in memory instead of actually writing to disk
Options.FileSystem = new SentryFileSystem(Options, new MockFileSystem());
// This keeps all writing-to-file operations in memory instead of actually writing to disk
Options.FileSystem = new FakeFileSystem(Options);

configureOptions?.Invoke(Options);
}
Expand Down
4 changes: 2 additions & 2 deletions test/Sentry.Tests/HubTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ async Task Verify(HttpRequestMessage message)
DiagnosticLogger = logger
};

// This keeps all writing-to-file opterations in memory instead of actually writing to disk
options.FileSystem = new SentryFileSystem(options, new MockFileSystem());
// This keeps all writing-to-file operations in memory instead of actually writing to disk
options.FileSystem = new FakeFileSystem(options);

// Disable process exit flush to resolve "There is no currently active test." errors.
options.DisableAppDomainProcessExitFlush();
Expand Down
4 changes: 2 additions & 2 deletions test/Sentry.Tests/Internals/BackgroundWorkerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,8 @@ public async Task FlushAsync_Calls_CachingTransport_FlushAsync()
using var tempDir = new TempDirectory();

var options = _fixture.SentryOptions;
// This keeps all writing-to-file opterations in memory instead of actually writing to disk
options.FileSystem = new SentryFileSystem(options, new MockFileSystem());
// This keeps all writing-to-file operations in memory instead of actually writing to disk
options.FileSystem = new FakeFileSystem(options);
options.CacheDirectoryPath = tempDir.Path;

var innerTransport = _fixture.Transport;
Expand Down
5 changes: 1 addition & 4 deletions test/Sentry.Tests/Internals/Http/CachingTransportTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ public async Task WithAttachment()
CacheDirectoryPath = cacheDirectory.Path
};

// This keeps all writing-to-file opterations in memory instead of actually writing to disk
options.FileSystem = new SentryFileSystem(options, new MockFileSystem());

string httpContent = null;
Exception exception = null;
var innerTransport = new HttpTransport(options, new HttpClient(new CallbackHttpClientHandler(async message =>
Expand Down Expand Up @@ -725,7 +722,7 @@ public async Task DoesntWriteSentAtHeaderToCacheFile()
Debug = true,
CacheDirectoryPath = cacheDirectory.Path
};
options.FileSystem = new SentryFileSystem(options, new MockFileSystem());
options.FileSystem = new FakeFileSystem(options);

var innerTransport = Substitute.For<ITransport>();
await using var transport = CachingTransport.Create(innerTransport, options, startWorker: false);
Expand Down
4 changes: 2 additions & 2 deletions test/Sentry.Tests/Internals/InstallationIdHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public Fixture(Action<SentryOptions> configureOptions = null)

configureOptions?.Invoke(Options);

// This keeps all writing-to-file opterations in memory instead of actually writing to disk
Options.FileSystem = new SentryFileSystem(Options, new MockFileSystem());
// This keeps all writing-to-file operations in memory instead of actually writing to disk
Options.FileSystem = new FakeFileSystem(Options);
}

public InstallationIdHelper GetSut() => new(Options);
Expand Down