This is the example project for Making a REST API in Play.
To get started the following settings in the /kamon-play-scala-sample/conf/application.conf
will need to be configured by environment variables.
- To send trace data to New Relic using the Kamon New Relic Span Reporter you must provide an
nr-insights-insert-key
:
kamon.newrelic {
# A New Relic Insights API Insert Key is required to send trace data to New Relic
# https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys#insert-key-create
nr-insights-insert-key = ${?INSIGHTS_INSERT_KEY}
}
- To run a Play Framework application in production mode you must provide an application secret key:
# https://www.playframework.com/documentation/2.7.x/ApplicationSecret
play.http.secret.key = ${?APPLICATION_SECRET}
- To send data to Kamon APM using the Kamon APM Reporter you must provide an
apm.api-key
:
kamon.apm {
# API Key. You can find it in the Administration section in Kamon APM https://ingestion.kamino.io/
api-key = ${?KAMON_APM_API_KEY}
...
}
You need to download and install sbt for this application to run.
Once you have sbt installed, from the root project directory, compile the program.
sbt compile
Then start up the app in development mode:
sbt run
Play will start up on the HTTP port at http://localhost:9000/. You don't need to deploy or reload anything -- changing any source code while the server is running will automatically recompile and hot-reload the application on the next HTTP request.
If you call the same URL from the command line, you’ll see JSON. Using httpie, we can execute the command:
http --verbose http://localhost:9000/v1/posts
and get back:
GET /v1/posts HTTP/1.1
Likewise, you can also send a POST directly as JSON:
http --verbose POST http://localhost:9000/v1/posts title="hello" body="world"
and get:
POST /v1/posts HTTP/1.1
Overview of what data is exposed on what ports (docker syntax HOST_PORT:CONTAINER_PORT
).
Port 5266
= Kamon status page
Ports 9000
/9001
= Kamon Play app
Port 9095
= Prometheus text format generated by kamon-prometheus reporter
Port 9411
= Port where the Zipkin Server is running. Trace data is sent here.
Generate a valid secret key to run the play app in production mode in the docker container:
Option 1: Generate a valid key and update the key in/kamon-play-scala-sample/conf/application.conf
:
sbt playUpdateSecret
Option 2: Only generate a key:
sbt playGenerateSecret
Stage your app so you can run it locally without having the app packaged:
sbt stage
Once it's been staged there should be an executable at:
./kamon-play-scala-sample/target/universal/stage/bin/play-scala-rest-api-example
Generate Dockerfile at /kamon-play-scala-sample/target/docker/stage/Dockerfile
:
sbt docker:stage
Build and publish docker image to local registry based on Dockerfile:
sbt docker:publishLocal
If you run docker images
you should see a newly created one named play-scala-rest-api-example
with the tag 2.7.x
.
Run the Kamon Play sample app docker container. Note: You must set the Play APPLICATION_SECRET
, KAMON_APM_API_KEY
, and INSIGHTS_INSERT_KEY
environment variables:
docker run -i -t --name kamon_play_app --rm \
-p 5266:5266 -p 9000:9000 -p 9001:9001 -p 9095:9095 \
-e APPLICATION_SECRET -e KAMON_APM_API_KEY -e INSIGHTS_INSERT_KEY \
play-scala-rest-api-example:2.7.x
Attach to a bash terminal in the docker container:
docker ps
docker exec -it <CONTAINER_ID> /bin/bash
Prometheus is a monitoring system that collects metrics at a configurable interval.
When using the kamon-prometheus reporter it will expose metrics in Prometheus text format for scraping at http://localhost:9095/
SELECT count(*) FROM Metric WHERE clusterName = 'kamon-play-scala-sample' facet metricName since 20 minutes ago limit 1000
In the config.yml
set the host you want to scrape Prometheus metrics from:
targets:
- description: Our sick sample app yo
urls: ["http://localhost:9095/"]
docker run -it --rm \
--name nri-prometheus \
-e $LICENSE_KEY \
-e VERBOSE=true \
-v "$(pwd)/config.yaml:/config.yaml" \
newrelic/nri-prometheus:1.1
This section covers some Docker networking configuration for running docker containers locally with the goal of running Zipkin slim in a container listening on port 9411
and reporting Kamon trace data there.
Create create a user-defined bridge network, then connect both containers to this network. Then each container can use the other’s host name to access its ports. An additional benefit is that entities outside the network cannot access these ports.
docker network create kamon_network
Start Zipkin Docker container on the network
docker run -d -p 9411:9411 --rm --name zipkin_slim --network kamon_network openzipkin/zipkin-slim
Start the Play app Docker container on the same network. Note: You must set the Play APPLICATION_SECRET
, KAMON_APM_API_KEY
, and INSIGHTS_INSERT_KEY
environment variables:
docker run -it --rm --name kamon_play_app --network kamon_network \
-p 9000:9000 -p 9001:9001 -p 9095:9095 -p 5266:5266 \
-e APPLICATION_SECRET -e KAMON_APM_API_KEY -e INSIGHTS_INSERT_KEY \
play-scala-rest-api-example:2.7.x
Inspect the network and verify that both containers are running on it
docker network inspect kamon_network
You should see output similar to the following
"Containers": {
"d7fd1e81e48af8466dfd9216043b104bc69c3720d203c88869cc5d89214d4dda": {
"Name": "kamon_play_app",
"EndpointID": "3ad4b8b15615c6da6ce562f3683743a30c4b7d3c78760fd0e6b0d422d379c693",
"MacAddress": "02:42:ac:19:00:03",
"IPv4Address": "172.25.0.3/16",
"IPv6Address": ""
},
"e06b0d1cac6ae3e9dff30d2f7869d13a70da8874f91d9899903a694033039a12": {
"Name": "zipkin_slim",
"EndpointID": "28de62f54e90cde35ebe1f4fcca289fd64f5622899f381e6b7feb49f9ec9d0a2",
"MacAddress": "02:42:ac:19:00:02",
"IPv4Address": "172.25.0.2/16",
"IPv6Address": ""
}
}
The best way to see what Play can do is to run a load test. We've included Gatling in this test project for integrated load testing.
Start Play in production mode, by staging the application and running the play script:
sbt stage
cd target/universal/stage
./bin/play-scala-rest-api-example -Dplay.http.secret.key=some-long-key-that-will-be-used-by-your-application
Then you'll start the Gatling load test up (it's already integrated into the project):
sbt ";project gatling;gatling:test"
alternatively,
sbt project gatling
sbt gatling:test
For best results, start the gatling load test up on another machine so you do not have contending resources. You can edit the Gatling simulation, and change the numbers as appropriate.
Once the test completes, you'll see an HTML file containing the load test chart:
./kamon-play-scala-sample/target/gatling/gatlingspec-1472579540405/index.html
That will contain your load test results. They will be useful.