diff --git a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/automation/RewardComputationTrigger.scala b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/automation/RewardComputationTrigger.scala index 0d9f1090f1..e98a4c7c7d 100644 --- a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/automation/RewardComputationTrigger.scala +++ b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/automation/RewardComputationTrigger.scala @@ -51,6 +51,8 @@ class RewardComputationTrigger( "current_migration_id" -> updateHistory.domainMigrationId.toString ) ) + private val mcDryRun = MetricsContext.apply("dryRun" -> "true") + private val mcNonDryRun = MetricsContext.apply("dryRun" -> "false") override def retrieveTasks()(implicit tc: TraceContext @@ -65,6 +67,12 @@ class RewardComputationTrigger( // - rounds where the rewards are already computed // - rounds with incomplete activity candidates <- rewardsReferenceStore.listActiveCalculateRewardsV2() + _ = rewardMetrics.calculateRewardsContractCount.updateValue( + candidates.count(_.payload.dryRun) + )(mcDryRun) + _ = rewardMetrics.calculateRewardsContractCount.updateValue( + candidates.count(!_.payload.dryRun) + )(mcNonDryRun) candidateRounds = candidates.map(_.payload.round.number.toLong).distinct.sorted computedRounds <- appRewardsStore.roundsWithComputedRewards(candidateRounds) afterComputedFilter = candidateRounds.filterNot(computedRounds.contains) diff --git a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/metrics/RewardComputationMetrics.scala b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/metrics/RewardComputationMetrics.scala index 113a3bd983..78ee19849e 100644 --- a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/metrics/RewardComputationMetrics.scala +++ b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/metrics/RewardComputationMetrics.scala @@ -4,7 +4,7 @@ package org.lfdecentralizedtrust.splice.scan.metrics import com.daml.metrics.api.MetricHandle.{Gauge, LabeledMetricsFactory} -import com.daml.metrics.api.MetricQualification.Traffic +import com.daml.metrics.api.MetricQualification.{Saturation, Traffic} import com.daml.metrics.api.{MetricInfo, MetricName, MetricsContext} import org.lfdecentralizedtrust.splice.environment.SpliceMetrics import org.lfdecentralizedtrust.splice.scan.store.db.DbScanAppRewardsStore.RewardComputationSummary @@ -51,6 +51,16 @@ class RewardComputationMetrics(metricsFactory: LabeledMetricsFactory)(implicit 0L, )(metricsContext) + val calculateRewardsContractCount: Gauge[Int] = + metricsFactory.gauge( + MetricInfo( + name = prefix :+ "calculate_rewards_v2" :+ "active_contracts", + summary = "The number of active CalculateRewardsV2 contracts", + Saturation, + ), + initial = -1, + )(metricsContext) + def record(summary: RewardComputationSummary): Unit = { activePartiesCount.updateValue(summary.activePartiesCount) activityRecordsCount.updateValue(summary.activityRecordsCount) @@ -63,5 +73,6 @@ class RewardComputationMetrics(metricsFactory: LabeledMetricsFactory)(implicit activityRecordsCount.close() rewardedPartiesCount.close() batchesCreatedCount.close() + calculateRewardsContractCount.close() } } diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/RewardProcessingMetrics.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/RewardProcessingMetrics.scala index 8c5b0bc79b..de938e7370 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/RewardProcessingMetrics.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/RewardProcessingMetrics.scala @@ -4,13 +4,13 @@ package org.lfdecentralizedtrust.splice.sv.automation import com.daml.metrics.api.{MetricInfo, MetricName, MetricsContext} -import com.daml.metrics.api.MetricHandle.{LabeledMetricsFactory, Meter, Timer} -import com.daml.metrics.api.MetricQualification.{Latency, Traffic} +import com.daml.metrics.api.MetricHandle.{Gauge, LabeledMetricsFactory, Meter, Timer} +import com.daml.metrics.api.MetricQualification.{Latency, Traffic, Saturation} import org.lfdecentralizedtrust.splice.environment.SpliceMetrics class RewardProcessingMetrics(metricsFactory: LabeledMetricsFactory)( metricsContext: MetricsContext -) { +) extends AutoCloseable { private val prefix: MetricName = SpliceMetrics.MetricsPrefix @@ -57,4 +57,18 @@ class RewardProcessingMetrics(metricsFactory: LabeledMetricsFactory)( qualification = Traffic, ) )(metricsContext) + + val calculateRewardsContractCount: Gauge[Int] = + metricsFactory.gauge( + MetricInfo( + name = prefix :+ "calculate_rewards_v2" :+ "active_contracts", + summary = "The number of active CalculateRewardsV2 contracts", + Saturation, + ), + initial = -1, + )(metricsContext) + + override def close() = { + calculateRewardsContractCount.close() + } } diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/confirmation/CalculateRewardsTrigger.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/confirmation/CalculateRewardsTrigger.scala index cadb4e13c9..3d50888316 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/confirmation/CalculateRewardsTrigger.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/confirmation/CalculateRewardsTrigger.scala @@ -31,6 +31,7 @@ import org.lfdecentralizedtrust.splice.util.AssignedContract import org.lfdecentralizedtrust.splice.util.PrettyInstances.* import com.daml.metrics.api.MetricsContext import com.daml.metrics.api.MetricsContext.Implicits.empty +import com.digitalasset.canton.lifecycle.{AsyncOrSyncCloseable, SyncCloseable} import com.digitalasset.canton.logging.pretty.{Pretty, PrettyPrinting} import com.digitalasset.canton.tracing.TraceContext import io.grpc.Status @@ -62,9 +63,10 @@ abstract class CalculateRewardsTriggerBase( override def retrieveTasks()(implicit tc: TraceContext): Future[Seq[Task]] = for { // These are ordered by round, so we process the oldest first calculateRewards <- store.listCalculateRewardsV2() + calculateRewardsForThisTrigger = calculateRewards.filter(_.payload.dryRun == isDryRun) + _ = rewardMetrics.calculateRewardsContractCount.updateValue(calculateRewardsForThisTrigger.size) confirmedCids <- listConfirmedCalculateRewardsCids() - } yield calculateRewards - .filter(_.payload.dryRun == isDryRun) + } yield calculateRewardsForThisTrigger .filterNot(c => confirmedCids.contains(c.contractId)) .map(Task(_)) @@ -192,6 +194,14 @@ abstract class CalculateRewardsTriggerBase( ) ) + override def closeAsync(): Seq[AsyncOrSyncCloseable] = { + Seq( + SyncCloseable( + "rewardMetrics", + rewardMetrics.close(), + ) + ) + } } class CalculateRewardsTrigger(