diff --git a/Sentry-CI-Build-macOS.slnf b/Sentry-CI-Build-macOS.slnf
index e654c81e63..ae938b72d0 100644
--- a/Sentry-CI-Build-macOS.slnf
+++ b/Sentry-CI-Build-macOS.slnf
@@ -36,12 +36,13 @@
"samples\\Sentry.Samples.OpenTelemetry.AspNetCore\\Sentry.Samples.OpenTelemetry.AspNetCore.csproj",
"samples\\Sentry.Samples.OpenTelemetry.Console\\Sentry.Samples.OpenTelemetry.Console.csproj",
"samples\\Sentry.Samples.Serilog\\Sentry.Samples.Serilog.csproj",
+ "samples\\Sentry.Samples.Sqlite\\Sentry.Samples.Sqlite.csproj",
"src\\Sentry.Analyzers\\Sentry.Analyzers.csproj",
"src\\Sentry.Android.AssemblyReader\\Sentry.Android.AssemblyReader.csproj",
- "src\\Sentry.AspNet\\Sentry.AspNet.csproj",
"src\\Sentry.AspNetCore.Blazor.WebAssembly\\Sentry.AspNetCore.Blazor.WebAssembly.csproj",
"src\\Sentry.AspNetCore.Grpc\\Sentry.AspNetCore.Grpc.csproj",
"src\\Sentry.AspNetCore\\Sentry.AspNetCore.csproj",
+ "src\\Sentry.AspNet\\Sentry.AspNet.csproj",
"src\\Sentry.Azure.Functions.Worker\\Sentry.Azure.Functions.Worker.csproj",
"src\\Sentry.Bindings.Android\\Sentry.Bindings.Android.csproj",
"src\\Sentry.Bindings.Cocoa\\Sentry.Bindings.Cocoa.csproj",
@@ -58,6 +59,7 @@
"src\\Sentry.Profiling\\Sentry.Profiling.csproj",
"src\\Sentry.Serilog\\Sentry.Serilog.csproj",
"src\\Sentry.SourceGenerators\\Sentry.SourceGenerators.csproj",
+ "src\\Sentry.Sqlite\\Sentry.Sqlite.csproj",
"src\\Sentry\\Sentry.csproj",
"test\\Sentry.Analyzers.Tests\\Sentry.Analyzers.Tests.csproj",
"test\\Sentry.Android.AssemblyReader.Tests\\Sentry.Android.AssemblyReader.Tests.csproj",
@@ -87,4 +89,4 @@
"test\\SingleFileTestApp\\SingleFileTestApp.csproj"
]
}
-}
+}
\ No newline at end of file
diff --git a/Sentry.sln b/Sentry.sln
index 3730377a46..fa8e6cac7d 100644
--- a/Sentry.sln
+++ b/Sentry.sln
@@ -209,6 +209,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.SourceGenerators.Tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Maui.CommunityToolkit.Mvvm.Tests", "test\Sentry.Maui.CommunityToolkit.Mvvm.Tests\Sentry.Maui.CommunityToolkit.Mvvm.Tests.csproj", "{ADC91A84-6054-42EC-8241-0D717E4C7194}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Sqlite", "src\Sentry.Sqlite\Sentry.Sqlite.csproj", "{CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Samples.Sqlite", "samples\Sentry.Samples.Sqlite\Sentry.Samples.Sqlite.csproj", "{BB4FF3AE-C835-41AB-8F75-1611977BCF71}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1252,6 +1256,30 @@ Global
{ADC91A84-6054-42EC-8241-0D717E4C7194}.Release|x64.Build.0 = Release|Any CPU
{ADC91A84-6054-42EC-8241-0D717E4C7194}.Release|x86.ActiveCfg = Release|Any CPU
{ADC91A84-6054-42EC-8241-0D717E4C7194}.Release|x86.Build.0 = Release|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Debug|x64.Build.0 = Debug|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Debug|x86.Build.0 = Debug|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Release|x64.ActiveCfg = Release|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Release|x64.Build.0 = Release|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Release|x86.ActiveCfg = Release|Any CPU
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912}.Release|x86.Build.0 = Release|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Debug|x64.Build.0 = Debug|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Debug|x86.Build.0 = Debug|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Release|x64.ActiveCfg = Release|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Release|x64.Build.0 = Release|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Release|x86.ActiveCfg = Release|Any CPU
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1343,5 +1371,7 @@ Global
{C3CDF61C-3E28-441C-A9CE-011C89D11719} = {230B9384-90FD-4551-A5DE-1A5C197F25B6}
{3A76FF7D-2F32-4EA5-8999-2FFE3C7CB893} = {6987A1CC-608E-4868-A02C-09D30C8B7B2D}
{ADC91A84-6054-42EC-8241-0D717E4C7194} = {6987A1CC-608E-4868-A02C-09D30C8B7B2D}
+ {CDCCB2EC-9DA8-4CBE-94D6-00EAB990D912} = {230B9384-90FD-4551-A5DE-1A5C197F25B6}
+ {BB4FF3AE-C835-41AB-8F75-1611977BCF71} = {21B42F60-5802-404E-90F0-AEBCC56760C0}
EndGlobalSection
EndGlobal
diff --git a/samples/Sentry.Samples.Sqlite/Program.cs b/samples/Sentry.Samples.Sqlite/Program.cs
new file mode 100644
index 0000000000..d28bf95db6
--- /dev/null
+++ b/samples/Sentry.Samples.Sqlite/Program.cs
@@ -0,0 +1,89 @@
+using System;
+using System.IO;
+using Microsoft.Data.Sqlite;
+using Sentry.Sqlite;
+
+SentrySdk.Init(options =>
+{
+#if !SENTRY_DSN_DEFINED_IN_ENV
+ // A DSN is required. You can set here in code, or you can set it in the SENTRY_DSN environment variable.
+ // See https://docs.sentry.io/product/sentry-basics/dsn-explainer/
+ options.Dsn = SamplesShared.Dsn;
+#endif
+ options.Debug = false;
+ options.TracesSampleRate = 1.0;
+});
+
+using (var connection = new SentrySqliteConnection("Data Source=hello.db"))
+{
+ connection.Open();
+
+ var command = connection.CreateCommand();
+ command.CommandText =
+ @"
+ CREATE TABLE user (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL
+ );
+
+ INSERT INTO user
+ VALUES (1, 'Brice'),
+ (2, 'Alexander'),
+ (3, 'Nate');
+ ";
+ command.ExecuteNonQuery();
+
+ Console.Write("Name: ");
+ var name = Console.ReadLine();
+
+ #region snippet_Parameter
+ command.CommandText =
+ @"
+ INSERT INTO user (name)
+ VALUES ($name)
+ ";
+ command.Parameters.AddWithValue("$name", name);
+ #endregion
+ command.ExecuteNonQuery();
+
+ command.CommandText =
+ @"
+ SELECT last_insert_rowid()
+ ";
+ var newId = (long)command.ExecuteScalar()!;
+
+ Console.WriteLine($"Your new user ID is {newId}.");
+}
+
+Console.Write("User ID: ");
+var id = int.Parse(Console.ReadLine()!);
+
+#region snippet_HelloWorld
+using (var connection = new SqliteConnection("Data Source=hello.db"))
+{
+ connection.Open();
+
+ var command = connection.CreateCommand();
+ command.CommandText =
+ @"
+ SELECT name
+ FROM user
+ WHERE id = $id
+ ";
+ command.Parameters.AddWithValue("$id", id);
+
+ using (var reader = command.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ var name = reader.GetString(0);
+
+ Console.WriteLine($"Hello, {name}!");
+ }
+ }
+}
+#endregion
+
+// Clean up
+SqliteConnection.ClearAllPools();
+File.Delete("hello.db");
diff --git a/samples/Sentry.Samples.Sqlite/Sentry.Samples.Sqlite.csproj b/samples/Sentry.Samples.Sqlite/Sentry.Samples.Sqlite.csproj
new file mode 100644
index 0000000000..89a257e5cd
--- /dev/null
+++ b/samples/Sentry.Samples.Sqlite/Sentry.Samples.Sqlite.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sentry.Sqlite/Sentry.Sqlite.csproj b/src/Sentry.Sqlite/Sentry.Sqlite.csproj
new file mode 100644
index 0000000000..abebe72060
--- /dev/null
+++ b/src/Sentry.Sqlite/Sentry.Sqlite.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net9.0
+ enable
+ enable
+ Experimental Microsoft.Data.Sqlite integration for Sentry - Open-source error tracking that helps developers monitor and fix crashes in real time.
+ $(PackageTags);Sqlite
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sentry.Sqlite/SentrySqliteCommand.cs b/src/Sentry.Sqlite/SentrySqliteCommand.cs
new file mode 100644
index 0000000000..dc2b03f521
--- /dev/null
+++ b/src/Sentry.Sqlite/SentrySqliteCommand.cs
@@ -0,0 +1,37 @@
+using Microsoft.Data.Sqlite;
+
+namespace Sentry.Sqlite;
+
+///
+public class SentrySqliteCommand : SqliteCommand
+{
+ internal ITransactionTracer? TransactionTracer { get; set; } = null;
+
+ ///
+ public override int ExecuteNonQuery()
+ {
+ var span = TransactionTracer?.StartChild("db.query", CommandText);
+ try
+ {
+ return base.ExecuteNonQuery();
+ }
+ finally
+ {
+ span?.Finish();
+ }
+ }
+
+ ///
+ public override object? ExecuteScalar()
+ {
+ var span = TransactionTracer?.StartChild("db.query", CommandText);
+ try
+ {
+ return base.ExecuteScalar();
+ }
+ finally
+ {
+ span?.Finish();
+ }
+ }
+}
diff --git a/src/Sentry.Sqlite/SentrySqliteConnection.cs b/src/Sentry.Sqlite/SentrySqliteConnection.cs
new file mode 100644
index 0000000000..19d0904eab
--- /dev/null
+++ b/src/Sentry.Sqlite/SentrySqliteConnection.cs
@@ -0,0 +1,52 @@
+using System.Data.Common;
+using Microsoft.Data.Sqlite;
+
+namespace Sentry.Sqlite;
+
+///
+public class SentrySqliteConnection : SqliteConnection
+{
+ private ITransactionTracer? TransactionTracer { get; set; } = null;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The string used to open the connection.
+ /// Connection Strings
+ ///
+ public SentrySqliteConnection(string? connectionString) : base(connectionString)
+ {
+ }
+
+ ///
+ public override void Open()
+ {
+ TransactionTracer = SentrySdk.StartTransaction(
+ "Open SQLite Connection",
+ "db.sqlite.open"
+ );
+ base.Open();
+ }
+
+ ///
+ public new virtual SentrySqliteCommand CreateCommand()
+ => new()
+ {
+ Connection = this,
+ CommandTimeout = DefaultTimeout,
+ Transaction = Transaction,
+ TransactionTracer = TransactionTracer
+ };
+
+ ///
+ protected override DbCommand CreateDbCommand()
+ => CreateCommand();
+
+ ///
+ public override void Close()
+ {
+ base.Close();
+ TransactionTracer?.Finish();
+ TransactionTracer = null;
+ }
+}