/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

  1. package services.agent
  2. import akka.actor.FSM.{Transition, SubscribeTransitionCallBack, UnsubscribeTransitionCallBack}
  3. import akka.actor._
  4. import play.api.libs.functional.syntax._
  5. import play.api.libs.json._
  6. import services.AgentStateFSM.{MContext, MAgentStates, AgentStateContext}
  7. import services.{CronScheduler, ProductionCronScheduler, XucEventBus}
  8. import stats.Statistic.{ResetStat}
  9. import us.theatr.akka.quartz.AddCronSchedule
  10. import xivo.events.AgentState
  11. import xivo.events.AgentState.AgentOnPause
  12. import xivo.models.Agent
  13. import xivo.xucstats.XucStatsConfig
  14. object AgentStatCollector {
  15. def props(id: Agent.Id, agentFSM: ActorRef): Props = Props(new AgentStatCollector(id, agentFSM))
  16. }
  17. trait XucLogging extends ActorLogging {
  18. this: Actor =>
  19. var logPrefix = ""
  20. private def logMessage(msg: String): String = s"[$logPrefix] $msg"
  21. object xlog {
  22. def debug(msg: String) = log.debug(logMessage(msg))
  23. def info(msg: String) = log.info(logMessage(msg))
  24. def error(msg: String) = log.error(logMessage(msg))
  25. def warning(msg: String) = log.warning(logMessage(msg))
  26. }
  27. }
  28. case class Statistic(name:String, value: StatValue)
  29. object Statistic {
  30. implicit val StatisticWrites = (
  31. (__ \ "name").write[String] and
  32. (__ \ "value").write[StatValue]
  33. )(unlift(Statistic.unapply))
  34. }
  35. case class AgentStatistic(agentId: Agent.Id, statistics: List[Statistic])
  36. object AgentStatistic {
  37. implicit val AgentStatisticWrites = (
  38. (__ \ "id").write[Long] and
  39. (__ \ "statistics").write[List[Statistic]]) (unlift(AgentStatistic.unapply))
  40. }
  41. case class AgentTransition(stateFrom: MAgentStates, contextFrom: MContext, stateTo: MAgentStates, contextTo: MContext)
  42. trait StatRegistrar {
  43. private var agentStatistics:Map[String, AgentStatCalculator] = Map()
  44. def getStats():List[AgentStatCalculator] = agentStatistics.values.toList
  45. def getAgentStatCalculatorsByEvent: List[AgentStatCalculatorByEvent] = getStats.flatMap {case s: AgentStatCalculatorByEvent => Some(s); case _ => None}
  46. def getAgentStatCalculatorsByStatValue: List[AgentStatCalculatorByStatValue] =
  47. getStats.flatMap {case s: AgentStatCalculatorByStatValue => Some(s); case _ => None}
  48. def getAgentStatCalculatorsByTransition: List[AgentStatCalculatorByTransition] =
  49. getStats.flatMap {case s: AgentStatCalculatorByTransition => Some(s); case _ => None}
  50. protected[agent] def registerStatistic(agentStatCalculator: AgentStatCalculator) = agentStatistics += (agentStatCalculator.name-> agentStatCalculator)
  51. def register(astate: AgentState, statCollector: StatCollector) = astate match {
  52. case AgentOnPause(_,_,_,_,Some(cause)) => agentStatistics.get(cause) match {
  53. case None => registerStatistic(AgentPausedTotalTimeWithCause(cause, statCollector))
  54. case _ =>
  55. }
  56. case _ =>
  57. }
  58. }
  59. trait StatDefinitions {
  60. this: StatRegistrar with StatCollector =>
  61. registerStatistic(LoginDateTime(LoginDateTime.name, this))
  62. registerStatistic(LogoutDateTime(LogoutDateTime.name, this))
  63. registerStatistic(AgentReadyTotalTime(AgentReadyTotalTime.name, this))
  64. registerStatistic(AgentPausedTotalTime(AgentPausedTotalTime.name, this))
  65. registerStatistic(AgentWrapupTotalTime(AgentWrapupTotalTime.name, this))
  66. registerStatistic(AgentInboundTotalCalls(AgentInboundTotalCalls.name, this))
  67. registerStatistic(AgentInboundAnsweredCalls(AgentInboundAnsweredCalls.name, this))
  68. registerStatistic(AgentInboundUnansweredCalls(AgentInboundUnansweredCalls.name, this))
  69. registerStatistic(AgentInboundPercentUnansweredCalls(AgentInboundPercentUnansweredCalls.name, this))
  70. registerStatistic(AgentInboundAverageCallTime(AgentInboundAverageCallTime.name, this))
  71. registerStatistic(AgentInboundTotalCallTime(AgentInboundTotalCallTime.name, this))
  72. registerStatistic(AgentOutboundTotalCalls(AgentOutboundTotalCalls.name, this))
  73. registerStatistic(AgentOutboundTotalCallTime(AgentOutboundTotalCallTime.name, this))
  74. }
  75. trait StatCollector {
  76. this: AgentStatCollector =>
  77. def onStatCalculated(name: String, statValue: StatValue) = {
  78. xlog.debug(s"publishing $name : $statValue")
  79. eventBus.publish(AgentStatistic(id, List(Statistic(name, statValue))))
  80. }
  81. }
  82. class AgentStatCollector( val id: Agent.Id, agentFSM: ActorRef, val eventBus: XucEventBus = XucEventBus.bus) extends Actor
  83. with StatCollector with ProductionCronScheduler with XucLogging with StatRegistrar with StatDefinitions{
  84. this: CronScheduler =>
  85. logPrefix = s"$id"
  86. private var agentStatistics:Map[String, AgentStatCalculator] = Map()
  87. xlog.info(s"$self starting")
  88. eventBus.subscribe(self,XucEventBus.agentEventTopic(id))
  89. eventBus.subscribe(self,XucEventBus.agentTransitionTopic(id))
  90. eventBus.subscribe(self,XucEventBus.statEventTopic(id))
  91. override def preStart() {
  92. log.info(s"setting schedule to ${XucStatsConfig.resetSchedule}")
  93. scheduler ! AddCronSchedule(self, XucStatsConfig.resetSchedule, ResetStat)
  94. }
  95. def receive = {
  96. case state: AgentState =>
  97. xlog.debug(s"processing agent state : $state")
  98. register(state,this)
  99. getAgentStatCalculatorsByEvent foreach(_.processEvent(state))
  100. case t: AgentTransition =>
  101. xlog.debug(s"processing agentFSM transition : ${t.stateFrom}, ${t.contextFrom}, ${t.stateTo}, ${t.contextTo}")
  102. getAgentStatCalculatorsByTransition foreach(_.processTransition(t))
  103. case stats: AgentStatistic =>
  104. xlog.debug(s"processing statistics: $stats")
  105. getAgentStatCalculatorsByStatValue foreach(_.processStat(stats))
  106. case ResetStat =>
  107. xlog.debug("reset statistics")
  108. getStats foreach(_.reset())
  109. case unk =>
  110. xlog.debug(s"unkown message received $unk")
  111. }
  112. }