Skip to content

Commit

Permalink
Easy to parse ledger-api-bench-tool logs (#10320)
Browse files Browse the repository at this point in the history
CHANGELOG_BEGIN
CHANGELOG_END
  • Loading branch information
kamil-da authored Jul 26, 2021
1 parent 16ff20c commit 3cedd83
Showing 1 changed file with 63 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,100 @@ object MetricReporter {
object Default extends MetricReporter {

def formattedValues(values: List[MetricValue]): String =
values.map(formattedValue).mkString(", ")
values.map(shortMetricReport).mkString(", ")

def finalReport(
streamName: String,
metrics: List[Metric[_]],
duration: Duration,
): String = {
def indented(str: String, spaces: Int = 4): String = s"${" " * spaces}$str"
val reports = metrics.map { metric =>
val finalValue = formattedValue(metric.finalValue(duration))
def valueFormat(label: String, value: String): String =
s"""[$streamName][final-value] $label: $value"""
def failureFormat(info: String): String = s"""[$streamName][failure] $info"""

val reports = metrics.flatMap { metric =>
val finalValue = metric.finalValue(duration)

val valueLog: Option[String] =
if (includeInFinalReport(metric))
Some(valueFormat(metricName(metric), formattedValue(finalValue)))
else
None

val violatedObjective: Option[String] = metric.violatedObjective
.map { case (objective, value) =>
s"""!!! FAILURE
|!!! OBJECTIVE NOT MET: ${formattedObjective(objective)} (actual: ${formattedValue(
value
)})
|""".stripMargin
val info =
s"${objectiveName(objective)}: required: ${formattedObjectiveValue(objective)}, metered: ${formattedValue(value)}"
failureFormat(info)
}

val all: String = (List(finalValue) ::: violatedObjective.toList)
.map(indented(_))
.mkString("\n")

s"""${metric.name}:
|$all""".stripMargin
valueLog.toList ::: violatedObjective.toList
}

val durationLog = valueFormat("Duration [s]", s"${duration.toMillis.toDouble / 1000}")
val reportWidth = 80
val bar = "=" * reportWidth
s"""
|$bar
|Stream: $streamName
|Total duration: ${duration.toMillis.toDouble / 1000} [s]
| BENCHMARK RESULTS: $streamName
|$bar
|$durationLog
|${reports.mkString("\n")}
|$bar""".stripMargin
}

private def includeInFinalReport(metric: Metric[_]): Boolean = metric match {
case _: ConsumptionSpeedMetric[_] => false
case _: DelayMetric[_] => false
case _ => true
}

private def metricName(metric: Metric[_]): String = metric match {
case _: ConsumptionSpeedMetric[_] => "Consumption speed [-]"
case _: CountRateMetric[_] => "Item rate [item/s]"
case _: DelayMetric[_] => "Mean delay [s]"
case _: SizeMetric[_] => "Size rate [MB/s]"
case _: TotalCountMetric[_] => "Total item count [item]"
}

private def shortMetricReport(value: MetricValue): String =
s"${shortMetricName(value)}: ${formattedValue(value)}"

private def shortMetricName(value: MetricValue): String = value match {
case _: ConsumptionSpeedMetric.Value => "speed [-]"
case _: CountRateMetric.Value => "rate [item/s]"
case _: DelayMetric.Value => "delay [s]"
case _: SizeMetric.Value => "rate [MB/s]"
case _: TotalCountMetric.Value => "count [item]"
}

private def formattedValue(value: MetricValue): String = value match {
case v: ConsumptionSpeedMetric.Value =>
s"speed: ${v.relativeSpeed.map(rounded).getOrElse("-")} [-]"
s"${v.relativeSpeed.map(rounded).getOrElse("-")}"
case v: CountRateMetric.Value =>
s"rate: ${rounded(v.ratePerSecond)} [tx/s]"
s"${rounded(v.ratePerSecond)}"
case v: DelayMetric.Value =>
s"mean delay: ${v.meanDelaySeconds.getOrElse("-")} [s]"
s"${v.meanDelaySeconds.getOrElse("-")}"
case v: SizeMetric.Value =>
s"size rate: ${rounded(v.megabytesPerSecond)} [MB/s]"
s"${rounded(v.megabytesPerSecond)}"
case v: TotalCountMetric.Value =>
s"total count: ${v.totalCount} [tx]"
s"${v.totalCount}"
}

private def formattedObjective(objective: ServiceLevelObjective[_]): String =
private def objectiveName(objective: ServiceLevelObjective[_]): String =
objective match {
case _: MaxDelay =>
s"Maximum record time delay [s]"
case _: MinConsumptionSpeed =>
s"Minimum consumption speed [-]"
}

private def formattedObjectiveValue(objective: ServiceLevelObjective[_]): String =
objective match {
case obj: MaxDelay =>
s"max allowed mean period delay: ${obj.maxDelaySeconds} [s]"
s"${obj.maxDelaySeconds}"
case obj: MinConsumptionSpeed =>
s"min allowed period consumption speed: ${obj.minSpeed} [-]"
s"${obj.minSpeed}"
}

private def rounded(value: Double): String = "%.2f".format(value)
Expand Down

0 comments on commit 3cedd83

Please sign in to comment.