diff --git a/conduwuit-example.toml b/conduwuit-example.toml
index cb6dc8e6bbfef8f011eaa86d026c42136a948ff3..ea095bfa11451c0b5457cb336a86e2488fb13915 100644
--- a/conduwuit-example.toml
+++ b/conduwuit-example.toml
@@ -60,6 +60,13 @@
 # Whether to attach a stacktrace to Sentry reports.
 #sentry_attach_stacktrace = false
 
+# Send panics to sentry. This is true by default, but sentry has to be enabled.
+#sentry_send_panic = true
+
+# Send errors to sentry. This is true by default, but sentry has to be enabled. This option is
+# only effective in release-mode; forced to false in debug-mode.
+#sentry_send_error = true
+
 
 ### Database configuration
 
diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs
index 8b864c846b277a9e4af41675427b2e0368083c06..1997a39ee09b0a8ccbd44da7c85dfc23e70d1a48 100644
--- a/src/core/config/mod.rs
+++ b/src/core/config/mod.rs
@@ -358,6 +358,10 @@ pub struct Config {
 	pub sentry_traces_sample_rate: f32,
 	#[serde(default)]
 	pub sentry_attach_stacktrace: bool,
+	#[serde(default = "true_fn")]
+	pub sentry_send_panic: bool,
+	#[serde(default = "true_fn")]
+	pub sentry_send_error: bool,
 
 	#[serde(default)]
 	pub tokio_console: bool,
@@ -822,6 +826,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 			#[cfg(feature = "sentry_telemetry")]
 			("Sentry.io tracing sample rate", &self.sentry_traces_sample_rate.to_string()),
 			("Sentry.io attach stacktrace", &self.sentry_attach_stacktrace.to_string()),
+			("Sentry.io send panics", &self.sentry_send_panic.to_string()),
+			("Sentry.io send errors", &self.sentry_send_error.to_string()),
 			(
 				"Well-known server name",
 				self.well_known
diff --git a/src/main/sentry.rs b/src/main/sentry.rs
index 59f88a0ce351a2c4b70869f980995b2e08de2af6..04ad8654f982da1e564292421420d8327221d35f 100644
--- a/src/main/sentry.rs
+++ b/src/main/sentry.rs
@@ -1,18 +1,34 @@
 #![cfg(feature = "sentry_telemetry")]
 
-use std::{str::FromStr, sync::Arc};
+use std::{
+	str::FromStr,
+	sync::{Arc, OnceLock},
+};
 
-use conduit::{config::Config, trace};
+use conduit::{config::Config, debug, trace};
 use sentry::{
-	types::{protocol::v7::Event, Dsn},
-	Breadcrumb, ClientOptions,
+	types::{
+		protocol::v7::{Context, Event},
+		Dsn,
+	},
+	Breadcrumb, ClientOptions, Level,
 };
 
+static SEND_PANIC: OnceLock<bool> = OnceLock::new();
+static SEND_ERROR: OnceLock<bool> = OnceLock::new();
+
 pub(crate) fn init(config: &Config) -> Option<sentry::ClientInitGuard> {
 	config.sentry.then(|| sentry::init(options(config)))
 }
 
 fn options(config: &Config) -> ClientOptions {
+	SEND_PANIC
+		.set(config.sentry_send_panic)
+		.expect("SEND_PANIC was not previously set");
+	SEND_ERROR
+		.set(config.sentry_send_error)
+		.expect("SEND_ERROR was not previously set");
+
 	let dsn = config
 		.sentry_endpoint
 		.as_ref()
@@ -36,11 +52,40 @@ fn options(config: &Config) -> ClientOptions {
 }
 
 fn before_send(event: Event<'static>) -> Option<Event<'static>> {
-	trace!("Sending sentry event: {event:?}");
+	if event.exception.iter().any(|e| e.ty == "panic") && !SEND_PANIC.get().unwrap_or(&true) {
+		return None;
+	}
+
+	if event.level == Level::Error {
+		if !SEND_ERROR.get().unwrap_or(&true) {
+			return None;
+		}
+
+		if cfg!(debug_assertions) {
+			return None;
+		}
+
+		//NOTE: we can enable this to specify error!(sentry = true, ...)
+		if let Some(Context::Other(context)) = event.contexts.get("Rust Tracing Fields") {
+			if !context.contains_key("sentry") {
+				//return None;
+			}
+		}
+	}
+
+	if event.level == Level::Fatal {
+		trace!("{event:#?}");
+	}
+
+	debug!("Sending sentry event: {event:?}");
 	Some(event)
 }
 
 fn before_breadcrumb(crumb: Breadcrumb) -> Option<Breadcrumb> {
-	trace!("Adding sentry breadcrumb: {crumb:?}");
+	if crumb.ty == "log" && crumb.level == Level::Debug {
+		return None;
+	}
+
+	trace!("Sentry breadcrumb: {crumb:?}");
 	Some(crumb)
 }