我有一个带有单个流/图的Akka Stream应用程序。我想测量源头的流量并每5秒记录一次,比如在过去的5秒钟内收到3条消息'我试过了,
someOtherFlow
.groupedWithin(Integer.MAX_VALUE, 5 seconds)
.runForeach(seq =>
log.debug(s"received ${seq.length} messages in the last 5 seconds")
)
但它仅在有消息时输出,在有0消息时没有空列表。我也想要0。这可能吗?
答案 0 :(得分:5)
您可以尝试类似
的内容 src
.conflateWithSeed(_ ⇒ 1){ case (acc, _) ⇒ acc + 1 }
.zip(Source.tick(5.seconds, 5.seconds, NotUsed))
.map(_._1)
应该批量你的元素,直到tick发布它们。这受到an example in the docs的启发。
另一方面,如果您需要将其用于监控目的,您可以利用第三方工具实现此目的 - 例如Kamon
答案 1 :(得分:2)
稍微扩展Stefano的答案我创建了以下流程:
def flowRate[T](metric: T => Int = (_: T) => 1, outputDelay: FiniteDuration = 1 second): Flow[T, Double, NotUsed] =
Flow[T]
.conflateWithSeed(metric(_)){ case (acc, x) ⇒ acc + metric(x) }
.zip(Source.tick(outputDelay, outputDelay, NotUsed))
.map(_._1.toDouble / outputDelay.toUnit(SECONDS))
def printFlowRate[T](name: String, metric: T => Int = (_: T) => 1,
outputDelay: FiniteDuration = 1 second): Flow[T, T, NotUsed] =
Flow[T]
.alsoTo(flowRate[T](metric, outputDelay)
.to(Sink.foreach(r => log.info(s"Rate($name): $r"))))
第一个将流量转换为每秒的速率。您可以提供metric
,它为每个通过的对象提供值。假设您想测量字符串流中的字符比率,那么您可以传递_.length
。第二个参数是流速报告之间的延迟(默认为一秒)。
第二个流可用于内联打印流速以进行调试,而无需修改通过流的值。例如
stringFlow
.via(printFlowRate[String]("Char rate", _.length, 10 seconds))
.map(_.toLowercase) // still a string
...
将每隔10秒显示字符的平均速率(每秒)。
答案 2 :(得分:2)
一个示例akka流日志记录。
implicit val system: ActorSystem = ActorSystem("StreamLoggingActorSystem")
implicit val materializer: ActorMaterializer = ActorMaterializer()
implicit val adapter: LoggingAdapter = Logging(system, "customLogger")
implicit val ec: ExecutionContextExecutor = system.dispatcher
def randomInt = Random.nextInt()
val source = Source.repeat(NotUsed).map(_ ⇒ randomInt)
val logger = source
.groupedWithin(Integer.MAX_VALUE, 5.seconds)
.log(s"in the last 5 seconds number of messages received : ", _.size)
.withAttributes(
Attributes.logLevels(
onElement = Logging.WarningLevel,
onFinish = Logging.InfoLevel,
onFailure = Logging.DebugLevel
)
)
val sink = Sink.ignore
val result: Future[Done] = logger.runWith(sink)
result.onComplete{
case Success(_) =>
println("end of stream")
case Failure(_) =>
println("stream ended with failure")
}
源代码为here。