├── .gitignore ├── build.gradle ├── docker-compose.yaml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── grafana ├── SpringBootDashboard.json ├── dashboards.yaml └── influxdb.yaml ├── readme.md ├── settings.gradle └── src ├── main ├── java │ └── ch │ │ └── mgysel │ │ └── example │ │ └── metrics │ │ ├── MainController.java │ │ └── MetricsExampleApplication.java └── resources │ └── application.properties └── test └── java └── ch └── mgysel └── example └── metrics └── MetricsExampleApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | 29 | ### VS Code ### 30 | .vscode/ 31 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.3.1.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.9.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'ch.mgysel.example' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | implementation 'io.micrometer:micrometer-registry-influx' 19 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 20 | } 21 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | grafana: 5 | image: grafana/grafana:7.0.5 6 | ports: 7 | - 3000:3000 8 | volumes: 9 | - ./grafana/influxdb.yaml:/etc/grafana/provisioning/datasources/influxdb.yaml 10 | - ./grafana/SpringBootDashboard.json:/var/lib/grafana/dashboards/SpringBoot.json 11 | - ./grafana/dashboards.yaml:/etc/grafana/provisioning/dashboards/dashboards.yaml 12 | environment: 13 | GF_SECURITY_ADMIN_PASSWORD: admin 14 | influxdb: 15 | image: influxdb:1.8.0 16 | ports: 17 | - 8086:8086 18 | volumes: 19 | - /var/lib/influxdb 20 | environment: 21 | INFLUXDB_HTTP_AUTH_ENABLED: "true" 22 | INFLUXDB_DB: boot 23 | INFLUXDB_USER: user 24 | INFLUXDB_USER_PASSWORD: pass 25 | INFLUXDB_ADMIN_USER: admin 26 | INFLUXDB_ADMIN_PASSWORD: secret 27 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gysel/spring-boot-metrics-influxdb/76fd9548d0798f6d6be014d339c2c17d1834ee70/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /grafana/SpringBootDashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "editable": true, 16 | "gnetId": null, 17 | "graphTooltip": 0, 18 | "links": [], 19 | "panels": [ 20 | { 21 | "aliasColors": {}, 22 | "bars": false, 23 | "dashLength": 10, 24 | "dashes": false, 25 | "fill": 1, 26 | "gridPos": { 27 | "h": 9, 28 | "w": 12, 29 | "x": 0, 30 | "y": 0 31 | }, 32 | "id": 2, 33 | "interval": "", 34 | "legend": { 35 | "avg": false, 36 | "current": false, 37 | "max": false, 38 | "min": false, 39 | "show": true, 40 | "total": false, 41 | "values": false 42 | }, 43 | "lines": true, 44 | "linewidth": 1, 45 | "links": [], 46 | "nullPointMode": "null", 47 | "options": {}, 48 | "percentage": false, 49 | "pointradius": 2, 50 | "points": false, 51 | "renderer": "flot", 52 | "seriesOverrides": [], 53 | "spaceLength": 10, 54 | "stack": false, 55 | "steppedLine": false, 56 | "targets": [ 57 | { 58 | "alias": "$tag_status", 59 | "groupBy": [ 60 | { 61 | "params": [ 62 | "$__interval" 63 | ], 64 | "type": "time" 65 | }, 66 | { 67 | "params": [ 68 | "status" 69 | ], 70 | "type": "tag" 71 | }, 72 | { 73 | "params": [ 74 | "null" 75 | ], 76 | "type": "fill" 77 | } 78 | ], 79 | "measurement": "http_server_requests", 80 | "orderByTime": "ASC", 81 | "policy": "default", 82 | "refId": "A", 83 | "resultFormat": "time_series", 84 | "select": [ 85 | [ 86 | { 87 | "params": [ 88 | "count" 89 | ], 90 | "type": "field" 91 | }, 92 | { 93 | "params": [], 94 | "type": "sum" 95 | } 96 | ] 97 | ], 98 | "tags": [ 99 | { 100 | "key": "uri", 101 | "operator": "=", 102 | "value": "/" 103 | } 104 | ] 105 | } 106 | ], 107 | "thresholds": [], 108 | "timeFrom": null, 109 | "timeRegions": [], 110 | "timeShift": null, 111 | "title": "HTTP Requests", 112 | "tooltip": { 113 | "shared": true, 114 | "sort": 0, 115 | "value_type": "individual" 116 | }, 117 | "type": "graph", 118 | "xaxis": { 119 | "buckets": null, 120 | "mode": "time", 121 | "name": null, 122 | "show": true, 123 | "values": [] 124 | }, 125 | "yaxes": [ 126 | { 127 | "format": "short", 128 | "label": null, 129 | "logBase": 1, 130 | "max": null, 131 | "min": "0", 132 | "show": true 133 | }, 134 | { 135 | "format": "short", 136 | "label": null, 137 | "logBase": 1, 138 | "max": null, 139 | "min": null, 140 | "show": true 141 | } 142 | ], 143 | "yaxis": { 144 | "align": false, 145 | "alignLevel": null 146 | } 147 | }, 148 | { 149 | "aliasColors": {}, 150 | "bars": false, 151 | "dashLength": 10, 152 | "dashes": false, 153 | "fill": 1, 154 | "gridPos": { 155 | "h": 9, 156 | "w": 12, 157 | "x": 12, 158 | "y": 0 159 | }, 160 | "id": 4, 161 | "interval": "", 162 | "legend": { 163 | "avg": false, 164 | "current": false, 165 | "max": false, 166 | "min": false, 167 | "show": true, 168 | "total": false, 169 | "values": false 170 | }, 171 | "lines": true, 172 | "linewidth": 1, 173 | "links": [], 174 | "nullPointMode": "null", 175 | "options": {}, 176 | "percentage": false, 177 | "pointradius": 2, 178 | "points": false, 179 | "renderer": "flot", 180 | "seriesOverrides": [], 181 | "spaceLength": 10, 182 | "stack": false, 183 | "steppedLine": false, 184 | "targets": [ 185 | { 186 | "alias": "$tag_level", 187 | "groupBy": [ 188 | { 189 | "params": [ 190 | "$__interval" 191 | ], 192 | "type": "time" 193 | }, 194 | { 195 | "params": [ 196 | "level" 197 | ], 198 | "type": "tag" 199 | }, 200 | { 201 | "params": [ 202 | "null" 203 | ], 204 | "type": "fill" 205 | } 206 | ], 207 | "measurement": "logback_events", 208 | "orderByTime": "ASC", 209 | "policy": "default", 210 | "refId": "A", 211 | "resultFormat": "time_series", 212 | "select": [ 213 | [ 214 | { 215 | "params": [ 216 | "value" 217 | ], 218 | "type": "field" 219 | }, 220 | { 221 | "params": [], 222 | "type": "sum" 223 | } 224 | ] 225 | ], 226 | "tags": [] 227 | } 228 | ], 229 | "thresholds": [], 230 | "timeFrom": null, 231 | "timeRegions": [], 232 | "timeShift": null, 233 | "title": "Log Events", 234 | "tooltip": { 235 | "shared": true, 236 | "sort": 0, 237 | "value_type": "individual" 238 | }, 239 | "type": "graph", 240 | "xaxis": { 241 | "buckets": null, 242 | "mode": "time", 243 | "name": null, 244 | "show": true, 245 | "values": [] 246 | }, 247 | "yaxes": [ 248 | { 249 | "format": "short", 250 | "label": null, 251 | "logBase": 1, 252 | "max": null, 253 | "min": null, 254 | "show": true 255 | }, 256 | { 257 | "format": "short", 258 | "label": null, 259 | "logBase": 1, 260 | "max": null, 261 | "min": null, 262 | "show": true 263 | } 264 | ], 265 | "yaxis": { 266 | "align": false, 267 | "alignLevel": null 268 | } 269 | }, 270 | { 271 | "aliasColors": {}, 272 | "bars": false, 273 | "dashLength": 10, 274 | "dashes": false, 275 | "fill": 1, 276 | "gridPos": { 277 | "h": 8, 278 | "w": 12, 279 | "x": 0, 280 | "y": 9 281 | }, 282 | "id": 6, 283 | "legend": { 284 | "avg": false, 285 | "current": false, 286 | "max": false, 287 | "min": false, 288 | "show": true, 289 | "total": false, 290 | "values": false 291 | }, 292 | "lines": true, 293 | "linewidth": 1, 294 | "links": [], 295 | "nullPointMode": "null", 296 | "options": {}, 297 | "percentage": false, 298 | "pointradius": 2, 299 | "points": false, 300 | "renderer": "flot", 301 | "seriesOverrides": [ 302 | { 303 | "alias": "max", 304 | "fill": 0 305 | } 306 | ], 307 | "spaceLength": 10, 308 | "stack": false, 309 | "steppedLine": false, 310 | "targets": [ 311 | { 312 | "alias": "used", 313 | "groupBy": [ 314 | { 315 | "params": [ 316 | "$__interval" 317 | ], 318 | "type": "time" 319 | }, 320 | { 321 | "params": [ 322 | "null" 323 | ], 324 | "type": "fill" 325 | } 326 | ], 327 | "measurement": "jvm_memory_used", 328 | "orderByTime": "ASC", 329 | "policy": "default", 330 | "refId": "A", 331 | "resultFormat": "time_series", 332 | "select": [ 333 | [ 334 | { 335 | "params": [ 336 | "value" 337 | ], 338 | "type": "field" 339 | }, 340 | { 341 | "params": [], 342 | "type": "mean" 343 | } 344 | ] 345 | ], 346 | "tags": [] 347 | }, 348 | { 349 | "alias": "max", 350 | "groupBy": [ 351 | { 352 | "params": [ 353 | "$__interval" 354 | ], 355 | "type": "time" 356 | }, 357 | { 358 | "params": [ 359 | "null" 360 | ], 361 | "type": "fill" 362 | } 363 | ], 364 | "measurement": "jvm_memory_max", 365 | "orderByTime": "ASC", 366 | "policy": "default", 367 | "refId": "B", 368 | "resultFormat": "time_series", 369 | "select": [ 370 | [ 371 | { 372 | "params": [ 373 | "value" 374 | ], 375 | "type": "field" 376 | }, 377 | { 378 | "params": [], 379 | "type": "mean" 380 | } 381 | ] 382 | ], 383 | "tags": [] 384 | } 385 | ], 386 | "thresholds": [], 387 | "timeFrom": null, 388 | "timeRegions": [], 389 | "timeShift": null, 390 | "title": "Memory", 391 | "tooltip": { 392 | "shared": true, 393 | "sort": 0, 394 | "value_type": "individual" 395 | }, 396 | "type": "graph", 397 | "xaxis": { 398 | "buckets": null, 399 | "mode": "time", 400 | "name": null, 401 | "show": true, 402 | "values": [] 403 | }, 404 | "yaxes": [ 405 | { 406 | "format": "bytes", 407 | "label": null, 408 | "logBase": 1, 409 | "max": null, 410 | "min": null, 411 | "show": true 412 | }, 413 | { 414 | "format": "short", 415 | "label": null, 416 | "logBase": 1, 417 | "max": null, 418 | "min": null, 419 | "show": true 420 | } 421 | ], 422 | "yaxis": { 423 | "align": false, 424 | "alignLevel": null 425 | } 426 | }, 427 | { 428 | "aliasColors": {}, 429 | "bars": false, 430 | "dashLength": 10, 431 | "dashes": false, 432 | "fill": 1, 433 | "gridPos": { 434 | "h": 8, 435 | "w": 12, 436 | "x": 12, 437 | "y": 9 438 | }, 439 | "id": 7, 440 | "legend": { 441 | "avg": false, 442 | "current": false, 443 | "max": false, 444 | "min": false, 445 | "show": true, 446 | "total": false, 447 | "values": false 448 | }, 449 | "lines": true, 450 | "linewidth": 1, 451 | "links": [], 452 | "nullPointMode": "null", 453 | "options": {}, 454 | "percentage": false, 455 | "pointradius": 2, 456 | "points": false, 457 | "renderer": "flot", 458 | "seriesOverrides": [ 459 | { 460 | "alias": "max", 461 | "fill": 0 462 | } 463 | ], 464 | "spaceLength": 10, 465 | "stack": false, 466 | "steppedLine": false, 467 | "targets": [ 468 | { 469 | "alias": "CPU usage", 470 | "groupBy": [ 471 | { 472 | "params": [ 473 | "$__interval" 474 | ], 475 | "type": "time" 476 | }, 477 | { 478 | "params": [ 479 | "null" 480 | ], 481 | "type": "fill" 482 | } 483 | ], 484 | "measurement": "process_cpu_usage", 485 | "orderByTime": "ASC", 486 | "policy": "default", 487 | "refId": "A", 488 | "resultFormat": "time_series", 489 | "select": [ 490 | [ 491 | { 492 | "params": [ 493 | "value" 494 | ], 495 | "type": "field" 496 | }, 497 | { 498 | "params": [], 499 | "type": "mean" 500 | } 501 | ] 502 | ], 503 | "tags": [] 504 | } 505 | ], 506 | "thresholds": [], 507 | "timeFrom": null, 508 | "timeRegions": [], 509 | "timeShift": null, 510 | "title": "CPU", 511 | "tooltip": { 512 | "shared": true, 513 | "sort": 0, 514 | "value_type": "individual" 515 | }, 516 | "type": "graph", 517 | "xaxis": { 518 | "buckets": null, 519 | "mode": "time", 520 | "name": null, 521 | "show": true, 522 | "values": [] 523 | }, 524 | "yaxes": [ 525 | { 526 | "format": "short", 527 | "label": null, 528 | "logBase": 1, 529 | "max": null, 530 | "min": null, 531 | "show": true 532 | }, 533 | { 534 | "format": "short", 535 | "label": null, 536 | "logBase": 1, 537 | "max": null, 538 | "min": null, 539 | "show": true 540 | } 541 | ], 542 | "yaxis": { 543 | "align": false, 544 | "alignLevel": null 545 | } 546 | } 547 | ], 548 | "refresh": "30s", 549 | "schemaVersion": 18, 550 | "style": "dark", 551 | "tags": [], 552 | "templating": { 553 | "list": [] 554 | }, 555 | "time": { 556 | "from": "now-30m", 557 | "to": "now" 558 | }, 559 | "timepicker": { 560 | "refresh_intervals": [ 561 | "5s", 562 | "10s", 563 | "30s", 564 | "1m", 565 | "5m", 566 | "15m", 567 | "30m", 568 | "1h", 569 | "2h", 570 | "1d" 571 | ], 572 | "time_options": [ 573 | "5m", 574 | "15m", 575 | "1h", 576 | "6h", 577 | "12h", 578 | "24h", 579 | "2d", 580 | "7d", 581 | "30d" 582 | ] 583 | }, 584 | "timezone": "", 585 | "title": "Spring Boot", 586 | "uid": "56Qv1gnZz", 587 | "version": 1 588 | } -------------------------------------------------------------------------------- /grafana/dashboards.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: 'default' 5 | folder: '' 6 | type: file 7 | editable: true 8 | options: 9 | path: /var/lib/grafana/dashboards 10 | -------------------------------------------------------------------------------- /grafana/influxdb.yaml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | datasources: 5 | - name: InfluxDb 6 | type: influxdb 7 | access: proxy 8 | orgId: 1 9 | url: http://influxdb:8086 10 | user: admin 11 | password: secret 12 | database: boot 13 | isDefault: true 14 | version: 1 15 | editable: false 16 | jsonData: 17 | httpMode: GET 18 | timeInterval: "30s" 19 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Metrics Example 2 | 3 | A Spring Boot application capturing metrics using [Micrometer](http://micrometer.io/) 4 | and sending them to an [InfluxDB](https://www.influxdata.com/products/influxdb-overview/). 5 | Reporting is done in [Grafana](https://grafana.com/). 6 | 7 | 8 | ## Start the Example 9 | 10 | ```sh 11 | docker-compose up -d 12 | ./gradlew bootRun 13 | ``` 14 | 15 | The example is accessible on: 16 | 17 | * Spring Boot: http://localhost:8080/ 18 | * Grafana: http://localhost:3000 19 | * User: admin 20 | * Password: admin 21 | * InfluxDB: http://localhost:8086 (only API, no UI) 22 | 23 | The Influx Datasource and a simple dashboard are automatically provisioned in Grafana. -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'spring-boot-metrics-influxdb' 7 | -------------------------------------------------------------------------------- /src/main/java/ch/mgysel/example/metrics/MainController.java: -------------------------------------------------------------------------------- 1 | package ch.mgysel.example.metrics; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class MainController { 8 | 9 | @GetMapping("/") 10 | public String index() { 11 | return "Hello World"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ch/mgysel/example/metrics/MetricsExampleApplication.java: -------------------------------------------------------------------------------- 1 | package ch.mgysel.example.metrics; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class MetricsExampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(MetricsExampleApplication.class, args); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | management.metrics.export.influx.db=boot 2 | management.metrics.export.influx.userName=user 3 | management.metrics.export.influx.password=pass 4 | management.metrics.export.influx.uri=http://localhost:8086 5 | management.metrics.export.influx.step=15s 6 | management.metrics.export.influx.autoCreateDb=false -------------------------------------------------------------------------------- /src/test/java/ch/mgysel/example/metrics/MetricsExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package ch.mgysel.example.metrics; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class MetricsExampleApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------