more puzzle monitoring
parent
d30c04c95c
commit
1a0ad20efa
|
@ -20,6 +20,16 @@ object Chronometer {
|
|||
this
|
||||
}
|
||||
|
||||
def mon(path: lila.mon.TimerPath) = {
|
||||
path(lila.mon).record(nanos).unit
|
||||
this
|
||||
}
|
||||
|
||||
def monValue(path: A => lila.mon.TimerPath) = {
|
||||
path(result)(lila.mon).record(nanos).unit
|
||||
this
|
||||
}
|
||||
|
||||
def pp: A = {
|
||||
println(s"chrono $showDuration")
|
||||
result
|
||||
|
@ -45,16 +55,12 @@ object Chronometer {
|
|||
}
|
||||
|
||||
def mon(path: lila.mon.TimerPath) = {
|
||||
lap dforeach { l =>
|
||||
path(lila.mon).record(l.nanos).unit
|
||||
}
|
||||
lap dforeach { _.mon(path).unit }
|
||||
this
|
||||
}
|
||||
|
||||
def monValue(path: A => lila.mon.TimerPath) = {
|
||||
lap dforeach { l =>
|
||||
path(l.result)(lila.mon).record(l.nanos).unit
|
||||
}
|
||||
lap dforeach { _.monValue(path).unit }
|
||||
this
|
||||
}
|
||||
|
||||
|
@ -67,6 +73,11 @@ object Chronometer {
|
|||
def pp(msg: String): Fu[A] = lap.dmap(_ pp msg)
|
||||
def ppIfGt(msg: String, duration: FiniteDuration): Fu[A] = lap.dmap(_.ppIfGt(msg, duration))
|
||||
|
||||
def tap(f: Lap[A] => Unit) = {
|
||||
lap dforeach f
|
||||
this
|
||||
}
|
||||
|
||||
def result = lap.dmap(_.result)
|
||||
}
|
||||
|
||||
|
|
|
@ -420,13 +420,15 @@ object mon {
|
|||
object puzzle {
|
||||
object selector {
|
||||
object user {
|
||||
def puzzle(theme: String, retries: Int) =
|
||||
timer("puzzle.selector.user.puzzle").withTags(Map("theme" -> theme, "retries" -> retries))
|
||||
def puzzle(theme: String, retries: Int, vote: Int) =
|
||||
timer("puzzle.selector.user.puzzle").withTags(
|
||||
Map("theme" -> theme, "retries" -> retries, "vote" -> vote)
|
||||
)
|
||||
def batch(nb: Int) = timer("puzzle.selector.user.batch").withTag("nb", nb)
|
||||
}
|
||||
object anon {
|
||||
val puzzle = timer("puzzle.selector.anon.puzzle").withoutTags()
|
||||
def batch(nb: Int) = timer("puzzle.selector.anon.batch").withTag("nb", nb)
|
||||
def puzzle(vote: Int) = timer("puzzle.selector.anon.puzzle").withTag("vote", vote)
|
||||
def batch(nb: Int) = timer("puzzle.selector.anon.batch").withTag("nb", nb)
|
||||
}
|
||||
def nextPuzzleResult(theme: String, difficulty: String, position: Int, result: String) =
|
||||
timer("puzzle.selector.user.puzzle").withTags(
|
||||
|
|
|
@ -25,6 +25,7 @@ private[puzzle] object BsonHandlers {
|
|||
line <- lineStr.split(' ').toList.flatMap(Uci.Move.apply).toNel.toTry("Empty move list?!")
|
||||
glicko <- r.getAsTry[Glicko](glicko)
|
||||
plays <- r.getAsTry[Int](plays)
|
||||
vote <- r.getAsTry[Int](vote)
|
||||
themes <- r.getAsTry[Set[PuzzleTheme.Key]](themes)
|
||||
} yield Puzzle(
|
||||
id = id,
|
||||
|
@ -33,6 +34,7 @@ private[puzzle] object BsonHandlers {
|
|||
line = line,
|
||||
glicko = glicko,
|
||||
plays = plays,
|
||||
vote = vote,
|
||||
themes = themes
|
||||
)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ case class Puzzle(
|
|||
line: NonEmptyList[Uci.Move],
|
||||
glicko: Glicko,
|
||||
plays: Int,
|
||||
vote: Int,
|
||||
themes: Set[PuzzleTheme.Key]
|
||||
) {
|
||||
// ply after "initial move" when we start solving
|
||||
|
|
|
@ -15,13 +15,18 @@ final class PuzzleAnon(colls: PuzzleColls, cacheApi: CacheApi, pathApi: PuzzlePa
|
|||
|
||||
def getOneFor(theme: PuzzleTheme.Key): Fu[Option[Puzzle]] = {
|
||||
pool get theme map ThreadLocalRandom.oneOf
|
||||
}.mon(_.puzzle.selector.anon.puzzle)
|
||||
}.chronometer.tap { lap =>
|
||||
lap.result.foreach { puzzle =>
|
||||
lap.mon(_.puzzle.selector.anon.puzzle(puzzle.vote))
|
||||
}
|
||||
}.result
|
||||
|
||||
def getBatchFor(nb: Int): Fu[Vector[Puzzle]] = {
|
||||
pool get PuzzleTheme.mix.key map (_ take nb)
|
||||
}.mon(_.puzzle.selector.anon.batch(nb))
|
||||
|
||||
private val poolSize = 60
|
||||
private val poolSize = 80
|
||||
private val minPathLength = 10
|
||||
|
||||
private val pool =
|
||||
cacheApi[PuzzleTheme.Key, Vector[Puzzle]](initialCapacity = 64, name = "puzzle.byTheme.anon") {
|
||||
|
@ -29,18 +34,18 @@ final class PuzzleAnon(colls: PuzzleColls, cacheApi: CacheApi, pathApi: PuzzlePa
|
|||
.buildAsyncFuture { theme =>
|
||||
pathApi countPuzzlesByTheme theme flatMap { count =>
|
||||
val tier =
|
||||
if (count > 4000) PuzzleTier.Top
|
||||
else if (count > 1500) PuzzleTier.Good
|
||||
if (count > 5000) PuzzleTier.Top
|
||||
else if (count > 2000) PuzzleTier.Good
|
||||
else PuzzleTier.All
|
||||
val ratingRange: Range =
|
||||
if (count > 9000) 1200 to 1600
|
||||
else if (count > 5000) 1000 to 1800
|
||||
if (count > 9000) 1300 to 1600
|
||||
else if (count > 5000) 1100 to 1800
|
||||
else 0 to 9999
|
||||
colls.path {
|
||||
_.aggregateList(poolSize) { framework =>
|
||||
import framework._
|
||||
Match(pathApi.select(theme, tier, ratingRange)) -> List(
|
||||
Sample(3),
|
||||
Sample(poolSize / minPathLength),
|
||||
Project($doc("puzzleId" -> "$ids", "_id" -> false)),
|
||||
Unwind("puzzleId"),
|
||||
Sample(poolSize),
|
||||
|
|
|
@ -73,7 +73,9 @@ final class PuzzleSessionApi(
|
|||
case PuzzleFound(puzzle) => fuccess(puzzle)
|
||||
}
|
||||
}
|
||||
.mon(_.puzzle.selector.user.puzzle(theme = theme.value, retries = retries))
|
||||
.monValue { puzzle =>
|
||||
_.puzzle.selector.user.puzzle(theme = theme.value, retries = retries, vote = puzzle.vote)
|
||||
}
|
||||
|
||||
private def nextPuzzleResult(user: User, session: PuzzleSession): Fu[NextPuzzleResult] =
|
||||
colls
|
||||
|
|
Loading…
Reference in New Issue