Skip to content
Browse files

Move management-play to it's own repo

  • Loading branch information...
1 parent 2042f7b commit d49fe2c5becb14dc0d59004a15659822774d110d @rtyley rtyley committed
View
4 build.sbt
@@ -1,8 +1,10 @@
import java.util.jar._
+organization in ThisBuild := "com.gu"
+
scalaVersion in ThisBuild := "2.10.0"
-organization in ThisBuild := "com.gu"
+crossScalaVersions in ThisBuild := Seq("2.9.2", "2.10.0")
releaseSettings
View
4 example-play/app/Global.scala
@@ -1,4 +0,0 @@
-import conf.PlayExampleRequestMetrics
-import play.api.mvc.WithFilters
-
-object Global extends WithFilters(PlayExampleRequestMetrics.asFilters: _*)
View
41 example-play/app/conf/Management.scala
@@ -1,41 +0,0 @@
-package conf
-
-import com.gu.management._
-import com.gu.management.logback._
-import play.RequestMetrics
-
-// example of creating your own new page type
-class DummyPage extends ManagementPage {
- val path = "/management/dummy"
- def get(request: HttpRequest) = PlainTextResponse("Hello dummy!")
-}
-
-// switches
-object Switches {
- val omniture = new DefaultSwitch("omniture", "enables omniture java script")
- val takeItDown = new DefaultSwitch("take-it-down", "enable this switch to take the site down", initiallyOn = false)
-
- val all = List(omniture, takeItDown, Healthcheck.switch)
-}
-
-object PlayExampleRequestMetrics extends RequestMetrics.Standard
-
-// properties
-object Properties {
- // If I were using com.gu.configuration I'd comment out the following line
- // val all = new ConfigurationFactory getConfiguration ("music", "conf/arts_music").toString
- val all = "key1=value1\nkey2=value2"
-}
-
-object Management extends com.gu.management.play.Management {
- val applicationName: String = "Example Play App"
- lazy val pages = List(
- new DummyPage(),
- new ManifestPage(),
- new Switchboard(applicationName, Switches.all),
- StatusPage(applicationName, ExceptionCountMetric :: ServerErrorCounter :: ClientErrorCounter :: PlayExampleRequestMetrics.asMetrics),
- new HealthcheckManagementPage(),
- new PropertiesPage(Properties.all),
- new LogbackLevelPage(applicationName)
- )
-}
View
34 example-play/app/controllers/ScalaApp.scala
@@ -1,34 +0,0 @@
-package controllers
-
-import play.api.mvc._
-import com.gu.management.Switch.On
-import play.api.libs.concurrent.Akka
-
-object ScalaApp extends Controller {
- def apply() = Action {
- conf.Switches.takeItDown match {
- case On() => InternalServerError("Temporarily switched off!")
- case _ => Ok("Thank you for invoking this app!")
- }
- }
-
- def exception() = Action {
- throw new Exception("Expected exception.")
- InternalServerError("Unreachable")
- }
-
- def long() = Action {
- Thread.sleep(2000)
- Ok("Slept OK")
- }
-
- def async() = Action {
- Async {
- import play.api.Play.current
- Akka.future {
- Thread.sleep(2000)
- Ok("Slept OK")
- }
- }
- }
-}
View
4 example-play/build.sbt
@@ -1,4 +0,0 @@
-
-publishArtifact := false
-
-seq(scalariformSettings: _*)
View
21 example-play/conf/application.conf
@@ -1,21 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="gAGb;Q______THIS_IS_NOT_A_SECRET_ANYMORE_____CTCA?ZcxlvS/GL^aDK"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory.
-
-logger.root=INFO
-logger.play=INFO
-logger.application=DEBUG
View
1 example-play/conf/play.plugins
@@ -1 +0,0 @@
-1000:com.gu.management.play.InternalManagementPlugin
View
4 example-play/conf/routes
@@ -1,4 +0,0 @@
-GET /scala-app controllers.ScalaApp.apply()
-GET /scala-app/long controllers.ScalaApp.long()
-GET /scala-app/exception controllers.ScalaApp.exception()
-GET /scala-app/async controllers.ScalaApp.async()
View
42 example-play/test/RequestMetricsSpec.scala
@@ -1,42 +0,0 @@
-import com.gu.management.{ Metric, TimingMetric, CountMetric }
-import conf.PlayExampleRequestMetrics
-import org.specs2.mutable._
-
-import play.api.test._
-import play.api.test.Helpers._
-
-class RequestMetricsSpec extends Specification {
-
- sequential
-
- "request metrics" should {
- "correctly count and time requests for performance" in running(FakeApplication()) {
- val metric = getMetric[TimingMetric]("request_duration")
-
- val originalTimingCount = metric.count
- val startTimeTotal = metric.totalTimeInMillis
-
- status(route(FakeRequest(GET, "/scala-app/long")).get) must equalTo(OK)
-
- val counted = metric.count - originalTimingCount
- val measuredDuration = metric.totalTimeInMillis - startTimeTotal
-
- counted must be equalTo (1)
- measuredDuration must be >= 2000L
- }
-
- "correctly count OK requests" in running(FakeApplication()) {
- val metric = getMetric[CountMetric]("200_ok")
-
- val originalOkCount = metric.count
-
- status(route(FakeRequest(GET, "/scala-app")).get) must equalTo(OK)
-
- val counted = metric.count - originalOkCount
-
- counted must be equalTo (1)
- }
- }
-
- def getMetric[A <: Metric](metricName: String) = PlayExampleRequestMetrics.asMetrics.find(_.name == metricName).get.asInstanceOf[A]
-}
View
4 management-internal/build.sbt
@@ -1,8 +1,8 @@
resolvers ++= Seq(Classpaths.typesafeResolver, ScalaToolsReleases)
libraryDependencies ++= Seq(
- "org.specs2" %% "specs2" % "1.5" % "test",
- "com.github.scala-incubator.io" %% "scala-io-file" % "0.4.2"
+ "org.specs2" %% "specs2" % "1.12.3" % "test",
+ "com.github.scala-incubator.io" %% "scala-io-file" % "0.4.1"
)
// disable publishing the main javadoc jar
View
20 management-play/build.sbt
@@ -1,20 +0,0 @@
-
-libraryDependencies ++= Seq(
- "play" %% "play" % "2.1-RC3",
- "org.reflections" % "reflections" % "0.9.8" exclude("javassist", "javassist"), // http://code.google.com/p/reflections/issues/detail?id=140
- "org.specs2" %% "specs2" % "1.5" % "test",
- "play" %% "play-test" % "2.1-RC2" % "test"
-)
-
-// needed for Play
-resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases/"
-
-// sad situation https://github.com/jesseeichar/scala-io/issues/77#issuecomment-11991815
-moduleConfigurations += ModuleConfiguration("com.github.scala-incubator.io", DefaultMavenRepository)
-
-moduleConfigurations += ModuleConfiguration("com.jsuereth", DefaultMavenRepository)
-
-// disable publishing the main javadoc jar
-publishArtifact in (Compile, packageDoc) := false
-
-seq(scalariformSettings: _*)
View
112 management-play/src/main/scala/com/gu/management/play/metrics.scala
@@ -1,112 +0,0 @@
-package com.gu.management.play
-
-import play.api.libs.concurrent.Execution.Implicits._
-import _root_.play.api.mvc._
-import concurrent.Future
-import util.Try
-import com.gu.management._
-import util.Failure
-import util.Success
-
-object RequestMetrics {
-
- trait Standard {
- val knownResultTypeCounters = List(OkCounter(), RedirectCounter(), NotFoundCounter(), ErrorCounter())
-
- val otherCounter = OtherCounter(knownResultTypeCounters)
-
- val asFilters: List[MetricsFilter] = List(TimingFilter(), CountersFilter(otherCounter :: knownResultTypeCounters))
-
- val asMetrics: List[Metric] = asFilters.flatMap(_.metrics).distinct
- }
-
- trait MetricsFilter extends Filter {
- val metrics: Seq[Metric]
- }
-
- object TimingFilter {
- def apply(): MetricsFilter = {
- val timingMetric = new TimingMetric("performance", "request_duration", "Client requests", "incoming requests to the application")
-
- new MetricsFilter {
- val metrics = Seq(timingMetric)
-
- def apply(next: (RequestHeader) => Result)(rh: RequestHeader): Result = {
- val s = new StopWatch
- val result = next(rh)
- onFinalPlainResult(result) { _ => timingMetric.recordTimeSpent(s.elapsed) }
- result
- }
- }
- }
- }
-
- object CountersFilter {
- def apply(counters: List[Counter]): MetricsFilter = new MetricsFilter {
- val metrics = counters.map(_.countMetric)
-
- def apply(next: (RequestHeader) => Result)(rh: RequestHeader): Result = {
- val result = next(rh)
- onFinalPlainResult(result) {
- plainResultTry => counters.foreach(_.submit(plainResultTry))
- }
- result
- }
- }
- }
-
- case class Counter(condition: Try[PlainResult] => Boolean, countMetric: CountMetric) {
- def submit(resultTry: Try[PlainResult]) {
- if (condition(resultTry)) countMetric increment ()
- }
- }
-
- object OkCounter {
- def apply() = Counter(StatusCode(200), new CountMetric("request-status", "200_ok", "200 Ok", "number of pages that responded 200"))
- }
-
- object RedirectCounter {
- def apply() = Counter(StatusCode(301, 302), new CountMetric("request-status", "30x_redirect", "30x Redirect", "number of pages that responded with a redirect"))
- }
-
- object NotFoundCounter {
- def apply() = Counter(StatusCode(404), new CountMetric("request-status", "404_not_found", "404 Not found", "number of pages that responded 404"))
- }
-
- object ErrorCounter {
- def apply() = Counter(t => { t.isFailure || (StatusCode(500 to 509)(t)) }, new CountMetric("request-status", "50x_error", "50x Error", "number of pages that responded 50x"))
- }
-
- object OtherCounter {
- def apply(knownResultTypeCounters: Seq[Counter]) = {
- def unknown(result: Try[PlainResult]) = !knownResultTypeCounters.exists(_.condition(result))
-
- Counter(unknown, new CountMetric("request-status", "other", "Other", "number of pages that responded with an unexpected status code"))
- }
- }
-
- object StatusCode {
-
- def apply(codes: Traversable[Int]): Try[PlainResult] => Boolean = apply(codes.toSet: Int => Boolean)
-
- def apply(codes: Int*): Try[PlainResult] => Boolean = apply(Set(codes: _*): Int => Boolean)
-
- def apply(condition: Int => Boolean)(resultTry: Try[PlainResult]) =
- resultTry.map(plainResult => condition(plainResult.header.status)).getOrElse(false)
- }
-
- /**
- * AsyncResult can - theoretically- return another AsyncResult, which we don't want. Redeem only when have a
- * non-async result.
- */
- private def onFinalPlainResult(result: Result)(k: Try[PlainResult] => Unit) {
- result match {
- case plainResult: PlainResult => k(Success(plainResult))
- case AsyncResult(future: Future[Result]) => future onComplete {
- case Success(anotherAsyncResult) => onFinalPlainResult(anotherAsyncResult)(k)
- case Failure(e) => k(Failure(e))
- }
- }
- }
-
-}
View
40 management-play/src/main/scala/com/gu/management/play/package.scala
@@ -1,40 +0,0 @@
-package com.gu.management.play
-
-import play.api.Application
-import play.api.mvc.{ AnyContent, Request }
-import com.gu.management.ListMultiMaps
-import org.reflections.Reflections
-import scala.collection.JavaConversions._
-
-object `package` extends ListMultiMaps {
-
- implicit def request2Parameters[A](request: Request[A]) = new {
- lazy val parameters: ListMultiMap[String, String] = {
- val queryStringParameters = request.queryString mapValues { _.toList }
- val bodyFormParameters: Map[String, List[String]] = request.body match {
- case body: AnyContent if body.asFormUrlEncoded.isDefined => body.asFormUrlEncoded.get mapValues { _.toList }
- case _ => Map()
- }
-
- queryStringParameters addBindings bodyFormParameters
- }
- }
-
- implicit def request2RequestURI[A](request: Request[A]) = new {
- lazy val requestURI: String = request.uri.replaceAll("\\?.*", "")
- }
-
- implicit def application2GetConfigurationProperty(app: Application) = new {
- def getConfigurationProperty(key: String, default: String): String = {
- app.configuration.getString(key).getOrElse(default)
- }
- }
-
- implicit def class2SubTypesFrom[T](supertype: Class[T]) = new {
- def subTypesFrom(root: String): Set[Class[_ <: T]] = {
- val reflections = new Reflections(root)
- reflections.getSubTypesOf(supertype).toSet
- }
- }
-
-}
View
50 management-play/src/main/scala/com/gu/management/play/plugin.scala
@@ -1,50 +0,0 @@
-package com.gu.management.play
-
-import com.gu.management.ManagementPage
-import com.gu.management.internal._
-import org.reflections.Reflections
-import scala.collection.JavaConversions._
-import play.api.{ Logger, Play, Plugin, Application }
-
-trait Management {
- val applicationName: String
- val pages: List[ManagementPage]
-}
-
-class InternalManagementPlugin(val app: Application) extends Plugin {
-
- implicit val log = Logger(getClass)
-
- override def onStart() {
- log.debug("Registering management pages")
-
- val searchRoot = app.getConfigurationProperty("management.search.root", "conf")
- val classes = classOf[Management].subTypesFrom(searchRoot).toList
-
- classes match {
- case Nil =>
- log.error("Can't start management server, no subtype of com.gu.management.play.Management found in package %s." format searchRoot)
- throw new RuntimeException("No management subtype found")
-
- case _ if classes.size > 1 =>
- log.error("Not starting management server, multiple subtypes of com.gu.management.play.Management found in package %s." format searchRoot)
- throw new RuntimeException("No management subtype found")
-
- // case List(managementClass: Class[_ <: Management]) =>
- case List(managementClass) =>
- val management = managementClass.getField("MODULE$").get(null).asInstanceOf[Management]
- val handler = new ManagementHandler {
- val applicationName = management.applicationName
- val pages = management.pages
- }
-
- log.debug("Starting internal management server")
- ManagementServer.start(handler)
- }
- }
-
- override def onStop() {
- log.debug("Shutting down management server")
- ManagementServer.shutdown()
- }
-}
View
52 management-play/src/test/scala/com/gu/management/play/PluginTest.scala
@@ -1,52 +0,0 @@
-package com.gu.management.play
-
-import org.specs2.mutable.Specification
-import play.api.test._
-import play.api.test.Helpers._
-import play.api.Play
-import com.gu.management.internal.ManagementServer
-import com.gu.management._
-import io.Source
-
-object TestManagement extends Management {
- val applicationName = "test-app"
- val pages = List(
- new ManagementPage {
- def get(req: HttpRequest): Response = new PlainTextResponse("response")
- val path: String = "/management/test"
- }
- )
-}
-
-class PluginTest extends Specification {
-
- "plugin" should {
- "be created" in {
- running(FakeApplication(
- additionalPlugins = Seq("com.gu.management.play.InternalManagementPlugin"),
- additionalConfiguration = Map("management.search.root" -> "com.gu.management.play")
- )) {
- Play.current.plugin[InternalManagementPlugin] must beSome
- }
- }
- "start management server" in {
- running(FakeApplication(
- additionalPlugins = Seq("com.gu.management.play.InternalManagementPlugin"),
- additionalConfiguration = Map("management.search.root" -> "com.gu.management.play")
- )) {
- ManagementServer.isRunning must beTrue
- }
- }
- "serve management page" in {
- running(FakeApplication(
- additionalPlugins = Seq("com.gu.management.play.InternalManagementPlugin"),
- additionalConfiguration = Map("management.search.root" -> "com.gu.management.play")
- )) {
- val port = ManagementServer.port()
- val response = Source.fromURL("http://localhost:%d/management/test" format port) mkString ""
- response must be equalTo ("response")
- }
- }
- }
-
-}
View
4 management-servlet-api/build.sbt
@@ -2,7 +2,7 @@
libraryDependencies ++= Seq(
"javax.servlet" % "servlet-api" % "2.4" % "provided",
"com.github.scala-incubator.io" %% "scala-io-core" % "0.4.1" exclude("javax.transaction", "jta"),
- "org.specs2" %% "specs2" % "1.13" % "test",
+ "org.specs2" %% "specs2" % "1.12.3" % "test",
"org.scalatest" %% "scalatest" % "1.9.1" % "test",
"org.mockito" % "mockito-core" % "1.9.5" % "test",
"net.liftweb" %% "lift-testkit" % "2.5-M4" % "test"
@@ -14,4 +14,4 @@ resolvers += ScalaToolsSnapshots
// disable publishing the main javadoc jar
publishArtifact in (Compile, packageDoc) := false
-seq(scalariformSettings: _*)
+seq(scalariformSettings: _*)
View
2 management/build.sbt
@@ -2,7 +2,7 @@
libraryDependencies ++= Seq(
"org.slf4j" % "slf4j-api" % "1.6.1",
"net.liftweb" %% "lift-json" % "2.5-M4", // Update when poss - 2.5-M4 incorrectly gave specs2 compile scope: https://github.com/lift/framework/issues/1397
- "org.specs2" %% "specs2" % "1.13" % "test",
+ "org.specs2" %% "specs2" % "1.12.3" % "test",
"net.liftweb" %% "lift-testkit" % "2.5-M4" % "test"
)
View
13 project/ManagementBuild.scala
@@ -14,19 +14,16 @@ object ManagementBuild extends Build {
lazy val root = Project("management-root", file(".")).aggregate(
management,
managementServletApi,
- managementPlay,
managementInternal,
managementLogback,
managementMongo,
- exampleServletApi,
- examplePlay
+ exampleServletApi
).noPublish
lazy val management = managementProject("management")
lazy val managementServletApi = managementProject("management-servlet-api") dependsOn (management)
lazy val managementInternal = managementProject("management-internal") dependsOn (management)
- lazy val managementPlay = managementProject("management-play") dependsOn (management,managementInternal)
lazy val managementLogback = managementProject("management-logback") dependsOn (management)
lazy val managementMongo = managementProject("management-mongo") dependsOn (management)
@@ -36,13 +33,5 @@ object ManagementBuild extends Build {
managementLogback
).noPublish
- lazy val examplePlay = play.Project(
- name = "example-play",
- applicationVersion = "1.0",
- dependencies = Nil,
- path = file("example-play")).
- dependsOn(management, managementPlay, managementLogback).
- noPublish
-
def managementProject(name: String) = Project(name, file(name)).settings(ScalariformPlugin.scalariformSettings :_*)
}
View
93 readme.md
@@ -7,13 +7,12 @@ This library provides standard management pages and makes it easy to create new
app-specific ones in order to fulfill those criteria.
The library is intended to be web framework agnostic and currently has support for
-anything using the servlet API, the Play framework and as a standalone internal server
-running on a separate port. A small adapter library
+anything using the servlet API, the Play framework (provided in [guardian-management-play](https://github.com/guardian/guardian-management-play))
+and as a standalone internal server running on a separate port. A small adapter library
for the request and response abstractions, blatantly inspired by/ripped off from
[lift](http://www.liftweb.net), needs to be added to support other frameworks.
-
Getting Started (Servlet API)
===============
@@ -121,51 +120,6 @@ and a more complex page that supports POSTs is
[the switchboard](https://github.com/guardian/guardian-management/blob/master/management/src/main/scala/com/gu/management/switchables.scala).
-
-Getting Started (Play Framework)
-===============
-
-Add the dependency to your build
------------------------------------
-
-In your build.sbt for sbt 0.10:
-
- resolvers += "Guardian Github Snapshots" at "http://guardian.github.com/maven/repo-releases"
- libraryDependencies += "com.gu" %% "management-play" % "5.21"
-
-As of 5.7, Scala 2.8.1 and 2.9.0-1 are no longer supported. Upgrade your project
-to Scala 2.9.1.
-
-Look at the example!
------------------------
-
-See example commit https://github.com/guardian/guardian-management/commit/f801e8d0
-
-The [example project](https://github.com/guardian/guardian-management/tree/master/example-play) has
-management routes set up and uses some switches and timing metrics.
-
- $ git clone git@github.com:guardian/guardian-management.git
- $ cd guardian-management
- $ ./sbt010
- > project example-play
- > run
-
-Try the following URLs locally:
-
- * http://localhost:9000/scala-app
- * http://localhost:18080/management
- * http://localhost:18080/management/switchboard
-
-Also, enable the `take-it-down` switch and retry `/scala-app`.
-
-The application also has very simple custom management page, but the best thing to do if you want to write your
-own management pages is to look at how the pre-defined ones are implemented: a simple readonly page to look at is
-the
-[status page](https://github.com/guardian/guardian-management/blob/master/management/src/main/scala/com/gu/management/StatusPage.scala),
-and a more complex page that supports POSTs is
-[the switchboard](https://github.com/guardian/guardian-management/blob/master/management/src/main/scala/com/gu/management/switchables.scala).
-
-
Getting started (standalone)
============================
@@ -216,49 +170,6 @@ ManagementServer.start(handler)
ManagementServer.shutdown()
```
-Using the internal server in Play 2
-===================================
-
-Configure your dependencies
----------------------------
-
- resolvers += "Guardian Github Snapshots" at "http://guardian.github.com/maven/repo-releases"
- libraryDependencies += "com.gu" %% "management-play" % "5.21"
-
-Add to the play plugins file
-----------------------------
-
-Add the following line to conf/play.plugins (create it if it doesn't exist):
-
- 1000:com.gu.management.play.InternalManagementPlugin
-
-Bind the management pages
--------------------------
-
-The plugin locates the pages and application name by convention.
-
-Create a scala Object called conf.Management that mixes in the ManagementPageManifest trait to
-provide the list of pages and your application name to the plugin:
-
-```scala
-package conf
-
-object Management extends ManagementPageManifest {
- val applicationName = "your-application-name"
-
- lazy val pages = List(
- new ManifestPage,
- new HealthcheckManagementPage,
- new Switchboard(applicationName, Switches.all),
- StatusPage(applicationName, Metrics.all),
- new LogbackLevelPage(applicationName)
- )
-}
-```
-
-If there is a reason you can't name your file conf.Management, you can override it
-by setting management.manifestobject in application.conf.
-
Providing metrics for GANGLIA
=====================

0 comments on commit d49fe2c

Please sign in to comment.
Something went wrong with that request. Please try again.