blob: 772fd7e1e99a3037c7eb68a12b9a41953cbff57a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tuweni.metrics
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import io.opentelemetry.exporter.prometheus.PrometheusCollector
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.metrics.SdkMeterProvider
import io.opentelemetry.sdk.metrics.export.IntervalMetricReader
import io.opentelemetry.sdk.resources.Resource
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes
import io.prometheus.client.CollectorRegistry
import io.prometheus.client.exporter.HTTPServer
import org.slf4j.LoggerFactory
import java.net.InetSocketAddress
import java.util.concurrent.TimeUnit
class MetricsService(
jobName: String,
reportingIntervalMillis: Long = 5000,
port: Int = 9090,
networkInterface: String = "0.0.0.0",
enablePrometheus: Boolean = true,
enableGrpcPush: Boolean = true,
grpcEndpoint: String = "http://localhost:4317",
grpcTimeout: Long = 2000,
) {
companion object {
private val logger = LoggerFactory.getLogger(MetricsService::class.java)
}
private val server: HTTPServer?
val meterSdkProvider: SdkMeterProvider
val openTelemetry: OpenTelemetrySdk
private val spanProcessor: BatchSpanProcessor
private val periodicReader: IntervalMetricReader?
init {
val exporter = OtlpGrpcMetricExporter.builder().setEndpoint(grpcEndpoint).setTimeout(grpcTimeout, TimeUnit.MILLISECONDS).build()
logger.info("Starting metrics service")
val resource = Resource.getDefault()
.merge(
Resource.create(
Attributes.builder().put(ResourceAttributes.SERVICE_NAME, jobName).build()
)
)
meterSdkProvider = SdkMeterProvider.builder().setResource(resource).build()
if (enableGrpcPush) {
logger.info("Starting GRPC push metrics service")
val builder = IntervalMetricReader.builder()
.setExportIntervalMillis(reportingIntervalMillis)
.setMetricProducers(setOf(meterSdkProvider))
.setMetricExporter(exporter)
periodicReader = builder.buildAndStart()
} else {
periodicReader = null
}
spanProcessor = BatchSpanProcessor.builder(
OtlpGrpcSpanExporter.builder().setEndpoint(grpcEndpoint)
.setTimeout(grpcTimeout, TimeUnit.MILLISECONDS).build()
).build()
openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(SdkTracerProvider.builder().setResource(resource).addSpanProcessor(spanProcessor).build())
.build()
if (enablePrometheus) {
logger.info("Starting Prometheus metrics service")
val prometheusRegistry = CollectorRegistry(true)
PrometheusCollector.builder()
.setMetricProducer(meterSdkProvider)
.build().register<PrometheusCollector>(prometheusRegistry)
server = HTTPServer(InetSocketAddress(networkInterface, port), prometheusRegistry, true)
} else {
server = null
}
}
fun close() {
periodicReader?.shutdown()
spanProcessor.shutdown()
server?.stop()
}
}