/app/services/agent/AgentStatCollector.scala
https://gitlab.com/winckell.benjamin.isart/xucserver · Scala · 146 lines · 112 code · 34 blank · 0 comment · 0 complexity · 9f68365006d30ff685375077f53b71da MD5 · raw file
- package services.agent
- import akka.actor.FSM.{Transition, SubscribeTransitionCallBack, UnsubscribeTransitionCallBack}
- import akka.actor._
- import play.api.libs.functional.syntax._
- import play.api.libs.json._
- import services.AgentStateFSM.{MContext, MAgentStates, AgentStateContext}
- import services.{CronScheduler, ProductionCronScheduler, XucEventBus}
- import stats.Statistic.{ResetStat}
- import us.theatr.akka.quartz.AddCronSchedule
- import xivo.events.AgentState
- import xivo.events.AgentState.AgentOnPause
- import xivo.models.Agent
- import xivo.xucstats.XucStatsConfig
- object AgentStatCollector {
- def props(id: Agent.Id, agentFSM: ActorRef): Props = Props(new AgentStatCollector(id, agentFSM))
- }
- trait XucLogging extends ActorLogging {
- this: Actor =>
- var logPrefix = ""
- private def logMessage(msg: String): String = s"[$logPrefix] $msg"
- object xlog {
- def debug(msg: String) = log.debug(logMessage(msg))
- def info(msg: String) = log.info(logMessage(msg))
- def error(msg: String) = log.error(logMessage(msg))
- def warning(msg: String) = log.warning(logMessage(msg))
- }
- }
- case class Statistic(name:String, value: StatValue)
- object Statistic {
- implicit val StatisticWrites = (
- (__ \ "name").write[String] and
- (__ \ "value").write[StatValue]
- )(unlift(Statistic.unapply))
- }
- case class AgentStatistic(agentId: Agent.Id, statistics: List[Statistic])
- object AgentStatistic {
- implicit val AgentStatisticWrites = (
- (__ \ "id").write[Long] and
- (__ \ "statistics").write[List[Statistic]]) (unlift(AgentStatistic.unapply))
- }
- case class AgentTransition(stateFrom: MAgentStates, contextFrom: MContext, stateTo: MAgentStates, contextTo: MContext)
- trait StatRegistrar {
- private var agentStatistics:Map[String, AgentStatCalculator] = Map()
- def getStats():List[AgentStatCalculator] = agentStatistics.values.toList
- def getAgentStatCalculatorsByEvent: List[AgentStatCalculatorByEvent] = getStats.flatMap {case s: AgentStatCalculatorByEvent => Some(s); case _ => None}
- def getAgentStatCalculatorsByStatValue: List[AgentStatCalculatorByStatValue] =
- getStats.flatMap {case s: AgentStatCalculatorByStatValue => Some(s); case _ => None}
- def getAgentStatCalculatorsByTransition: List[AgentStatCalculatorByTransition] =
- getStats.flatMap {case s: AgentStatCalculatorByTransition => Some(s); case _ => None}
- protected[agent] def registerStatistic(agentStatCalculator: AgentStatCalculator) = agentStatistics += (agentStatCalculator.name-> agentStatCalculator)
- def register(astate: AgentState, statCollector: StatCollector) = astate match {
- case AgentOnPause(_,_,_,_,Some(cause)) => agentStatistics.get(cause) match {
- case None => registerStatistic(AgentPausedTotalTimeWithCause(cause, statCollector))
- case _ =>
- }
- case _ =>
- }
- }
- trait StatDefinitions {
- this: StatRegistrar with StatCollector =>
- registerStatistic(LoginDateTime(LoginDateTime.name, this))
- registerStatistic(LogoutDateTime(LogoutDateTime.name, this))
- registerStatistic(AgentReadyTotalTime(AgentReadyTotalTime.name, this))
- registerStatistic(AgentPausedTotalTime(AgentPausedTotalTime.name, this))
- registerStatistic(AgentWrapupTotalTime(AgentWrapupTotalTime.name, this))
- registerStatistic(AgentInboundTotalCalls(AgentInboundTotalCalls.name, this))
- registerStatistic(AgentInboundAnsweredCalls(AgentInboundAnsweredCalls.name, this))
- registerStatistic(AgentInboundUnansweredCalls(AgentInboundUnansweredCalls.name, this))
- registerStatistic(AgentInboundPercentUnansweredCalls(AgentInboundPercentUnansweredCalls.name, this))
- registerStatistic(AgentInboundAverageCallTime(AgentInboundAverageCallTime.name, this))
- registerStatistic(AgentInboundTotalCallTime(AgentInboundTotalCallTime.name, this))
- registerStatistic(AgentOutboundTotalCalls(AgentOutboundTotalCalls.name, this))
- registerStatistic(AgentOutboundTotalCallTime(AgentOutboundTotalCallTime.name, this))
- }
- trait StatCollector {
- this: AgentStatCollector =>
- def onStatCalculated(name: String, statValue: StatValue) = {
- xlog.debug(s"publishing $name : $statValue")
- eventBus.publish(AgentStatistic(id, List(Statistic(name, statValue))))
- }
- }
- class AgentStatCollector( val id: Agent.Id, agentFSM: ActorRef, val eventBus: XucEventBus = XucEventBus.bus) extends Actor
- with StatCollector with ProductionCronScheduler with XucLogging with StatRegistrar with StatDefinitions{
- this: CronScheduler =>
- logPrefix = s"$id"
- private var agentStatistics:Map[String, AgentStatCalculator] = Map()
- xlog.info(s"$self starting")
- eventBus.subscribe(self,XucEventBus.agentEventTopic(id))
- eventBus.subscribe(self,XucEventBus.agentTransitionTopic(id))
- eventBus.subscribe(self,XucEventBus.statEventTopic(id))
- override def preStart() {
- log.info(s"setting schedule to ${XucStatsConfig.resetSchedule}")
- scheduler ! AddCronSchedule(self, XucStatsConfig.resetSchedule, ResetStat)
- }
- def receive = {
- case state: AgentState =>
- xlog.debug(s"processing agent state : $state")
- register(state,this)
- getAgentStatCalculatorsByEvent foreach(_.processEvent(state))
- case t: AgentTransition =>
- xlog.debug(s"processing agentFSM transition : ${t.stateFrom}, ${t.contextFrom}, ${t.stateTo}, ${t.contextTo}")
- getAgentStatCalculatorsByTransition foreach(_.processTransition(t))
- case stats: AgentStatistic =>
- xlog.debug(s"processing statistics: $stats")
- getAgentStatCalculatorsByStatValue foreach(_.processStat(stats))
- case ResetStat =>
- xlog.debug("reset statistics")
- getStats foreach(_.reset())
- case unk =>
- xlog.debug(s"unkown message received $unk")
- }
- }