| package controllers |
| |
| import java.util.concurrent.TimeUnit |
| |
| import play.api.mvc.{Action, Controller, Result, Request, BodyParser, AnyContent} |
| import play.api.Logger |
| import scala.concurrent.ExecutionContext |
| import scala.concurrent.Future |
| import com.daumkakao.s2graph.rest.actors._ |
| import com.daumkakao.s2graph.rest.config.{Instrumented, Config} |
| import com.codahale.metrics.Timer |
| |
| object ApplicationController extends Controller with Instrumented { |
| |
| var isHealthy = true |
| val useKeepAlive = Config.USE_KEEP_ALIVE |
| var connectionOption = CONNECTION -> "Keep-Alive" |
| var keepAliveOption = "Keep-Alive" -> "timeout=5, max=100" |
| |
| consoleReporter.start(10, TimeUnit.SECONDS) |
| |
| def updateHealthCheck(isHealthy: Boolean) = Action { request => |
| this.isHealthy = isHealthy |
| Ok(this.isHealthy + "\n") |
| } |
| |
| def healthCheck() = withHeader { request => |
| if (isHealthy) Ok.withHeaders(CONNECTION -> "close") |
| else NotFound.withHeaders(CONNECTION -> "close") |
| } |
| |
| |
| def toLogMessage[A](request: Request[A], result: Result)(startedAt: Long): String = { |
| val duration = System.currentTimeMillis() - startedAt |
| val key = s"${request.method} ${request.uri} ${result.header.status.toString}" |
| val ctx = getOrElseUpdateMetric[Timer](key)(metricRegistry.timer(key)).time() |
| try { |
| if (!Config.IS_WRITE_SERVER) { |
| s"${request.method} ${request.uri} took ${duration} ms ${result.header.status} ${request.body}" |
| } else { |
| s"${request.method} ${request.uri} took ${duration} ms ${result.header.status}" |
| } |
| } finally { |
| ctx.stop() |
| } |
| } |
| |
| def withHeaderAsync(block: Request[AnyContent] => Future[Result])(implicit ex: ExecutionContext) = { |
| Action.async { request => |
| val startedAt = System.currentTimeMillis() |
| block(request).map { r => |
| Logger.info(toLogMessage(request, r)(startedAt)) |
| if (useKeepAlive) if (isHealthy) r.withHeaders(connectionOption, keepAliveOption) else r.withHeaders(CONNECTION -> "close") |
| else r.withHeaders(CONNECTION -> "close") |
| } |
| } |
| } |
| |
| def withHeaderAsync[A](bodyParser: BodyParser[A])(block: Request[A] => Future[Result])(implicit ex: ExecutionContext) = { |
| Action.async(bodyParser) { request => |
| val startedAt = System.currentTimeMillis() |
| block(request).map { r => |
| Logger.info(toLogMessage(request, r)(startedAt)) |
| if (useKeepAlive) if (isHealthy) r.withHeaders(connectionOption, keepAliveOption) else r.withHeaders(CONNECTION -> "close") |
| else r.withHeaders(CONNECTION -> "close") |
| } |
| } |
| } |
| |
| def withHeader[A](bodyParser: BodyParser[A])(block: Request[A] => Result) = { |
| Action(bodyParser) { request: Request[A] => |
| val startedAt = System.currentTimeMillis() |
| val r = block(request) |
| Logger.info(toLogMessage(request, r)(startedAt)) |
| if (useKeepAlive) if (isHealthy) r.withHeaders(connectionOption, keepAliveOption) else r.withHeaders(CONNECTION -> "close") |
| else r.withHeaders(CONNECTION -> "close") |
| } |
| } |
| |
| def withHeader(block: Request[AnyContent] => Result) = { |
| Action { request: Request[AnyContent] => |
| val startedAt = System.currentTimeMillis() |
| val r = block(request) |
| Logger.info(toLogMessage(request, r)(startedAt)) |
| if (useKeepAlive) if (isHealthy) r.withHeaders(connectionOption, keepAliveOption) else r.withHeaders(CONNECTION -> "close") |
| else r.withHeaders(CONNECTION -> "close") |
| } |
| |
| } |
| } |