What changed, and why it matters
This commit only improves monitoring/observability. It adds a new label ('error-type') to internal error-counting metrics so developers can see what kind of channel errors are happening, in addition to whether they came from the local node or a remote peer. There is no user-facing behavior change, no bug fix in business logic, and no security fix.
No security action required. Treat as a normal observability improvement during routine review/merge.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch enriches Kamon metrics tags for channel errors. It introduces a new tag constant ErrorType in Monitoring.scala and updates DbEventHandler.scala to build a TagSet that includes the exception class name for LocalError and marks remote errors as always fatal. This is purely a telemetry/metrics enhancement; no functional channel logic is modified.
Changed components
eclair-core/src/main/scala/fr/acinq/eclair/channel/Monitoring.scalaeclair-core/src/main/scala/fr/acinq/eclair/db/DbEventHandler.scalaInspect captured patch +13 / −4
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Monitoring.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Monitoring.scala
index f7d8062..863de3a 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Monitoring.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Monitoring.scala
@@ -86,6 +86,7 @@ object Monitoring {
val Direction = "direction"
val Event = "event"
val Fatal = "fatal"
+ val ErrorType = "error-type"
val Origin = "origin"
val State = "state"
val CommitmentFormat = "commitment-format"
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/DbEventHandler.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/DbEventHandler.scala
index 9275ade..77343e8 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/db/DbEventHandler.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/DbEventHandler.scala
@@ -30,6 +30,7 @@ import fr.acinq.eclair.db.DbEventHandler.ChannelEvent
import fr.acinq.eclair.payment.Monitoring.{Metrics => PaymentMetrics, Tags => PaymentTags}
import fr.acinq.eclair.payment._
import fr.acinq.eclair.{Logs, NodeParams, TimestampMilli}
+import kamon.tag.TagSet
/**
* This actor sits at the interface between our event stream and the database.
@@ -112,10 +113,17 @@ class DbEventHandler(nodeParams: NodeParams) extends Actor with DiagnosticActorL
// The first pattern matching level is to ignore some errors, the second level is to separate between different kind of errors.
e.error match {
case LocalError(_: CannotAffordFees) => () // will be thrown at each new block if our balance is too low to update the commitment fee
- case _ => e.error match {
- case LocalError(_) => ChannelMetrics.ChannelErrors.withTag(ChannelTags.Origin, ChannelTags.Origins.Local).withTag(ChannelTags.Fatal, value = e.isFatal).increment()
- case RemoteError(_) => ChannelMetrics.ChannelErrors.withTag(ChannelTags.Origin, ChannelTags.Origins.Remote).increment()
- }
+ case _ =>
+ val tags = e.error match {
+ case LocalError(t) => TagSet.Empty
+ .withTag(ChannelTags.Origin, ChannelTags.Origins.Local)
+ .withTag(ChannelTags.Fatal, value = e.isFatal)
+ .withTag(ChannelTags.ErrorType, t.getClass.getSimpleName)
+ case RemoteError(_) => TagSet.Empty
+ .withTag(ChannelTags.Origin, ChannelTags.Origins.Remote)
+ .withTag(ChannelTags.Fatal, value = true) // remote errors are always fatal
+ }
+ ChannelMetrics.ChannelErrors.withTags(tags).increment()
}
case e: ChannelStateChanged =>
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.