Skip to content

Commit

Permalink
More metrics and test
Browse files Browse the repository at this point in the history
  • Loading branch information
thomash-acinq committed Jul 24, 2023
1 parent d70ca33 commit 7d53a40
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
import fr.acinq.eclair.MilliSatoshi
import fr.acinq.eclair.channel.CMD_FAIL_HTLC
import kamon.Kamon
import kamon.metric.Histogram

object Monitoring {

Expand Down Expand Up @@ -67,6 +68,10 @@ object Monitoring {
PaymentNodeOutAmount.withoutTags().record(bucket, amount.truncateToSatoshi.toLong)
PaymentNodeOut.withoutTags().record(bucket)
}

private val RelayConfidence = Kamon.histogram("payment.relay.confidence", "Confidence (in percent) that the relayed HTLC will be fulfilled")
def relaySettleFulfill(confidence: Double) = RelayConfidence.withTag("status", "fulfill").record((confidence * 100).toLong)
def relaySettleFail(confidence: Double) = RelayConfidence.withTag("status", "fail").record((confidence * 100).toLong)
}

object Tags {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,22 @@ class ChannelRelay private(nodeParams: NodeParams,

case WrappedAddResponse(_: RES_SUCCESS[_]) =>
context.log.debug("sent htlc to the downstream channel")
waitForAddSettled()
waitForAddSettled(confidence)
}

def waitForAddSettled(): Behavior[Command] =
def waitForAddSettled(confidence: Double): Behavior[Command] =
Behaviors.receiveMessagePartial {
case WrappedAddResponse(RES_ADD_SETTLED(o: Origin.ChannelRelayedHot, htlc, fulfill: HtlcResult.Fulfill)) =>
context.log.debug("relaying fulfill to upstream")
Metrics.relaySettleFulfill(confidence)
val cmd = CMD_FULFILL_HTLC(o.originHtlcId, fulfill.paymentPreimage, commit = true)
context.system.eventStream ! EventStream.Publish(ChannelPaymentRelayed(o.amountIn, o.amountOut, htlc.paymentHash, o.originChannelId, htlc.channelId, startedAt, TimestampMilli.now()))
recordRelayDuration(isSuccess = true)
safeSendAndStop(o.originChannelId, cmd)

case WrappedAddResponse(RES_ADD_SETTLED(o: Origin.ChannelRelayedHot, _, fail: HtlcResult.Fail)) =>
context.log.debug("relaying fail to upstream")
Metrics.relaySettleFail(confidence)
Metrics.recordPaymentRelayFailed(Tags.FailureType.Remote, Tags.RelayType.Channel)
val cmd = translateRelayFailure(o.originHtlcId, fail)
recordRelayDuration(isSuccess = false)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2023 ACINQ SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package fr.acinq.eclair.reputation

import fr.acinq.eclair.{MilliSatoshiLong, TimestampMilli}
import fr.acinq.eclair.reputation.Reputation.ReputationConfig
import org.scalatest.funsuite.AnyFunSuite
import org.scalactic.Tolerance.convertNumericToPlusOrMinusWrapper

import java.util.UUID
import scala.concurrent.duration.DurationInt

class ReputationSpec extends AnyFunSuite {
val (uuid1, uuid2, uuid3, uuid4, uuid5, uuid6, uuid7) = (UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID())

test("basic") {
var r = Reputation.init(ReputationConfig(1000000000 msat, 30 seconds))
r = r.attempt(uuid1, 10000 msat)
assert(r.confidence() == 0)
r = r.record(uuid1, isSuccess = true)
r = r.attempt(uuid2, 10000 msat)
assert(r.confidence() == 0.5)
r = r.attempt(uuid3, 10000 msat)
assert(r.confidence() === 0.333 +- 0.001)
r = r.record(uuid2, isSuccess = true)
r = r.record(uuid3, isSuccess = true)
r = r.attempt(uuid4, 1 msat)
assert(r.confidence() === 1.0 +- 0.001)
r = r.attempt(uuid5, 90000 msat)
assert(r.confidence() === 0.25 +- 0.001)
r = r.attempt(uuid6, 10000 msat)
assert(r.confidence() === (3.0 / 13) +- 0.001)
r = r.cancel(uuid5)
assert(r.confidence() === 0.75 +- 0.001)
r = r.record(uuid6, isSuccess = false)
assert(r.confidence() === 0.75 +- 0.001)
r = r.attempt(uuid7, 10000 msat)
assert(r.confidence() === 0.6 +- 0.001)
}

test("long HTLC") {
var r = Reputation.init(ReputationConfig(1000000000 msat, 1 second))
r = r.attempt(uuid1, 100000 msat)
assert(r.confidence() == 0)
r = r.record(uuid1, isSuccess = true)
assert(r.confidence() == 1)
r = r.attempt(uuid2, 1000 msat, TimestampMilli(0))
assert(r.confidence(TimestampMilli(0)) === 0.99 +- 0.001)
assert(r.confidence(TimestampMilli(0) + 100.seconds) == 0.5)
r = r.record(uuid2, isSuccess = false, now = TimestampMilli(0) + 100.seconds)
assert(r.confidence() == 0.5)
}
}

0 comments on commit 7d53a40

Please sign in to comment.