refactor(sentry): decouple agent import via string-match, rename predicate
Some checks failed
CI / Test (push) Successful in 2m46s
CI / Build (push) Successful in 1m35s
CI / Build-1 (push) Successful in 1m59s
CI / Build-2 (push) Successful in 1m35s
CI / Build-3 (push) Successful in 1m35s
CI / Build-4 (push) Successful in 1m33s
CI / Build-5 (push) Successful in 1m39s
CI / Lint (push) Failing after 2m33s
CI / Coverage (push) Successful in 2m56s
CI / Vet (push) Successful in 2m7s
Some checks failed
CI / Test (push) Successful in 2m46s
CI / Build (push) Successful in 1m35s
CI / Build-1 (push) Successful in 1m59s
CI / Build-2 (push) Successful in 1m35s
CI / Build-3 (push) Successful in 1m35s
CI / Build-4 (push) Successful in 1m33s
CI / Build-5 (push) Successful in 1m39s
CI / Lint (push) Failing after 2m33s
CI / Coverage (push) Successful in 2m56s
CI / Vet (push) Successful in 2m7s
This commit is contained in:
parent
9fe796f195
commit
9135332777
5 changed files with 36 additions and 23 deletions
|
|
@ -9,8 +9,6 @@ import (
|
|||
|
||||
gosentry "github.com/getsentry/sentry-go"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/torrentclaw/unarr/internal/agent"
|
||||
)
|
||||
|
||||
// dsn is injected at build time via ldflags. If empty, Sentry is disabled.
|
||||
|
|
@ -48,11 +46,16 @@ func Close() {
|
|||
gosentry.Flush(flushTimeout)
|
||||
}
|
||||
|
||||
// daemonNotRunningMarker matches the message of agent.ErrDaemonNotRunning
|
||||
// without importing the agent package — avoids a sentry → agent dependency
|
||||
// that would risk a cycle if agent ever needed to report errors itself.
|
||||
const daemonNotRunningMarker = "daemon does not appear to be running"
|
||||
|
||||
// CaptureError sends a non-fatal error to Sentry with optional command context.
|
||||
// User-input errors (unknown flag/command, bad value) are skipped — they are
|
||||
// not bugs, just noise.
|
||||
// Expected non-bug errors (bad CLI input, daemon not running) are skipped to
|
||||
// keep the issue feed signal-heavy.
|
||||
func CaptureError(err error, command string) {
|
||||
if err == nil || isUserInputError(err) {
|
||||
if err == nil || shouldSkipSentry(err) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -64,10 +67,7 @@ func CaptureError(err error, command string) {
|
|||
})
|
||||
}
|
||||
|
||||
func isUserInputError(err error) bool {
|
||||
if errors.Is(err, agent.ErrDaemonNotRunning) {
|
||||
return true
|
||||
}
|
||||
func shouldSkipSentry(err error) bool {
|
||||
var notExist *pflag.NotExistError
|
||||
var valueReq *pflag.ValueRequiredError
|
||||
var invalidVal *pflag.InvalidValueError
|
||||
|
|
@ -78,7 +78,8 @@ func isUserInputError(err error) bool {
|
|||
}
|
||||
msg := err.Error()
|
||||
return strings.HasPrefix(msg, "unknown command ") ||
|
||||
strings.HasPrefix(msg, "required flag(s)")
|
||||
strings.HasPrefix(msg, "required flag(s)") ||
|
||||
strings.Contains(msg, daemonNotRunningMarker)
|
||||
}
|
||||
|
||||
// RecoverPanic captures a panic and re-panics after reporting.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package sentry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/torrentclaw/unarr/internal/agent"
|
||||
)
|
||||
|
||||
func TestEnvironment(t *testing.T) {
|
||||
|
|
@ -51,12 +50,15 @@ func TestSetUser(t *testing.T) {
|
|||
SetUser("agent-123")
|
||||
}
|
||||
|
||||
func TestIsUserInputErrorDaemonNotRunning(t *testing.T) {
|
||||
if !isUserInputError(agent.ErrDaemonNotRunning) {
|
||||
t.Error("ErrDaemonNotRunning should be treated as user-input error")
|
||||
func TestShouldSkipSentryDaemonNotRunning(t *testing.T) {
|
||||
// String must stay in sync with agent.ErrDaemonNotRunning. If that sentinel
|
||||
// is reworded, this test fails loudly so the marker can be updated.
|
||||
err := errors.New("daemon does not appear to be running (state file not found)")
|
||||
if !shouldSkipSentry(err) {
|
||||
t.Error("ErrDaemonNotRunning message should be skipped")
|
||||
}
|
||||
wrapped := fmt.Errorf("stop daemon: %w", agent.ErrDaemonNotRunning)
|
||||
if !isUserInputError(wrapped) {
|
||||
t.Error("wrapped ErrDaemonNotRunning should be treated as user-input error")
|
||||
wrapped := fmt.Errorf("read daemon state: %w", err)
|
||||
if !shouldSkipSentry(wrapped) {
|
||||
t.Error("wrapped ErrDaemonNotRunning message should be skipped")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue