Add MeterRegistry monitoring
- update and cleanup in README.md - extract webclient call from registerDevice and add metrics in DeviceRegistryService - add WebClientCalls.kt - update kotlin logging dependency - add MeterRegistry dependency
This commit is contained in:
65
README.md
65
README.md
@@ -5,16 +5,23 @@ Classes and endpoints, to shape and to steer, Devices and sensors, their purpose
|
|||||||
## Properties for deployment
|
## Properties for deployment
|
||||||
|
|
||||||
| name | required | info |
|
| name | required | info |
|
||||||
|-------------------------------|----------|-------------------------|
|
|----------------------------------------------|:--------:|----------------------------------------------|
|
||||||
| spring.profiles.active | * | Spring Boot environment |
|
| spring.profiles.active | ✓ | Spring Boot environment |
|
||||||
| server.port | * | HTTP port |
|
| server.port | ✓ | HTTP port |
|
||||||
| server.ssl.enabled | * | HTTP Enable SSL |
|
| server.ssl.enabled | ✓ | HTTP Enable SSL |
|
||||||
| server.ssl.key-store | * | HTTP Keystore |
|
| server.ssl.key-store | ✓ | HTTP Keystore |
|
||||||
| server.ssl.key-store-type | * | HTTP Cert Type |
|
| server.ssl.key-store-type | ✓ | HTTP Cert Type |
|
||||||
| server.ssl.key-store-password | ** | HTTP Cert Pass |
|
| server.ssl.key-store-password | ✗ | HTTP Cert Pass |
|
||||||
| device-registry.url | * | Device Register URL |
|
| device-registry.url | ✓ | Device Register URL |
|
||||||
|
| management.influx.metrics.export.api-version | | InfluxDB API version |
|
||||||
|
| management.influx.metrics.export.enabled | | Enable/Disable exporting metrics to InfluxDB |
|
||||||
|
| management.influx.metrics.export.bucket | ✓ | InfluxDB bucket name |
|
||||||
|
| management.influx.metrics.export.org | ✓ | InfluxDB organization |
|
||||||
|
| management.influx.metrics.export.token | ✗ | InfluxDB token |
|
||||||
|
| management.influx.metrics.export.uri | ✓ | InfluxDB URL |
|
||||||
|
| management.metrics.tags.application | ✓ | Application instance tag for metrics |
|
||||||
|
|
||||||
Required: * can be stored as text, and ** need to be stored as secret.
|
*Required: ✓ can be stored as text, and ✗ need to be stored as secret.*
|
||||||
|
|
||||||
## Releasing Service
|
## Releasing Service
|
||||||
|
|
||||||
@@ -22,39 +29,29 @@ Run `release.sh` script from `master` branch.
|
|||||||
|
|
||||||
## Development Configuration
|
## Development Configuration
|
||||||
|
|
||||||
|
|
||||||
### Developer Keystore
|
### Developer Keystore
|
||||||
|
|
||||||
1. Open `hosts` file:
|
We use a keystore to enable HTTPS for our API. To set up your developer environment for local development, please refer to [generate keystore](https://github.com/swordsteel/hlaeja-development/blob/master/doc/keystore.md) documentation. When generating and exporting the certificate for local development, please store it in the `./cert/keystore.p12` folder at the project root.
|
||||||
* On Unix-like systems (Linux, macOS), this directory is typically `/etc/hosts`.
|
|
||||||
* On Windows, this directory is typically `%SystemRoot%\System32\drivers\etc\hosts`.
|
|
||||||
|
|
||||||
2. Add the following lines to the `hosts` file:
|
### Global Settings
|
||||||
```text
|
|
||||||
127.0.0.1 registryapi # Hlæja Registry API
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Generate Keystores
|
This services rely on a set of global settings to configure development environments. These settings, managed through Gradle properties or environment variables.
|
||||||
```shell
|
|
||||||
keytool -genkeypair -alias registry-api -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=registryapi" -keypass password -keystore ./cert/keystore.p12 -storetype PKCS12 -storepass password
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Export the public certificate
|
*Note: For more information on global properties, please refer to our [global settings](https://github.com/swordsteel/hlaeja-development/blob/master/doc/global_settings.md) documentation.*
|
||||||
```shell
|
|
||||||
keytool -export -alias registry-api -keystore ./cert/keystore.p12 -storepass password -file ./cert/registry-api.cer -rfc
|
|
||||||
```
|
|
||||||
|
|
||||||
### Global gradle properties
|
#### Gradle Properties
|
||||||
|
|
||||||
To authenticate with Gradle to access repositories that require authentication, you can set your user and token in the `gradle.properties` file.
|
|
||||||
|
|
||||||
Here's how you can do it:
|
|
||||||
|
|
||||||
1. Open or create the `gradle.properties` file in your Gradle user home directory:
|
|
||||||
- On Unix-like systems (Linux, macOS), this directory is typically `~/.gradle/`.
|
|
||||||
- On Windows, this directory is typically `C:\Users\<YourUsername>\.gradle\`.
|
|
||||||
2. Add the following lines to the `gradle.properties` file:
|
|
||||||
```properties
|
```properties
|
||||||
repository.user=your_user
|
repository.user=your_user
|
||||||
repository.token=your_token_value
|
repository.token=your_token_value
|
||||||
|
influxdb.token=your_token_value
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Environment Variables
|
||||||
|
|
||||||
|
```properties
|
||||||
|
REPOSITORY_USER=your_user
|
||||||
|
REPOSITORY_TOKEN=your_token_value
|
||||||
|
INFLUXDB_TOKEN=your_token_value
|
||||||
```
|
```
|
||||||
or use environment variables `REPOSITORY_USER` and `REPOSITORY_TOKEN`
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(hlaeja.plugins.kotlin.jvm)
|
alias(hlaeja.plugins.kotlin.jvm)
|
||||||
alias(hlaeja.plugins.kotlin.spring)
|
alias(hlaeja.plugins.kotlin.spring)
|
||||||
@@ -13,6 +15,7 @@ dependencies {
|
|||||||
implementation(hlaeja.kotlin.reflect)
|
implementation(hlaeja.kotlin.reflect)
|
||||||
implementation(hlaeja.kotlinx.coroutines)
|
implementation(hlaeja.kotlinx.coroutines)
|
||||||
implementation(hlaeja.library.hlaeja.common.messages)
|
implementation(hlaeja.library.hlaeja.common.messages)
|
||||||
|
implementation(hlaeja.micrometer.registry.influx)
|
||||||
implementation(hlaeja.springboot.starter.actuator)
|
implementation(hlaeja.springboot.starter.actuator)
|
||||||
implementation(hlaeja.springboot.starter.webflux)
|
implementation(hlaeja.springboot.starter.webflux)
|
||||||
|
|
||||||
@@ -27,6 +30,17 @@ dependencies {
|
|||||||
|
|
||||||
group = "ltd.hlaeja"
|
group = "ltd.hlaeja"
|
||||||
|
|
||||||
tasks.named("processResources") {
|
fun influxDbToken(): String = config.findOrDefault("influxdb.token", "INFLUXDB_TOKEN", "")
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
named("containerCreate", DockerCreateContainer::class) {
|
||||||
|
withEnvVar("MANAGEMENT_INFLUX_METRICS_EXPORT_TOKEN", influxDbToken())
|
||||||
|
}
|
||||||
|
withType<ProcessResources> {
|
||||||
|
filesMatching("**/application.yml") { filter { it.replace("%INFLUXDB_TOKEN%", influxDbToken()) } }
|
||||||
|
onlyIf { file("src/main/resources/application.yml").exists() }
|
||||||
|
}
|
||||||
|
named("processResources") {
|
||||||
dependsOn("copyCertificates")
|
dependsOn("copyCertificates")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
version=0.1.0-SNAPSHOT
|
version=0.1.0-SNAPSHOT
|
||||||
catalog=0.6.0
|
catalog=0.7.0-SNAPSHOT
|
||||||
docker.port.expose=8443
|
docker.port.expose=8443
|
||||||
container.port.expose=8443
|
container.port.expose=8443
|
||||||
container.port.host=9040
|
container.port.host=9040
|
||||||
|
|||||||
0
release.sh
Normal file → Executable file
0
release.sh
Normal file → Executable file
@@ -1,24 +1,46 @@
|
|||||||
package ltd.hlaeja.service
|
package ltd.hlaeja.service
|
||||||
|
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
|
import io.micrometer.core.instrument.Counter
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry
|
||||||
import ltd.hlaeja.library.deviceRegistry.Device
|
import ltd.hlaeja.library.deviceRegistry.Device
|
||||||
import ltd.hlaeja.util.logCall
|
|
||||||
import ltd.hlaeja.property.DeviceRegistryProperty
|
import ltd.hlaeja.property.DeviceRegistryProperty
|
||||||
import org.springframework.http.HttpStatus.REQUEST_TIMEOUT
|
import ltd.hlaeja.util.deviceRegistryCreateDevice
|
||||||
|
import org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.web.ErrorResponseException
|
||||||
import org.springframework.web.reactive.function.client.WebClient
|
import org.springframework.web.reactive.function.client.WebClient
|
||||||
import org.springframework.web.reactive.function.client.awaitBodyOrNull
|
import org.springframework.web.reactive.function.client.WebClientRequestException
|
||||||
import org.springframework.web.server.ResponseStatusException
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
|
private val log = KotlinLogging.logger {}
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class DeviceRegistryService(
|
class DeviceRegistryService(
|
||||||
|
meterRegistry: MeterRegistry,
|
||||||
private val webClient: WebClient,
|
private val webClient: WebClient,
|
||||||
private val deviceRegistryProperty: DeviceRegistryProperty,
|
private val deviceRegistryProperty: DeviceRegistryProperty,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
private val registerDeviceSuccess = Counter.builder("device.registry.success")
|
||||||
|
.description("Number of successful device registrations")
|
||||||
|
.register(meterRegistry)
|
||||||
|
|
||||||
|
private val registerDeviceFailure = Counter.builder("device.registry.failure")
|
||||||
|
.description("Number of failed device registrations")
|
||||||
|
.register(meterRegistry)
|
||||||
|
|
||||||
suspend fun registerDevice(
|
suspend fun registerDevice(
|
||||||
request: Device.Request,
|
request: Device.Request,
|
||||||
): Device.Response = webClient.post()
|
): Device.Response = try {
|
||||||
.uri("${deviceRegistryProperty.url}/device".also(::logCall))
|
webClient.deviceRegistryCreateDevice(request, deviceRegistryProperty)
|
||||||
.bodyValue(request)
|
.also { registerDeviceSuccess.increment() }
|
||||||
.retrieve()
|
} catch (e: ErrorResponseException) {
|
||||||
.awaitBodyOrNull<Device.Response>() ?: throw ResponseStatusException(REQUEST_TIMEOUT)
|
registerDeviceFailure.increment()
|
||||||
|
throw e
|
||||||
|
} catch (e: WebClientRequestException) {
|
||||||
|
registerDeviceFailure.increment()
|
||||||
|
log.error(e) { "Error device registry" }
|
||||||
|
throw ResponseStatusException(SERVICE_UNAVAILABLE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package ltd.hlaeja.util
|
package ltd.hlaeja.util
|
||||||
|
|
||||||
import mu.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
|
|
||||||
private val log = KotlinLogging.logger {}
|
private val log = KotlinLogging.logger {}
|
||||||
|
|
||||||
fun logCall(url: String) {
|
fun logCall(url: String) = log.debug { "calling: $url" }
|
||||||
log.debug("calling: {}", url)
|
|
||||||
}
|
|
||||||
|
|||||||
17
src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt
Normal file
17
src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package ltd.hlaeja.util
|
||||||
|
|
||||||
|
import ltd.hlaeja.library.deviceRegistry.Device
|
||||||
|
import ltd.hlaeja.property.DeviceRegistryProperty
|
||||||
|
import org.springframework.http.HttpStatus.REQUEST_TIMEOUT
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient
|
||||||
|
import org.springframework.web.reactive.function.client.awaitBodyOrNull
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
|
suspend fun WebClient.deviceRegistryCreateDevice(
|
||||||
|
request: Device.Request,
|
||||||
|
property: DeviceRegistryProperty,
|
||||||
|
): Device.Response = post()
|
||||||
|
.uri("${property.url}/device".also(::logCall))
|
||||||
|
.bodyValue(request)
|
||||||
|
.retrieve()
|
||||||
|
.awaitBodyOrNull<Device.Response>() ?: throw ResponseStatusException(REQUEST_TIMEOUT)
|
||||||
@@ -10,6 +10,25 @@ spring:
|
|||||||
name: "%APP_BUILD_OS_NAME%"
|
name: "%APP_BUILD_OS_NAME%"
|
||||||
version: "%APP_BUILD_OS_VERSION%"
|
version: "%APP_BUILD_OS_VERSION%"
|
||||||
|
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
enabled-by-default: false
|
||||||
|
web:
|
||||||
|
exposure:
|
||||||
|
include: "health,info"
|
||||||
|
endpoint:
|
||||||
|
health:
|
||||||
|
enabled: true
|
||||||
|
show-details: always
|
||||||
|
info:
|
||||||
|
enabled: true
|
||||||
|
influx:
|
||||||
|
metrics:
|
||||||
|
export:
|
||||||
|
api-version: v2
|
||||||
|
bucket: hlaeja
|
||||||
|
org: hlaeja_ltd
|
||||||
|
|
||||||
---
|
---
|
||||||
###############################
|
###############################
|
||||||
### Development environment ###
|
### Development environment ###
|
||||||
@@ -30,6 +49,16 @@ server:
|
|||||||
device-registry:
|
device-registry:
|
||||||
url: http://localhost:9010
|
url: http://localhost:9010
|
||||||
|
|
||||||
|
management:
|
||||||
|
metrics:
|
||||||
|
tags:
|
||||||
|
application: register-api
|
||||||
|
influx:
|
||||||
|
metrics:
|
||||||
|
export:
|
||||||
|
enabled: false
|
||||||
|
token: %INFLUXDB_TOKEN%
|
||||||
|
|
||||||
---
|
---
|
||||||
##########################
|
##########################
|
||||||
### Docker environment ###
|
### Docker environment ###
|
||||||
@@ -39,6 +68,15 @@ spring:
|
|||||||
activate:
|
activate:
|
||||||
on-profile: docker
|
on-profile: docker
|
||||||
|
|
||||||
|
management:
|
||||||
|
metrics:
|
||||||
|
tags:
|
||||||
|
application: register-api
|
||||||
|
influx:
|
||||||
|
metrics:
|
||||||
|
export:
|
||||||
|
uri: http://InfluxDB:8086
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: 8443
|
port: 8443
|
||||||
ssl:
|
ssl:
|
||||||
|
|||||||
Reference in New Issue
Block a user