reporting app
parent
18fa379dbe
commit
9655a1b786
|
@ -20,7 +20,7 @@ final class Env(config: Config, system: ActorSystem, isServer: Boolean) {
|
|||
)), name = RouterName)
|
||||
|
||||
loginfo("[boot] Preloading modules")
|
||||
(Env.site, Env.game, Env.setup, Env.game, Env.gameSearch, Env.team,
|
||||
(Env.site, Env.game, Env.ai, Env.setup, Env.round, Env.gameSearch, Env.team,
|
||||
Env.teamSearch, Env.forumSearch, Env.message, Env.socket)
|
||||
|
||||
if (Env.ai.isServer) println("Running as AI server")
|
||||
|
|
|
@ -1,44 +1,36 @@
|
|||
package controllers
|
||||
|
||||
import play.api.mvc._
|
||||
import play.api.libs.Comet
|
||||
import play.api.libs.json._
|
||||
import akka.pattern.ask
|
||||
|
||||
import lila.app._
|
||||
import lila.monitor.actorApi._
|
||||
import lila.socket.actorApi.GetNbMembers
|
||||
// import lila.monitor._
|
||||
import makeTimeout.short
|
||||
|
||||
object Monitor extends LilaController {
|
||||
|
||||
// private def reporting = env.monitor.reporting
|
||||
// private def usernameMemo = env.user.usernameMemo
|
||||
// private def userRepo = env.user.userRepo
|
||||
// private def gameRepo = env.game.gameRepo
|
||||
private def env = Env.monitor
|
||||
|
||||
def index = TODO
|
||||
// Action {
|
||||
// Ok(views.html.monitor.monitor())
|
||||
// }
|
||||
def index = Action {
|
||||
Ok(views.html.monitor.monitor())
|
||||
}
|
||||
|
||||
// def websocket = WebSocket.async[JsValue] { implicit req ⇒
|
||||
// env.monitor.socket.join(uidOption = get("sri", req))
|
||||
// }
|
||||
def websocket = WebSocket.async[JsValue] { implicit req ⇒
|
||||
get("sri", req) zmap env.socketHandler.join
|
||||
}
|
||||
|
||||
// def status = Open { implicit ctx ⇒
|
||||
// Async {
|
||||
// import lila.common.Futuristic.ioToFuture
|
||||
// (~get("key") match {
|
||||
// case "elo" ⇒
|
||||
// userRepo.idsAverageElo(usernameMemo.keys).toFuture zip
|
||||
// gameRepo.recentAverageElo(5).toFuture map {
|
||||
// case (users, (rated, casual)) ⇒ List(users, rated, casual) mkString " "
|
||||
// }
|
||||
// case "moves" ⇒ (reporting ? GetNbMoves).mapTo[Int]
|
||||
// case "players" ⇒ (reporting ? GetNbMembers).mapTo[Int] map { "%d %d".format(_, usernameMemo.preciseCount) }
|
||||
// case _ ⇒ (reporting ? GetStatus).mapTo[String]
|
||||
// }) map { x ⇒ Ok(x.toString) }
|
||||
// }
|
||||
// }
|
||||
def status = Open { implicit ctx ⇒
|
||||
(~get("key") match {
|
||||
case "elo" ⇒
|
||||
lila.user.UserRepo.idsAverageElo(Env.user.usernameMemo.keys) zip
|
||||
lila.game.GameRepo.recentAverageElo(5) map {
|
||||
case (users, (rated, casual)) ⇒ List(users, rated, casual) mkString " "
|
||||
}
|
||||
case "moves" ⇒ (env.reporting ? GetNbMoves).mapTo[Int]
|
||||
case "players" ⇒ (env.reporting ? GetNbMembers).mapTo[Int] map { "%d %d".format(_, Env.user.usernameMemo.count) }
|
||||
case _ ⇒ (env.reporting ? GetStatus).mapTo[String]
|
||||
}) map { x ⇒ Ok(x.toString) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,10 +177,8 @@ POST /import controllers.Importer.sendGame
|
|||
|
||||
# Monitor
|
||||
GET /monitor controllers.Monitor.index
|
||||
# GET /monitor/socket controllers.Monitor.websocket
|
||||
# GET /monitor/players controllers.Monitor.nbPlayers
|
||||
# GET /monitor/mps controllers.Monitor.nbMoves
|
||||
# GET /monitor/status controllers.Monitor.status
|
||||
GET /monitor/socket controllers.Monitor.websocket
|
||||
GET /monitor/status controllers.Monitor.status
|
||||
|
||||
# Misc
|
||||
POST /cli controllers.Cli.command
|
||||
|
|
|
@ -2,7 +2,7 @@ package lila.ai
|
|||
|
||||
import lila.common.PimpedConfig._
|
||||
|
||||
import akka.actor.{ ActorRef, ActorSystem }
|
||||
import akka.actor._
|
||||
import com.typesafe.config.Config
|
||||
|
||||
final class Env(
|
||||
|
@ -17,6 +17,7 @@ final class Env(
|
|||
val StockfishExecPath = config getString "stockfish.exec_path"
|
||||
val StockfishPlayUrl = config getString "stockfish.play.url"
|
||||
val StockfishAnalyseUrl = config getString "stockfish.analyse.url"
|
||||
val ActorName = config getString "actor.name"
|
||||
}
|
||||
import settings._
|
||||
|
||||
|
@ -32,6 +33,13 @@ final class Env(
|
|||
|
||||
def isServer = IsServer
|
||||
|
||||
// api actor
|
||||
system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
case lila.hub.actorApi.ai.Ping ⇒ sender ! clientPing
|
||||
}
|
||||
}), name = ActorName)
|
||||
|
||||
{
|
||||
import scala.concurrent.duration._
|
||||
|
||||
|
@ -39,7 +47,7 @@ final class Env(
|
|||
clientDiagnose
|
||||
}
|
||||
|
||||
scheduler.once(5 millis) { clientDiagnose }
|
||||
scheduler.once(10 millis) { clientDiagnose }
|
||||
}
|
||||
|
||||
private lazy val stockfishAi = new stockfish.Ai(
|
||||
|
|
|
@ -3,6 +3,7 @@ package lila.game
|
|||
import com.typesafe.config.Config
|
||||
import lila.common.PimpedConfig._
|
||||
import akka.actor._
|
||||
import akka.pattern.pipe
|
||||
|
||||
final class Env(
|
||||
config: Config,
|
||||
|
@ -21,6 +22,7 @@ final class Env(
|
|||
val CollectionPgn = config getString "collection.pgn"
|
||||
val JsPathRaw = config getString "js_path.raw"
|
||||
val JsPathCompiled = config getString "js_path.compiled"
|
||||
val ActorName = config getString "actor.name"
|
||||
}
|
||||
import settings._
|
||||
|
||||
|
@ -50,6 +52,13 @@ final class Env(
|
|||
// load captcher actor
|
||||
system.actorOf(Props(new Captcher), name = CaptcherName)
|
||||
|
||||
// api actor
|
||||
system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
case lila.hub.actorApi.game.Count ⇒ cached.nbGames pipeTo sender
|
||||
}
|
||||
}), name = ActorName)
|
||||
|
||||
{
|
||||
import scala.concurrent.duration._
|
||||
|
||||
|
|
|
@ -7,8 +7,11 @@ import lila.user.User
|
|||
import lila.db.api._
|
||||
import lila.db.Implicits._
|
||||
import tube.gameTube
|
||||
import lila.common.PimpedJson._
|
||||
|
||||
import play.api.libs.json._
|
||||
import play.modules.reactivemongo.json.ImplicitBSONHandlers.JsObjectWriter
|
||||
import play.modules.reactivemongo.json.BSONFormats.toJSON
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import org.scala_tools.time.Imports._
|
||||
|
@ -19,8 +22,7 @@ object GameRepo {
|
|||
|
||||
type ID = String
|
||||
|
||||
import Game._
|
||||
import Game.ShortFields._
|
||||
import Game._, ShortFields._
|
||||
|
||||
def game(gameId: ID): Fu[Option[Game]] = $find byId gameId
|
||||
|
||||
|
@ -140,35 +142,39 @@ object GameRepo {
|
|||
$count(Json.obj(createdAt -> ($gte(from) ++ $lt(to))))
|
||||
}
|
||||
|
||||
// def recentAverageElo(minutes: Int): Fu[(Int, Int)] = io {
|
||||
// val result = collection.mapReduce(
|
||||
// mapFunction = """function() {
|
||||
// emit(!!this.ra, this.p);
|
||||
// }""",
|
||||
// reduceFunction = """function(rated, values) {
|
||||
// var sum = 0, nb = 0;
|
||||
// values.forEach(function(game) {
|
||||
// if(typeof game[0] != "undefined") {
|
||||
// game.forEach(function(player) {
|
||||
// if(player.elo) {
|
||||
// sum += player.elo;
|
||||
// ++nb;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// return nb == 0 ? nb : Math.round(sum / nb);
|
||||
// }""",
|
||||
// output = MapReduceInlineOutput,
|
||||
// query = Some {
|
||||
// (createdAt $gte (DateTime.now - minutes.minutes)) ++ ("p.elo" $exists true)
|
||||
// }
|
||||
// )
|
||||
// (for {
|
||||
// ratedRow ← result.hasNext option result.next
|
||||
// rated ← ratedRow.getAs[Double]("value")
|
||||
// casualRow ← result.hasNext option result.next
|
||||
// casual ← casualRow.getAs[Double]("value")
|
||||
// } yield rated.toInt -> casual.toInt) | (0, 0)
|
||||
// }
|
||||
def recentAverageElo(minutes: Int): Fu[(Int, Int)] = {
|
||||
val command = MapReduce(
|
||||
collectionName = gameTube.coll.name,
|
||||
mapFunction = """function() {
|
||||
emit(!!this.ra, this.p);
|
||||
}""",
|
||||
reduceFunction = """function(rated, values) {
|
||||
var sum = 0, nb = 0;
|
||||
values.forEach(function(game) {
|
||||
if(typeof game[0] != "undefined") {
|
||||
game.forEach(function(player) {
|
||||
if(player.elo) {
|
||||
sum += player.elo;
|
||||
++nb;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return nb == 0 ? nb : Math.round(sum / nb);
|
||||
}""",
|
||||
query = Some(JsObjectWriter write Json.obj(
|
||||
createdAt -> $gte(DateTime.now - minutes.minutes),
|
||||
"p.elo" -> $exists(true)
|
||||
))
|
||||
)
|
||||
gameTube.coll.db.command(command) map { res ⇒
|
||||
toJSON(res).pp.arr("results").pp.flatMap(_.apply(0) int "value")
|
||||
} map (~_) inject (0, 0)
|
||||
// (for {
|
||||
// ratedRow ← result.hasNext option result.next
|
||||
// rated ← ratedRow.getAs[Double]("value")
|
||||
// casualRow ← result.hasNext option result.next
|
||||
// casual ← casualRow.getAs[Double]("value")
|
||||
// } yield rated.toInt -> casual.toInt) | (0, 0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ final class Env(config: Config, system: ActorSystem) {
|
|||
private val SocketHubTimeout = config duration "socket.hub.timeout"
|
||||
|
||||
object actor {
|
||||
val game = actorFor("game.actor")
|
||||
val gameIndexer = actorFor("game.indexer")
|
||||
val renderer = actorFor("renderer")
|
||||
val captcher = actorFor("captcher")
|
||||
|
@ -29,6 +30,7 @@ final class Env(config: Config, system: ActorSystem) {
|
|||
val lobby = socketFor("lobby")
|
||||
val monitor = socketFor("monitor")
|
||||
val site = socketFor("site")
|
||||
val round = socketFor("round")
|
||||
val hub = system.actorOf(Props(new Broadcast(List(
|
||||
socket.lobby, socket.site
|
||||
))(makeTimeout(SocketHubTimeout))), name = SocketHubName)
|
||||
|
|
|
@ -28,6 +28,10 @@ package lobby {
|
|||
case class Censor(username: String)
|
||||
}
|
||||
|
||||
package game {
|
||||
case object Count
|
||||
}
|
||||
|
||||
package message {
|
||||
case class LichessThread(to: String, subject: String, message: String)
|
||||
}
|
||||
|
@ -44,6 +48,7 @@ package forum {
|
|||
}
|
||||
|
||||
package ai {
|
||||
case object Ping
|
||||
case class Analyse(pgn: String, initialFen: Option[String])
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,11 @@ final class Env(
|
|||
|
||||
lazy val socketHandler = new SocketHandler(socket)
|
||||
|
||||
lazy val reporting = system.actorOf(
|
||||
val reporting = system.actorOf(
|
||||
Props(new Reporting(
|
||||
rpsProvider = rpsProvider,
|
||||
mpsProvider = mpsProvider,
|
||||
socket = socket,
|
||||
db = db,
|
||||
hub = hub
|
||||
)), name = ActorName)
|
||||
|
@ -33,8 +34,8 @@ final class Env(
|
|||
{
|
||||
import scala.concurrent.duration._
|
||||
|
||||
scheduler.message(5 seconds) {
|
||||
reporting -> actorApi.Update
|
||||
scheduler.message(1 seconds) {
|
||||
reporting -> lila.hub.actorApi.monitor.Update
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package lila.monitor
|
||||
|
||||
import actorApi._
|
||||
import lila.socket.actorApi.GetNbMembers
|
||||
import lila.socket.actorApi.{ GetNbMembers, GetNbHubs }
|
||||
import lila.hub.actorApi.monitor._
|
||||
// import round.GetNbHubs
|
||||
|
||||
import akka.actor._
|
||||
import akka.pattern.{ ask, pipe }
|
||||
|
@ -16,6 +15,7 @@ import java.lang.management.ManagementFactory
|
|||
private[monitor] final class Reporting(
|
||||
rpsProvider: RpsProvider,
|
||||
mpsProvider: RpsProvider,
|
||||
socket: ActorRef,
|
||||
db: lila.db.Env,
|
||||
hub: lila.hub.Env) extends Actor {
|
||||
|
||||
|
@ -61,37 +61,35 @@ private[monitor] final class Reporting(
|
|||
|
||||
case GetMonitorData ⇒ sender ! monitorData
|
||||
|
||||
// TODO
|
||||
// case Update ⇒ {
|
||||
// val before = nowMillis
|
||||
// List(
|
||||
// (env.site.hub ? GetNbMembers).mapTo[Int],
|
||||
// (hub.actor.lobby ? GetNbMembers).mapTo[Int],
|
||||
// (env.round.hubMaster ? GetNbHubs).mapTo[Int],
|
||||
// (env.round.hubMaster ? GetNbMembers).mapTo[Int]
|
||||
// ).sequence onComplete {
|
||||
// case Failure(e) ⇒ logwarn("[reporting] " + e.getMessage)
|
||||
// case Success(List(
|
||||
// siteMembers,
|
||||
// lobbyMembers,
|
||||
// gameHubs,
|
||||
// gameMembers)) ⇒ {
|
||||
// latency = (nowMillis - before).toInt
|
||||
// site = SiteSocket(siteMembers)
|
||||
// lobby = LobbySocket(lobbyMembers)
|
||||
// game = GameSocket(gameHubs, gameMembers)
|
||||
// mongoStatus = MongoStatus(mongodb)(mongoStatus)
|
||||
// nbGames = env.game.cached.nbGames
|
||||
// loadAvg = osStats.getSystemLoadAverage.toFloat
|
||||
// nbThreads = threadStats.getThreadCount
|
||||
// memory = memoryStats.getHeapMemoryUsage.getUsed / 1024 / 1024
|
||||
// rps = rpsProvider.rps
|
||||
// mps = mpsProvider.rps
|
||||
// cpu = ((cpuStats.getCpuUsage() * 1000).round / 10.0).toInt
|
||||
// clientAi = env.ai.clientPing
|
||||
// hub ! MonitorData(monitorData)
|
||||
// }
|
||||
// }
|
||||
case Update ⇒ {
|
||||
val before = nowMillis
|
||||
MongoStatus(db.db)(mongoStatus) zip
|
||||
(hub.actor.ai ? lila.hub.actorApi.ai.Ping).mapTo[Option[Int]] zip
|
||||
List((hub.socket.site ? GetNbMembers),
|
||||
(hub.socket.lobby ? GetNbMembers),
|
||||
(hub.socket.round ? GetNbHubs),
|
||||
(hub.socket.round ? GetNbMembers),
|
||||
(hub.actor.game ? lila.hub.actorApi.game.Count)
|
||||
).map(_.mapTo[Int]).sequence onComplete {
|
||||
case Failure(e) ⇒ logwarn("[reporting] " + e.getMessage)
|
||||
case Success(((mongoS, aiPing), List(siteMembers, lobbyMembers, gameHubs, gameMembers, games))) ⇒ {
|
||||
latency = (nowMillis - before).toInt
|
||||
site = SiteSocket(siteMembers)
|
||||
lobby = LobbySocket(lobbyMembers)
|
||||
game = GameSocket(gameHubs, gameMembers)
|
||||
mongoStatus = mongoS
|
||||
nbGames = games
|
||||
loadAvg = osStats.getSystemLoadAverage.toFloat
|
||||
nbThreads = threadStats.getThreadCount
|
||||
memory = memoryStats.getHeapMemoryUsage.getUsed / 1024 / 1024
|
||||
rps = rpsProvider.rps
|
||||
mps = mpsProvider.rps
|
||||
cpu = ((cpuStats.getCpuUsage() * 1000).round / 10.0).toInt
|
||||
clientAi = aiPing
|
||||
socket ! MonitorData(monitorData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def display {
|
||||
|
|
|
@ -11,7 +11,7 @@ private[monitor] final class SocketHandler(socket: ActorRef) {
|
|||
def join(uid: String): Fu[JsSocketHandler] = {
|
||||
|
||||
def controller: Handler.Controller = {
|
||||
case _ =>
|
||||
case _ ⇒
|
||||
}
|
||||
|
||||
Handler(socket, uid, Join(uid)) {
|
||||
|
|
|
@ -12,7 +12,5 @@ case object GetNbMoves
|
|||
case object GetStatus
|
||||
case object GetMonitorData
|
||||
|
||||
case object Update
|
||||
|
||||
case class Join(uid: String)
|
||||
case class MonitorData(data: List[String])
|
||||
|
|
|
@ -35,7 +35,7 @@ final class Env(
|
|||
|
||||
lazy val history = () ⇒ new History(ttl = MessageTtl)
|
||||
|
||||
lazy val socketHub = system.actorOf(Props(new SocketHub(
|
||||
val socketHub = system.actorOf(Props(new SocketHub(
|
||||
makeHistory = history,
|
||||
uidTimeout = UidTimeout,
|
||||
socketTimeout = SocketTimeout,
|
||||
|
|
|
@ -30,6 +30,8 @@ private[round] final class SocketHub(
|
|||
|
||||
case msg @ GameEvents(gameId, events) ⇒ sockets get gameId foreach (_ forward msg)
|
||||
|
||||
case GetNbHubs ⇒ sender ! sockets.size
|
||||
|
||||
case GetSocket(id) ⇒ sender ! {
|
||||
(sockets get id) | {
|
||||
mkSocket(id) ~ { h ⇒ sockets = sockets + (id -> h) }
|
||||
|
|
|
@ -9,6 +9,7 @@ case class Connected[M <: SocketMember](
|
|||
case object Close
|
||||
case object GetNbMembers
|
||||
case class NbMembers(nb: Int)
|
||||
case object GetNbHubs
|
||||
case class Ping(uid: String)
|
||||
case class PingVersion(uid: String, version: Int)
|
||||
case object Broom
|
||||
|
|
|
@ -128,7 +128,7 @@ object UserRepo {
|
|||
|
||||
def idsAverageElo(ids: Iterable[String]): Fu[Int] = {
|
||||
val command = MapReduce(
|
||||
collectionName = tube.userTube.coll.name,
|
||||
collectionName = userTube.coll.name,
|
||||
mapFunction = """function() { emit("e", this.elo); }""",
|
||||
reduceFunction = """function(key, values) {
|
||||
var sum = 0;
|
||||
|
@ -139,14 +139,14 @@ object UserRepo {
|
|||
JsObjectWriter write Json.obj("_id" -> $in(ids map normalize))
|
||||
}
|
||||
)
|
||||
tube.userTube.coll.db.command(command) map { res ⇒
|
||||
userTube.coll.db.command(command) map { res ⇒
|
||||
toJSON(res).arr("results").flatMap(_.apply(0) int "value")
|
||||
} map (~_)
|
||||
}
|
||||
|
||||
def idsSumToints(ids: Iterable[String]): Fu[Int] = {
|
||||
val command = MapReduce(
|
||||
collectionName = tube.userTube.coll.name,
|
||||
collectionName = userTube.coll.name,
|
||||
mapFunction = """function() { emit("e", this.toints); }""",
|
||||
reduceFunction = """function(key, values) {
|
||||
var sum = 0;
|
||||
|
@ -157,7 +157,7 @@ object UserRepo {
|
|||
JsObjectWriter write Json.obj("_id" -> $in(ids map normalize))
|
||||
}
|
||||
)
|
||||
tube.userTube.coll.db.command(command) map { res ⇒
|
||||
userTube.coll.db.command(command) map { res ⇒
|
||||
toJSON(res).arr("results").flatMap(_.apply(0) int "value")
|
||||
} map (~_)
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ case object Start
|
|||
case object Reload
|
||||
case object ReloadPage
|
||||
case object HubTimeout
|
||||
case object GetNbHubs
|
||||
case class StartGame(game: DbGame)
|
||||
case class Joining(userId: String)
|
||||
|
||||
|
|
Loading…
Reference in New Issue