Skip to content
Permalink
Browse files

Add prometheus and grafana for metrics

Signed-off-by: Till Kottmann <me@deletescape.ch>
  • Loading branch information
deletescape committed Nov 27, 2019
1 parent 3476e6c commit 214c384416dda4a5550cffaf344005290e7213a3
@@ -34,6 +34,13 @@ dependencies {
compile("com.github.ben-manes.caffeine:caffeine:2.8.0")
compile("com.vladsch.flexmark:flexmark-all:0.50.44")
compile("me.gosimple:nbvcxz:1.4.3")
compile("com.github.zensum:ktor-prometheus-feature:-SNAPSHOT")
compile("io.prometheus:simpleclient:0.8.0")
compile("io.prometheus:simpleclient_common:0.8.0")
compile("io.prometheus:simpleclient_logback:0.8.0")
compile("io.prometheus:simpleclient_hotspot:0.8.0")
compile("io.prometheus:simpleclient_caffeine:0.8.0")
compile("io.prometheus:simpleclient_logback:0.8.0")
compile(project(":data:base"))
compile(project(":commons"))

@@ -4,9 +4,14 @@
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="METRICS" class="io.prometheus.client.logback.InstrumentedAppender"/>

<root level="trace">
<appender-ref ref="STDOUT"/>
<appender-ref ref="METRICS"/>
</root>

<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
<logger name="org.reflections" level="INFO"/>
@@ -1,9 +1,11 @@
package dog.del.app

import com.github.benmanes.caffeine.cache.Caffeine
import com.mitchellbosecke.pebble.cache.CacheKey
import com.mitchellbosecke.pebble.cache.tag.CaffeineTagCache
import com.mitchellbosecke.pebble.cache.template.CaffeineTemplateCache
import com.mitchellbosecke.pebble.loader.ClasspathLoader
import com.mitchellbosecke.pebble.template.PebbleTemplate
import dog.del.app.api.ws.websocketApis
import dog.del.app.config.AppConfig
import dog.del.app.frontend.admin
@@ -26,30 +28,34 @@ import dog.del.data.base.model.config.Config
import dog.del.data.base.model.document.XdDocument
import dog.del.data.base.model.document.XdDocumentType
import dog.del.data.base.model.user.XdUser
import io.ktor.application.*
import io.ktor.application.Application
import io.ktor.application.install
import io.ktor.application.log
import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import io.ktor.client.features.json.GsonSerializer
import io.ktor.client.features.json.JsonFeature
import io.ktor.features.*
import io.ktor.routing.*
import io.ktor.gson.*
import io.ktor.http.ContentType.*
import io.ktor.http.content.*
import io.ktor.gson.gson
import io.ktor.http.content.resource
import io.ktor.http.content.resources
import io.ktor.http.content.static
import io.ktor.pebble.Pebble
import io.ktor.response.ApplicationSendPipeline
import io.ktor.routing.routing
import io.ktor.sessions.SessionTransportTransformerMessageAuthentication
import io.ktor.sessions.Sessions
import io.ktor.sessions.cookie
import io.ktor.websocket.WebSockets
import io.prometheus.client.cache.caffeine.CacheMetricsCollector
import io.prometheus.client.hotspot.DefaultExports
import jetbrains.exodus.database.TransientEntityStore
import kotlinx.coroutines.*
import kotlinx.coroutines.io.readRemaining
import kotlinx.coroutines.io.writer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import ktor_health_check.Health
import org.koin.ktor.ext.Koin
import org.koin.ktor.ext.get
import se.zensum.ktorPrometheusFeature.PrometheusFeature
import java.io.File

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
@@ -59,6 +65,8 @@ fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
fun Application.module(testing: Boolean = false) {
val appConfig = AppConfig(environment.config)

val cacheMetrics: CacheMetricsCollector = CacheMetricsCollector().register()

install(Koin) {
// TODO: split into multiple modules
val appModule = org.koin.dsl.module {
@@ -81,6 +89,7 @@ fun Application.module(testing: Boolean = false) {
single { MarkdownRenderer() }
single { Iframely() }
single { PasswordEstimator.init() }
single { cacheMetrics }
}
modules(
appModule
@@ -108,8 +117,27 @@ fun Application.module(testing: Boolean = false) {
suffix = ".peb"
})
extension(DogbinPebbleExtension())
tagCache(CaffeineTagCache())
templateCache(CaffeineTemplateCache(Caffeine.newBuilder().maximumSize(600).build()))

tagCache(
CaffeineTagCache(
Caffeine.newBuilder()
.maximumSize(200)
.recordStats()
.build<CacheKey, Any>().also {
cacheMetrics.addCache("pebbleTagCache", it)
}
)
)
templateCache(
CaffeineTemplateCache(
Caffeine.newBuilder()
.maximumSize(600)
.recordStats()
.build<Any, PebbleTemplate>().also {
cacheMetrics.addCache("pebbleTemplateCache", it)
}
)
)
executorService(Dispatchers.IO.asExecutorService())
}

@@ -125,6 +153,11 @@ fun Application.module(testing: Boolean = false) {

install(CallLogging)

install(PrometheusFeature) {
disableMetricsEndpoint()
}
DefaultExports.initialize()

install(Sessions) {
cookie<WebSession>("doggie_session", XdSessionStorage()) {
transform(SessionTransportTransformerMessageAuthentication(appConfig.keys.session))
@@ -18,6 +18,7 @@ import io.ktor.features.origin
import io.ktor.http.URLProtocol
import io.ktor.request.*
import io.ktor.util.url
import io.prometheus.client.cache.caffeine.CacheMetricsCollector
import jetbrains.exodus.database.TransientEntityStore
import kotlinx.coroutines.*
import kotlinx.coroutines.future.asDeferred
@@ -32,14 +33,18 @@ class SimpleAnalyticsReporter : StatisticsReporter, KoinComponent {
private val db by inject<TransientEntityStore>()
private val log by inject<Logger>()
private val config by inject<AppConfig>()
private val cacheMetrics by inject<CacheMetricsCollector>()
private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + job)
private val timezoneCache = Caffeine.newBuilder()
.maximumSize(100)
.recordStats()
.buildAsync<String, String?> { slug, _ ->
scope.future {
getTimezone(slug)
}
}.also {
cacheMetrics.addCache("analyticsTimezoneCache", it)
}
private val impressionsCache = Caffeine.newBuilder()
.maximumSize(100)
@@ -48,6 +53,8 @@ class SimpleAnalyticsReporter : StatisticsReporter, KoinComponent {
scope.future {
getSaViewCount(slug)
}
}.also {
cacheMetrics.addCache("analyticsImpressionsCache", it)
}

override val embedCode = """
@@ -0,0 +1,11 @@
apiVersion: 1

providers:
- name: 'Prometheus'
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: true
options:
path: /etc/grafana/provisioning/dashboards
@@ -0,0 +1,50 @@
# config file version
apiVersion: 1

# list of datasources that should be deleted from the database
deleteDatasources:
- name: Prometheus
orgId: 1

# list of datasources to insert/update depending
# whats available in the database
datasources:
# <string, required> name of the datasource. Required
- name: Prometheus
# <string, required> datasource type. Required
type: prometheus
# <string, required> access mode. direct or proxy. Required
access: proxy
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string> url
url: http://prometheus:9090
# <string> database password, if used
password:
# <string> database user, if used
user:
# <string> database name, if used
database:
# <bool> enable/disable basic auth
basicAuth: false
# <string> basic auth username, if used
basicAuthUser:
# <string> basic auth password, if used
basicAuthPassword:
# <bool> enable/disable with credentials headers
withCredentials:
# <bool> mark as default datasource. Max one per org
isDefault: true
# <map> fields that will be converted to json and stored in json_data
jsonData:
graphiteVersion: "1.1"
tlsAuth: false
tlsAuthWithCACert: false
# <string> json object of data that will be encrypted.
secureJsonData:
tlsCACert: "..."
tlsClientCert: "..."
tlsClientKey: "..."
version: 1
# <bool> allow users to edit datasources from the UI.
editable: true
@@ -0,0 +1,21 @@
global:
scrape_interval: 10s
evaluation_interval: 10s

scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.

- job_name: 'prometheus'

static_configs:
- targets: ['localhost:9090']

- job_name: 'node-exporter'

static_configs:
- targets: ['node-exporter:9100']

- job_name: 'dogbin'

static_configs:
- targets: ['dogbin:9090']
@@ -1,4 +1,9 @@
version: '3'

volumes:
prometheus_data: {}
grafana_data: {}

services:
reverse-proxy:
image: traefik:v2.0
@@ -22,11 +27,12 @@ services:
- ./dogbin.xdb:/dogbin.xdb
expose:
- 8080
- 9090
links:
- "highlighter:highlighter"
- "iframely:iframely"
labels:
- "traefik.http.routers.dogbin.rule=Host(`${HOST}`)"
- "traefik.http.routers.dogbin.rule=Host(`l.del.dog`)"
highlighter:
build: microservices/highlighter/
image: dogbin/highlighter
@@ -43,4 +49,37 @@ services:
- ./iframely.config.js:/iframely/config.local.js
command: server.js
labels:
- "traefik.http.routers.iframely.rule=Host(`iframely.docker.localhost`) || (Host(`${HOST}`) && PathPrefix(`/r/`))"
- "traefik.http.routers.iframely.rule=Host(`iframely.docker.localhost`) || (Host(`l.del.dog`) && PathPrefix(`/r/`))"
prometheus:
image: prom/prometheus
volumes:
- ./deployment/prometheus:/etc/prometheus/
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
grafana:
image: grafana/grafana
depends_on:
- prometheus
volumes:
- grafana_data:/var/lib/grafana
- ./deployment/grafana/provisioning/:/etc/grafana/provisioning/
environment:
- GF_SECURITY_ADMIN_PASSWORD=foobar
- GF_USERS_ALLOW_SIGN_UP=false
labels:
- "traefik.http.routers.grafana.rule=Host(`grafana.docker.localhost`)"
node-exporter:
image: prom/node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- --collector.filesystem.ignored-mount-points
- "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)"
@@ -1,8 +1,13 @@
version: '3'

volumes:
prometheus_data: {}
grafana_data: {}

services:
reverse-proxy:
image: traefik:v2.0
command: --api.insecure=true --providers.docker
command: --api.insecure=true --providers.docker --providers.docker.exposedByDefault=false
restart: always
ports:
- "80:80"
@@ -24,6 +29,7 @@ services:
- ./dogbin.xdb:/dogbin.xdb
expose:
- 8080
- 9090
links:
- "highlighter:highlighter"
- "iframely:iframely"
@@ -64,3 +70,37 @@ services:
- AUTOHEAL_START_PERIOD=30
volumes:
- /var/run/docker.sock:/var/run/docker.sock
prometheus:
image: prom/prometheus
volumes:
- ./deployment/prometheus:/etc/prometheus/
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
grafana:
image: grafana/grafana
depends_on:
- prometheus
volumes:
- grafana_data:/var/lib/grafana
- ./deployment/grafana/provisioning/:/etc/grafana/provisioning/
environment:
- GF_SECURITY_ADMIN_PASSWORD=foobar
- GF_USERS_ALLOW_SIGN_UP=false
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`${GRAFANA_HOST}`)"
node-exporter:
image: prom/node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- --collector.filesystem.ignored-mount-points
- "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)"

0 comments on commit 214c384

Please sign in to comment.
You can’t perform that action at this time.