diff --git a/.editorconfig b/.editorconfig index 4e61e809..270e69fe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,21 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +insert_final_newline = true +max_line_length = 120 +trim_trailing_whitespace = true + # Override for Makefile [{Makefile, makefile, GNUmakefile}] indent_style = tab indent_size = 4 + +[*.{kt,kts}] +ktlint_standard_no-wildcard-imports = disabled +ktlint_standard_multiline-if-else = disabled +ktlint_standard_string-template-indent = disabled +ktlint_standard_indent = disabled +ktlint_standard_multiline-expression-wrapping = disabled diff --git a/Makefile b/Makefile index 65976120..2595332e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ -VERSION=1.18.0 +VERSION=1.19.0 default: versioncheck +stop: + ./gradlew --stop + clean: ./gradlew clean @@ -68,4 +71,4 @@ refresh: ./gradlew --refresh-dependencies upgrade-wrapper: - ./gradlew wrapper --gradle-version=8.2.1 --distribution-type=bin \ No newline at end of file + ./gradlew wrapper --gradle-version=8.4 --distribution-type=bin \ No newline at end of file diff --git a/README.md b/README.md index d93d6cad..0412c1c7 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![codecov](https://codecov.io/gh/pambrose/prometheus-proxy/branch/master/graph/badge.svg)](https://codecov.io/gh/pambrose/prometheus-proxy) [![Coverage Status](https://coveralls.io/repos/github/pambrose/prometheus-proxy/badge.svg?branch=master)](https://coveralls.io/github/pambrose/prometheus-proxy?branch=master) [![Kotlin](https://img.shields.io/badge/%20language-Kotlin-red.svg)](https://kotlinlang.org/) +[![ktlint](https://img.shields.io/badge/ktlint%20code--style-%E2%9D%A4-FF4081)](https://pinterest.github.io/ktlint/) [Prometheus](https://prometheus.io) is an excellent systems monitoring and alerting toolkit, which uses a pull model for collecting metrics. The pull model is problematic when a firewall separates a Prometheus server and its metrics @@ -112,8 +113,8 @@ scrape_configs: The docker images are available via: ```bash -docker pull pambrose/prometheus-proxy:1.18.0 -docker pull pambrose/prometheus-agent:1.18.0 +docker pull pambrose/prometheus-proxy:1.19.0 +docker pull pambrose/prometheus-agent:1.19.0 ``` Start a proxy container with: @@ -122,7 +123,7 @@ Start a proxy container with: docker run --rm -p 8082:8082 -p 8092:8092 -p 50051:50051 -p 8080:8080 \ --env ADMIN_ENABLED=true \ --env METRICS_ENABLED=true \ - pambrose/prometheus-proxy:1.18.0 + pambrose/prometheus-proxy:1.19.0 ``` Start an agent container with: @@ -130,7 +131,7 @@ Start an agent container with: ```bash docker run --rm -p 8083:8083 -p 8093:8093 \ --env AGENT_CONFIG='https://raw.githubusercontent.com/pambrose/prometheus-proxy/master/examples/simple.conf' \ - pambrose/prometheus-agent:1.18.0 + pambrose/prometheus-agent:1.19.0 ``` Using the config @@ -148,7 +149,7 @@ is in your current directory, run an agent container with: docker run --rm -p 8083:8083 -p 8093:8093 \ --mount type=bind,source="$(pwd)"/prom-agent.conf,target=/app/prom-agent.conf \ --env AGENT_CONFIG=prom-agent.conf \ - pambrose/prometheus-agent:1.18.0 + pambrose/prometheus-agent:1.19.0 ``` **Note:** The `WORKDIR` of the proxy and agent images is `/app`, so make sure to use `/app` as the base directory in the @@ -296,7 +297,7 @@ docker run --rm -p 8082:8082 -p 8092:8092 -p 50440:50440 -p 8080:8080 \ --env PROXY_CONFIG=tls-no-mutual-auth.conf \ --env ADMIN_ENABLED=true \ --env METRICS_ENABLED=true \ - pambrose/prometheus-proxy:1.18.0 + pambrose/prometheus-proxy:1.19.0 docker run --rm -p 8083:8083 -p 8093:8093 \ --mount type=bind,source="$(pwd)"/testing/certs,target=/app/testing/certs \ @@ -304,7 +305,7 @@ docker run --rm -p 8083:8083 -p 8093:8093 \ --env AGENT_CONFIG=tls-no-mutual-auth.conf \ --env PROXY_HOSTNAME=mymachine.lan:50440 \ --name docker-agent \ - pambrose/prometheus-agent:1.18.0 + pambrose/prometheus-agent:1.19.0 ``` **Note:** The `WORKDIR` of the proxy and agent images is `/app`, so make sure to use `/app` as the base directory in the diff --git a/bin/docker-agent.sh b/bin/docker-agent.sh index e75b0aae..d2dabdab 100755 --- a/bin/docker-agent.sh +++ b/bin/docker-agent.sh @@ -3,4 +3,4 @@ docker run --rm -p 8083:8083 -p 8093:8093 \ --env AGENT_CONFIG='https://raw.githubusercontent.com/pambrose/prometheus-proxy/master/examples/simple.conf' \ --env PROXY_HOSTNAME=mymachine.lan \ - pambrose/prometheus-agent:1.18.0 + pambrose/prometheus-agent:1.19.0 diff --git a/bin/docker-proxy.sh b/bin/docker-proxy.sh index a13569bc..3f079697 100755 --- a/bin/docker-proxy.sh +++ b/bin/docker-proxy.sh @@ -2,4 +2,4 @@ docker run --rm -p 8082:8082 -p 8092:8092 -p 50051:50051 -p 8080:8080 \ --env PROXY_CONFIG='https://raw.githubusercontent.com/pambrose/prometheus-proxy/master/examples/simple.conf' \ - pambrose/prometheus-proxy:1.18.0 + pambrose/prometheus-proxy:1.19.0 diff --git a/build.gradle b/build.gradle index 4d75b2d7..226b066c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,151 +1,151 @@ plugins { - id 'idea' - id 'java' - id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.9.0' - id 'com.google.protobuf' version '0.9.1' // Keep in sync with grpc - id 'org.jmailen.kotlinter' version "3.13.0" - id "com.github.ben-manes.versions" version '0.47.0' - id 'com.github.johnrengelman.shadow' version '8.1.1' - id 'com.github.gmazzo.buildconfig' version '4.1.2' - id 'org.jetbrains.kotlinx.kover' version '0.7.2' - // Turn these off until jacoco fixes their kotlin 1.5.0 SMAP issue - // id 'jacoco' - // id 'com.github.kt3k.coveralls' version '2.12.0' + id 'idea' + id 'java' + id 'maven-publish' + id 'org.jetbrains.kotlin.jvm' version '1.9.20' + id 'com.google.protobuf' version '0.9.4' // Keep in sync with grpc + id 'org.jmailen.kotlinter' version "4.0.0" + id "com.github.ben-manes.versions" version '0.49.0' + id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.github.gmazzo.buildconfig' version '4.1.2' + id 'org.jetbrains.kotlinx.kover' version '0.7.4' + // Turn these off until jacoco fixes their kotlin 1.5.0 SMAP issue + // id 'jacoco' + // id 'com.github.kt3k.coveralls' version '2.12.0' } group = 'io.prometheus' -version = '1.18.0' +version = '1.19.0' sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 buildConfig { - packageName("io.prometheus") + packageName("io.prometheus") - buildConfigField('String', 'APP_NAME', "\"${project.name}\"") - buildConfigField('String', 'APP_VERSION', "\"${project.version}\"") - buildConfigField('String', 'APP_RELEASE_DATE', "\"07/19/2023\"") + buildConfigField('String', 'APP_NAME', "\"${project.name}\"") + buildConfigField('String', 'APP_VERSION', "\"${project.version}\"") + buildConfigField('String', 'APP_RELEASE_DATE', "\"11/02/2023\"") } repositories { - google() - mavenCentral() - maven { url = 'https://jitpack.io' } + google() + mavenCentral() + maven { url = 'https://jitpack.io' } } dependencies { - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version" - implementation "io.grpc:grpc-netty:$grpc_version" - implementation "io.grpc:grpc-protobuf:$grpc_version" - implementation "io.grpc:grpc-stub:$grpc_version" - implementation "io.grpc:grpc-services:$grpc_version" + implementation "io.grpc:grpc-netty:$grpc_version" + implementation "io.grpc:grpc-protobuf:$grpc_version" + implementation "io.grpc:grpc-stub:$grpc_version" + implementation "io.grpc:grpc-services:$grpc_version" - implementation "io.grpc:grpc-kotlin-stub:$gengrpc_version" + implementation "io.grpc:grpc-kotlin-stub:$gengrpc_version" - implementation "io.github.mscheong01:krotoDC-core:$krotodc_version" + implementation "io.github.mscheong01:krotoDC-core:$krotodc_version" - // Required - implementation "io.netty:netty-tcnative-boringssl-static:$tcnative_version" + // Required + implementation "io.netty:netty-tcnative-boringssl-static:$tcnative_version" - implementation "com.github.pambrose.common-utils:core-utils:$utils_version" - implementation "com.github.pambrose.common-utils:corex-utils:$utils_version" - implementation "com.github.pambrose.common-utils:dropwizard-utils:$utils_version" - implementation "com.github.pambrose.common-utils:guava-utils:$utils_version" - implementation "com.github.pambrose.common-utils:grpc-utils:$utils_version" - implementation "com.github.pambrose.common-utils:jetty-utils:$utils_version" - implementation "com.github.pambrose.common-utils:ktor-client-utils:$utils_version" - implementation "com.github.pambrose.common-utils:prometheus-utils:$utils_version" - implementation "com.github.pambrose.common-utils:service-utils:$utils_version" - implementation "com.github.pambrose.common-utils:zipkin-utils:$utils_version" + implementation "com.github.pambrose.common-utils:core-utils:$utils_version" + implementation "com.github.pambrose.common-utils:corex-utils:$utils_version" + implementation "com.github.pambrose.common-utils:dropwizard-utils:$utils_version" + implementation "com.github.pambrose.common-utils:guava-utils:$utils_version" + implementation "com.github.pambrose.common-utils:grpc-utils:$utils_version" + implementation "com.github.pambrose.common-utils:jetty-utils:$utils_version" + implementation "com.github.pambrose.common-utils:ktor-client-utils:$utils_version" + implementation "com.github.pambrose.common-utils:prometheus-utils:$utils_version" + implementation "com.github.pambrose.common-utils:service-utils:$utils_version" + implementation "com.github.pambrose.common-utils:zipkin-utils:$utils_version" - implementation "org.eclipse.jetty:jetty-servlet:$jetty_version" + implementation "org.eclipse.jetty:jetty-servlet:$jetty_version" - implementation "javax.annotation:javax.annotation-api:$annotation_version" - implementation "com.beust:jcommander:$jcommander_version" - implementation "com.typesafe:config:$typesafe_version" + implementation "javax.annotation:javax.annotation-api:$annotation_version" + implementation "com.beust:jcommander:$jcommander_version" + implementation "com.typesafe:config:$typesafe_version" - implementation "io.prometheus:simpleclient:$prometheus_version" + implementation "io.prometheus:simpleclient:$prometheus_version" - implementation "io.ktor:ktor-client:$ktor_version" - implementation "io.ktor:ktor-client-cio:$ktor_version" - implementation "io.ktor:ktor-client-auth:$ktor_version" - implementation "io.ktor:ktor-network:$ktor_version" - implementation "io.ktor:ktor-network-tls:$ktor_version" + implementation "io.ktor:ktor-client:$ktor_version" + implementation "io.ktor:ktor-client-cio:$ktor_version" + implementation "io.ktor:ktor-client-auth:$ktor_version" + implementation "io.ktor:ktor-network:$ktor_version" + implementation "io.ktor:ktor-network-tls:$ktor_version" - implementation "io.ktor:ktor-server:$ktor_version" - implementation "io.ktor:ktor-server-cio:$ktor_version" - implementation "io.ktor:ktor-server-call-logging:$ktor_version" - implementation "io.ktor:ktor-server-compression:$ktor_version" + implementation "io.ktor:ktor-server:$ktor_version" + implementation "io.ktor:ktor-server-cio:$ktor_version" + implementation "io.ktor:ktor-server-call-logging:$ktor_version" + implementation "io.ktor:ktor-server-compression:$ktor_version" - implementation "io.dropwizard.metrics:metrics-healthchecks:$dropwizard_version" + implementation "io.dropwizard.metrics:metrics-healthchecks:$dropwizard_version" - implementation "io.zipkin.brave:brave-instrumentation-grpc:$zipkin_version" + implementation "io.zipkin.brave:brave-instrumentation-grpc:$zipkin_version" - implementation "io.github.microutils:kotlin-logging:$logging_version" - implementation "ch.qos.logback:logback-classic:$logback_version" - implementation "org.slf4j:jul-to-slf4j:$slf4j_version" + implementation "io.github.microutils:kotlin-logging:$logging_version" + implementation "ch.qos.logback:logback-classic:$logback_version" + implementation "org.slf4j:jul-to-slf4j:$slf4j_version" - testImplementation "org.amshove.kluent:kluent:$kluent_version" - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" + testImplementation "org.amshove.kluent:kluent:$kluent_version" + testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" } publishing { - publications { - mavenJava(MavenPublication) { - from components.java - versionMapping { - usage('java-api') { - fromResolutionOf('runtimeClasspath') - } - usage('java-runtime') { - fromResolutionResult() - } - } + publications { + mavenJava(MavenPublication) { + from components.java + versionMapping { + usage('java-api') { + fromResolutionOf('runtimeClasspath') } + usage('java-runtime') { + fromResolutionResult() + } + } } + } } compileKotlin.dependsOn ':generateProto' protobuf { - protoc { - artifact = "com.google.protobuf:protoc:$protoc_version" + protoc { + artifact = "com.google.protobuf:protoc:$protoc_version" + } + plugins { + grpc { + artifact = "io.grpc:protoc-gen-grpc-java:$grpc_version" } - plugins { - grpc { - artifact = "io.grpc:protoc-gen-grpc-java:$grpc_version" - } - // Specify protoc to generate using our grpc kotlin plugin - grpckt { - artifact = "io.grpc:protoc-gen-grpc-kotlin:$gengrpc_version:jdk8@jar" - } + // Specify protoc to generate using our grpc kotlin plugin + grpckt { + artifact = "io.grpc:protoc-gen-grpc-kotlin:$gengrpc_version:jdk8@jar" + } - krotoDC { - artifact = "io.github.mscheong01:protoc-gen-krotoDC:$krotodc_version:jdk8@jar" - } + krotoDC { + artifact = "io.github.mscheong01:protoc-gen-krotoDC:$krotodc_version:jdk8@jar" } - generateProtoTasks { - all().each { task -> - task.plugins { - grpc {} // Generate Java gRPC classes - grpckt {} // Generate Kotlin gRPC using the custom plugin from library - krotoDC {} // Generate Kotlin data classes - } + } + generateProtoTasks { + all().each { task -> + task.plugins { + grpc {} // Generate Java gRPC classes + grpckt {} // Generate Kotlin gRPC using the custom plugin from library + krotoDC {} // Generate Kotlin data classes + } // task.builtins { // kotlin {} // } - } } + } } configurations.all { - resolutionStrategy.cacheChangingModulesFor 0, 'seconds' + resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } //startScripts.enabled = false @@ -154,24 +154,24 @@ configurations.all { project.getTasks().getByName("jar").setProperty("duplicatesStrategy", DuplicatesStrategy.INCLUDE); tasks.register('sourcesJar', Jar) { - dependsOn classes - from sourceSets.main.allSource - archiveClassifier = 'sources' + dependsOn classes + from sourceSets.main.allSource + archiveClassifier = 'sources' } tasks.register('javadocJar', Jar) { - dependsOn javadoc - archiveClassifier = 'javadoc' - from javadoc.destinationDir + dependsOn javadoc + archiveClassifier = 'javadoc' + from javadoc.destinationDir } artifacts { - archives sourcesJar - //archives javadocJar + archives sourcesJar + //archives javadocJar } java { - withSourcesJar() + withSourcesJar() } @@ -195,140 +195,129 @@ java { //check.dependsOn jacocoTestReport tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' + options.encoding = 'UTF-8' } // Required for multiple uberjar targets shadowJar { - mergeServiceFiles() + mergeServiceFiles() } task agentJar(type: Jar, dependsOn: shadowJar) { - archiveFileName = 'prometheus-agent.jar' - manifest { - attributes('Main-Class': 'io.prometheus.Agent') - } - from zipTree(shadowJar.archiveFile) + archiveFileName = 'prometheus-agent.jar' + manifest { + attributes('Main-Class': 'io.prometheus.Agent') + } + from zipTree(shadowJar.archiveFile) } task proxyJar(type: Jar, dependsOn: shadowJar) { - archiveFileName = 'prometheus-proxy.jar' - manifest { - attributes('Main-Class': 'io.prometheus.Proxy') - } - from zipTree(shadowJar.archiveFile) + archiveFileName = 'prometheus-proxy.jar' + manifest { + attributes('Main-Class': 'io.prometheus.Proxy') + } + from zipTree(shadowJar.archiveFile) } compileKotlin.dependsOn ':generateProto' kotlin { - jvmToolchain(17) + jvmToolchain(17) } compileKotlin { - kotlinOptions.freeCompilerArgs += ['-Xbackend-threads=8', - "-opt-in=kotlin.time.ExperimentalTime", - "-opt-in=kotlin.contracts.ExperimentalContracts", - "-opt-in=kotlin.ExperimentalUnsignedTypes", - "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", - "-opt-in=kotlinx.coroutines.InternalCoroutinesApi", - "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"] + kotlinOptions.freeCompilerArgs += ['-Xbackend-threads=8', + "-opt-in=kotlin.time.ExperimentalTime", + "-opt-in=kotlin.contracts.ExperimentalContracts", + "-opt-in=kotlin.ExperimentalUnsignedTypes", + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-opt-in=kotlinx.coroutines.InternalCoroutinesApi", + "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"] } compileTestKotlin { - kotlinOptions.freeCompilerArgs += ['-Xbackend-threads=8', - "-opt-in=kotlinx.coroutines.InternalCoroutinesApi", - "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"] + kotlinOptions.freeCompilerArgs += ['-Xbackend-threads=8', + "-opt-in=kotlinx.coroutines.InternalCoroutinesApi", + "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"] } test { - useJUnitPlatform() + useJUnitPlatform() - // finalizedBy jacocoTestReport + // finalizedBy jacocoTestReport - testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - exceptionFormat "full" - showStandardStreams = true - } + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + exceptionFormat "full" + showStandardStreams = true + } } // This will keep generated code out of the kotlinter checks tasks.named("lintKotlinMain") { - source = source - fileTree("$buildDir/generated") + source = source - fileTree("$buildDir/generated") } kotlinter { - ignoreFailures = false - //indentSize = 2 - reporters = ['checkstyle', 'plain'] - experimentalRules = false - disabledRules = ["no-wildcard-imports", - "indent", - "final-newline", - "comment-spacing", - "max-line-length", - "no-multi-spaces", - "no-trailing-spaces", - "wrapping", - "multiline-if-else",] + ignoreFailures = false + reporters = ['checkstyle', 'plain'] } koverMerged { - enable() // create Kover merged reports + enable() // create Kover merged reports - filters { // common filters for all default Kover merged tasks - classes { // common class filter for all default Kover merged tasks - includes.add("io.prometheus.*") // class inclusion rules - //excludes.addAll("io.prometheus.subpackage.*") // class exclusion rules - } + filters { // common filters for all default Kover merged tasks + classes { // common class filter for all default Kover merged tasks + includes.add("io.prometheus.*") // class inclusion rules + //excludes.addAll("io.prometheus.subpackage.*") // class exclusion rules + } - projects { // common projects filter for all default Kover merged tasks - //excludes.addAll("project1", ":child:project") // Specifies the projects excluded in the merged tasks - } + projects { // common projects filter for all default Kover merged tasks + //excludes.addAll("project1", ":child:project") // Specifies the projects excluded in the merged tasks } + } - xmlReport { - onCheck.set(true) - // true to run koverMergedXmlReport task during the execution of the check task (if it exists) of the current project - reportFile.set(layout.buildDirectory.file("my-merged-report/result.xml")) // change report file name - overrideClassFilter { // override common class filter - includes.add("io.prometheus.*") // override class inclusion rules - //excludes.addAll("io.prometheus.subpackage.*") // override class exclusion rules - } + xmlReport { + onCheck.set(true) + // true to run koverMergedXmlReport task during the execution of the check task (if it exists) of the current project + reportFile.set(layout.buildDirectory.file("my-merged-report/result.xml")) // change report file name + overrideClassFilter { // override common class filter + includes.add("io.prometheus.*") // override class inclusion rules + //excludes.addAll("io.prometheus.subpackage.*") // override class exclusion rules } - - htmlReport { - onCheck.set(true) - // true to run koverMergedHtmlReport task during the execution of the check task (if it exists) of the current project - reportDir.set(layout.buildDirectory.dir("my-merged-report/html-result")) // change report directory - overrideClassFilter { // override common class filter - includes.add("io.prometheus.*") // override class inclusion rules - //excludes.addAll("io.prometheus.subpackage.*") // override class exclusion rules - } + } + + htmlReport { + onCheck.set(true) + // true to run koverMergedHtmlReport task during the execution of the check task (if it exists) of the current project + reportDir.set(layout.buildDirectory.dir("my-merged-report/html-result")) // change report directory + overrideClassFilter { // override common class filter + includes.add("io.prometheus.*") // override class inclusion rules + //excludes.addAll("io.prometheus.subpackage.*") // override class exclusion rules } - - verify { - onCheck.set(true) - // true to run koverMergedVerify task during the execution of the check task (if it exists) of the current project - rule { // add verification rule - //isEnabled = true // false to disable rule checking - name = null // custom name for the rule - target = 'ALL' // specify by which entity the code for separate coverage evaluation will be grouped - - overrideClassFilter { // override common class filter - includes.add("io.prometheus.verify.*") // override class inclusion rules - // excludes.addAll("io.prometheus.verify.subpackage.*") // override class exclusion rules - } - - bound { // add rule bound - minValue = 10 - maxValue = 20 - counter = 'LINE' // change coverage metric to evaluate (LINE, INSTRUCTION, BRANCH) - valueType = 'COVERED_PERCENTAGE' - // change counter value (COVERED_COUNT, MISSED_COUNT, COVERED_PERCENTAGE, MISSED_PERCENTAGE) - } - } + } + + verify { + onCheck.set(true) + // true to run koverMergedVerify task during the execution of the check task (if it exists) of the current project + rule { // add verification rule + //isEnabled = true // false to disable rule checking + name = null // custom name for the rule + target = 'ALL' // specify by which entity the code for separate coverage evaluation will be grouped + + overrideClassFilter { // override common class filter + includes.add("io.prometheus.verify.*") // override class inclusion rules + // excludes.addAll("io.prometheus.verify.subpackage.*") // override class exclusion rules + } + + bound { // add rule bound + minValue = 10 + maxValue = 20 + counter = 'LINE' // change coverage metric to evaluate (LINE, INSTRUCTION, BRANCH) + valueType = 'COVERED_PERCENTAGE' + // change counter value (COVERED_COUNT, MISSED_COUNT, COVERED_PERCENTAGE, MISSED_PERCENTAGE) + } } -} \ No newline at end of file + } +} diff --git a/docs/release.md b/docs/release.md index 23e63a66..46af4e87 100644 --- a/docs/release.md +++ b/docs/release.md @@ -18,7 +18,7 @@ 9) Build distro with: `make distro` -10) Create release on github (https://github.com/pambrose/prometheus-proxy/releases) +10) Create release on GitHub (https://github.com/pambrose/prometheus-proxy/releases) and upload the *build/libs/prometheus-proxy.jar* and *build/libs/prometheus-agent.jar* files. 11) Build and push docker images with: `make docker-push` diff --git a/etc/compose/proxy.yml b/etc/compose/proxy.yml index 2d70739f..3ce5d28b 100644 --- a/etc/compose/proxy.yml +++ b/etc/compose/proxy.yml @@ -1,6 +1,6 @@ prometheus-proxy: autoredeploy: true - image: 'pambrose/prometheus-proxy:1.18.0' + image: 'pambrose/prometheus-proxy:1.19.0' ports: - '8080:8080' - '8082:8082' diff --git a/gradle.properties b/gradle.properties index cf6292c2..0fff69fc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,30 +1,33 @@ +# Gradle settings kotlin.code.style=official kotlin.incremental=true +# kotlin.experimental.tryK2=true org.gradle.daemon=true org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.caching=true org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# Jars annotation_version=1.3.2 -dropwizard_version=4.2.19 -gengrpc_version=1.3.0 -grpc_version=1.56.1 +dropwizard_version=4.2.21 +gengrpc_version=1.4.0 +grpc_version=1.59.0 jcommander_version=1.82 -jetty_version=10.0.15 -junit_version=5.9.3 +jetty_version=10.0.18 +junit_version=5.10.0 kluent_version=1.73 -kotlin_version=1.9.0 -krotodc_version=1.0.3 -ktor_version=2.3.2 -logback_version=1.4.8 +kotlin_version=1.9.20 +krotodc_version=1.0.6 +ktor_version=2.3.5 +logback_version=1.4.11 logging_version=4.0.0-beta-2 # Keep in sync with grpc -tcnative_version=2.0.59.Final +tcnative_version=2.0.61.Final prometheus_version=0.16.0 # Keep in sync with grpc -protoc_version=3.22.3 -serialization_version=1.5.1 -slf4j_version=2.0.7 -typesafe_version=1.4.2 -utils_version=1.39.9 +protoc_version=3.24.0 +serialization_version=1.6.0 +slf4j_version=2.0.9 +typesafe_version=1.4.3 +utils_version=1.42.1 zipkin_version=5.16.0 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79..033e24c4 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 17a8ddce..3fa8f862 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb..fcb6fca1 100755 --- a/gradlew +++ b/gradlew @@ -130,10 +130,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. diff --git a/src/main/kotlin/io/prometheus/Agent.kt b/src/main/kotlin/io/prometheus/Agent.kt index 55c22cb7..5cae7de6 100644 --- a/src/main/kotlin/io/prometheus/Agent.kt +++ b/src/main/kotlin/io/prometheus/Agent.kt @@ -70,15 +70,15 @@ class Agent( val options: AgentOptions, inProcessServerName: String = "", testMode: Boolean = false, - initBlock: (Agent.() -> Unit)? = null + initBlock: (Agent.() -> Unit)? = null, ) : GenericService( - options.configVals, - newAdminConfig(options.adminEnabled, options.adminPort, options.configVals.agent.admin), - newMetricsConfig(options.metricsEnabled, options.metricsPort, options.configVals.agent.metrics), - newZipkinConfig(options.configVals.agent.internal.zipkin), - { getVersionDesc(true) }, - isTestMode = testMode + configVals = options.configVals, + adminConfig = newAdminConfig(options.adminEnabled, options.adminPort, options.configVals.agent.admin), + metricsConfig = newMetricsConfig(options.metricsEnabled, options.metricsPort, options.configVals.agent.metrics), + zipkinConfig = newZipkinConfig(options.configVals.agent.internal.zipkin), + versionBlock = { getVersionDesc(true) }, + isTestMode = testMode, ) { private val agentConfigVals = configVals.agent.internal private val clock = Monotonic @@ -98,21 +98,22 @@ class Agent( internal val metrics by lazy { AgentMetrics(this) } init { - fun toPlainText() = """ - Prometheus Agent Info [${getVersionDesc(false)}] - - Uptime: ${upTime.format(true)} - AgentId: $agentId - AgentName: $agentName - ProxyHost: $proxyHost - - Admin Service: - ${if (isAdminEnabled) servletService.toString() else "Disabled"} - - Metrics Service: - ${if (isMetricsEnabled) metricsService.toString() else "Disabled"} - - """.trimIndent() + fun toPlainText() = + """ + Prometheus Agent Info [${getVersionDesc(false)}] + + Uptime: ${upTime.format(true)} + AgentId: $agentId + AgentName: $agentName + ProxyHost: $proxyHost + + Admin Service: + ${if (isAdminEnabled) servletService.toString() else "Disabled"} + + Metrics Service: + ${if (isMetricsEnabled) metricsService.toString() else "Disabled"} + + """.trimIndent() logger.info { "Agent name: $agentName" } logger.info { "Proxy reconnect pause time: ${agentConfigVals.reconnectPauseSecs.seconds}" } @@ -122,10 +123,8 @@ class Agent( if (options.debugEnabled) { logger.info { "Adding /$DEBUG endpoint" } addServlet( - DEBUG, - LambdaServlet { - listOf(toPlainText(), pathManager.toPlainText()).joinToString("\n") - } + path = DEBUG, + servlet = LambdaServlet { listOf(toPlainText(), pathManager.toPlainText()).joinToString("\n") }, ) } } @@ -193,11 +192,19 @@ class Agent( } }.onFailure { e -> when (e) { - is RequestFailureException -> logger.info { "Disconnected from proxy at $proxyHost after invalid response ${e.message}" } - is StatusRuntimeException -> logger.info { "Disconnected from proxy at $proxyHost" } - is StatusException -> logger.warn { "Cannot connect to proxy at $proxyHost ${e.simpleClassName} ${e.message}" } + is RequestFailureException -> + logger.info { + "Disconnected from proxy at $proxyHost after invalid response ${e.message}" + } + + is StatusRuntimeException -> + logger.info { "Disconnected from proxy at $proxyHost" } + + is StatusException -> + logger.warn { "Cannot connect to proxy at $proxyHost ${e.simpleClassName} ${e.message}" } // Catch anything else to avoid exiting retry loop - else -> logger.warn { "Throwable caught ${e.simpleClassName} ${e.message}" } + else -> + logger.warn { "Throwable caught ${e.simpleClassName} ${e.message}" } } } } finally { @@ -218,9 +225,9 @@ class Agent( healthCheckRegistry.register( "scrape_request_backlog_check", newBacklogHealthCheck( - scrapeRequestBacklogSize.get(), - agentConfigVals.scrapeRequestBacklogUnhealthySize - ) + backlogSize = scrapeRequestBacklogSize.get(), + size = agentConfigVals.scrapeRequestBacklogUnhealthySize, + ), ) } @@ -243,7 +250,10 @@ class Agent( logger.info { "Heartbeat disabled" } } - internal fun updateScrapeCounter(agent: Agent, type: String) { + internal fun updateScrapeCounter( + agent: Agent, + type: String, + ) { if (type.isNotEmpty()) metrics { scrapeRequestCount.labels(agent.launchId, type).inc() } } @@ -281,7 +291,10 @@ class Agent( } @JvmStatic - fun startSyncAgent(argv: Array, exitOnMissingConfig: Boolean) { + fun startSyncAgent( + argv: Array, + exitOnMissingConfig: Boolean, + ) { logger.apply { info { getBanner("banners/agent.txt", this) } info { getVersionDesc() } @@ -294,7 +307,7 @@ class Agent( fun startAsyncAgent( configFilename: String, exitOnMissingConfig: Boolean, - logBanner: Boolean = true + logBanner: Boolean = true, ): EmbeddedAgentInfo { if (logBanner) logger.apply { diff --git a/src/main/kotlin/io/prometheus/Proxy.kt b/src/main/kotlin/io/prometheus/Proxy.kt index cc5a4295..0b6320b5 100644 --- a/src/main/kotlin/io/prometheus/Proxy.kt +++ b/src/main/kotlin/io/prometheus/Proxy.kt @@ -58,15 +58,15 @@ class Proxy( proxyHttpPort: Int = options.proxyHttpPort, inProcessServerName: String = "", testMode: Boolean = false, - initBlock: (Proxy.() -> Unit)? = null + initBlock: (Proxy.() -> Unit)? = null, ) : GenericService( - options.configVals, - newAdminConfig(options.adminEnabled, options.adminPort, options.configVals.proxy.admin), - newMetricsConfig(options.metricsEnabled, options.metricsPort, options.configVals.proxy.metrics), - newZipkinConfig(options.configVals.proxy.internal.zipkin), - { getVersionDesc(true) }, - isTestMode = testMode + configVals = options.configVals, + adminConfig = newAdminConfig(options.adminEnabled, options.adminPort, options.configVals.proxy.admin), + metricsConfig = newMetricsConfig(options.metricsEnabled, options.metricsPort, options.configVals.proxy.metrics), + zipkinConfig = newZipkinConfig(options.configVals.proxy.internal.zipkin), + versionBlock = { getVersionDesc(true) }, + isTestMode = testMode, ) { private val proxyConfigVals: ConfigVals.Proxy2.Internal2 = configVals.proxy.internal private val httpService = ProxyHttpService(this, proxyHttpPort, isTestMode) @@ -85,19 +85,20 @@ class Proxy( internal val scrapeRequestManager = ScrapeRequestManager() init { - fun toPlainText() = """ - Prometheus Proxy Info [${getVersionDesc(false)}] - - Uptime: ${upTime.format(true)} - Proxy port: ${httpService.httpPort} - - Admin Service: - ${if (isAdminEnabled) servletService.toString() else "Disabled"} - - Metrics Service: - ${if (isMetricsEnabled) metricsService.toString() else "Disabled"} - - """.trimIndent() + fun toPlainText() = + """ + Prometheus Proxy Info [${getVersionDesc(false)}] + + Uptime: ${upTime.format(true)} + Proxy port: ${httpService.httpPort} + + Admin Service: + ${if (isAdminEnabled) servletService.toString() else "Disabled"} + + Metrics Service: + ${if (isMetricsEnabled) metricsService.toString() else "Disabled"} + + """.trimIndent() addServices(grpcService, httpService) @@ -111,10 +112,10 @@ class Proxy( toPlainText(), pathManager.toPlainText(), if (recentReqs.size > 0) "\n${recentReqs.size} most recent requests:" else "", - recentReqs.reversed().joinToString("\n") + recentReqs.reversed().joinToString("\n"), ) .joinToString("\n") - } + }, ) } else { logger.info { "Debug servlet disabled" } @@ -160,15 +161,15 @@ class Proxy( "chunking_map_check", newMapHealthCheck( agentContextManager.chunkedContextMap, - proxyConfigVals.chunkContextMapUnhealthySize - ) + proxyConfigVals.chunkContextMapUnhealthySize, + ), ) register( "scrape_response_map_check", newMapHealthCheck( scrapeRequestManager.scrapeRequestMap, - proxyConfigVals.scrapeRequestMapUnhealthySize - ) + proxyConfigVals.scrapeRequestMapUnhealthySize, + ), ) register( "agent_scrape_request_backlog", @@ -184,13 +185,16 @@ class Proxy( HealthCheck.Result.unhealthy("Large agent scrape request backlog: $s") } } - } + }, ) } } // This is called on agent disconnects - internal fun removeAgentContext(agentId: String, reason: String): AgentContext? { + internal fun removeAgentContext( + agentId: String, + reason: String, + ): AgentContext? { require(agentId.isNotEmpty()) { EMPTY_AGENT_ID_MSG } pathManager.removeFromPathManager(agentId, reason) @@ -202,7 +206,7 @@ class Proxy( args.invoke(metrics) } - //val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS") + // val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS") private val formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS") internal fun logActivity(desc: String) { @@ -228,4 +232,4 @@ class Proxy( Proxy(options = ProxyOptions(argv)) { startSync() } } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/AgentClientInterceptor.kt b/src/main/kotlin/io/prometheus/agent/AgentClientInterceptor.kt index 7fafa15c..42bce8a4 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentClientInterceptor.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentClientInterceptor.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -32,16 +32,18 @@ import io.prometheus.proxy.ProxyServerInterceptor.Companion.META_AGENT_ID_KEY import mu.two.KLogging internal class AgentClientInterceptor(private val agent: Agent) : ClientInterceptor { - override fun interceptCall( method: MethodDescriptor, callOptions: CallOptions, - next: Channel + next: Channel, ): ClientCall = object : ForwardingClientCall.SimpleForwardingClientCall( - agent.grpcService.channel.newCall(method, callOptions) + agent.grpcService.channel.newCall(method, callOptions), ) { - override fun start(responseListener: Listener, metadata: Metadata) { + override fun start( + responseListener: Listener, + metadata: Metadata, + ) { super.start( object : ForwardingClientCallListener.SimpleForwardingClientCallListener(responseListener) { override fun onHeaders(headers: Metadata) { @@ -58,7 +60,7 @@ internal class AgentClientInterceptor(private val agent: Agent) : ClientIntercep super.onHeaders(headers) } }, - metadata + metadata, ) } } diff --git a/src/main/kotlin/io/prometheus/agent/AgentConnectionContext.kt b/src/main/kotlin/io/prometheus/agent/AgentConnectionContext.kt index d194cbe9..4b7f332c 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentConnectionContext.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentConnectionContext.kt @@ -36,4 +36,4 @@ internal class AgentConnectionContext : Closeable { } val connected get() = !disconnected -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/AgentGrpcService.kt b/src/main/kotlin/io/prometheus/agent/AgentGrpcService.kt index 281c1bde..f0c2aee0 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentGrpcService.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentGrpcService.kt @@ -79,7 +79,7 @@ import kotlin.properties.Delegates.notNull internal class AgentGrpcService( internal val agent: Agent, private val options: AgentOptions, - private val inProcessServerName: String + private val inProcessServerName: String, ) { private var grpcStarted by atomicBoolean(false) private var stub: ProxyServiceGrpcKt.ProxyServiceCoroutineStub by notNull() @@ -122,7 +122,7 @@ internal class AgentGrpcService( buildClientTlsContext( certChainFilePath = certChainFilePath, privateKeyFilePath = privateKeyFilePath, - trustCertCollectionFilePath = trustCertCollectionFilePath + trustCertCollectionFilePath = trustCertCollectionFilePath, ) else PLAINTEXT_CONTEXT @@ -155,7 +155,7 @@ internal class AgentGrpcService( enableRetry = true, tlsContext = tlsContext, overrideAuthority = agent.options.overrideAuthority, - inProcessServerName = inProcessServerName + inProcessServerName = inProcessServerName, ) { if (agent.isZipkinEnabled) intercept(grpcTracing.newClientInterceptor()) @@ -183,7 +183,9 @@ internal class AgentGrpcService( true }.getOrElse { e -> agent.metrics { connectCount.labels(agent.launchId, "failure").inc() } - logger.info { "Cannot connect to proxy at ${agent.proxyHost} using ${tlsContext.desc()} - ${e.simpleClassName}: ${e.message}" } + logger.info { + "Cannot connect to proxy at ${agent.proxyHost} using ${tlsContext.desc()} - ${e.simpleClassName}: ${e.message}" + } false } @@ -194,7 +196,7 @@ internal class AgentGrpcService( launchId = agent.launchId, agentName = agent.agentName, hostName = hostName, - consolidated = agent.options.consolidated + consolidated = agent.options.consolidated, ).apply { require(agentId.isNotEmpty()) { EMPTY_AGENT_ID_MSG } } .toProto() stub.registerAgent(request) @@ -272,7 +274,10 @@ internal class AgentGrpcService( } } - suspend fun readRequestsFromProxy(agentHttpService: AgentHttpService, connectionContext: AgentConnectionContext) { + suspend fun readRequestsFromProxy( + agentHttpService: AgentHttpService, + connectionContext: AgentConnectionContext, + ) { connectionContext .use { val agentInfo = @@ -294,70 +299,72 @@ internal class AgentGrpcService( agent: Agent, scrapeResultsChannel: Channel, nonChunkedChannel: Channel, - chunkedChannel: Channel - ) = - try { - for (scrapeResults: ScrapeResults in scrapeResultsChannel) { - val scrapeId = scrapeResults.scrapeId - - if (!scrapeResults.zipped) { - logger.debug { "Writing non-chunked msg scrapeId: $scrapeId length: ${scrapeResults.contentAsText.length}" } + chunkedChannel: Channel, + ) = try { + for (scrapeResults: ScrapeResults in scrapeResultsChannel) { + val scrapeId = scrapeResults.scrapeId + + if (!scrapeResults.zipped) { + logger.debug { "Writing non-chunked msg scrapeId: $scrapeId length: ${scrapeResults.contentAsText.length}" } + nonChunkedChannel.send(scrapeResults.toScrapeResponse().toProto()) + agent.metrics { scrapeResultCount.labels(agent.launchId, "non-gzipped").inc() } + } else { + val zipped = scrapeResults.contentAsZipped + val chunkContentSize = options.chunkContentSizeKbs + + logger.debug { "Comparing ${zipped.size} and $chunkContentSize" } + + if (zipped.size < chunkContentSize) { + logger.debug { "Writing zipped non-chunked msg scrapeId: $scrapeId length: ${zipped.size}" } nonChunkedChannel.send(scrapeResults.toScrapeResponse().toProto()) - agent.metrics { scrapeResultCount.labels(agent.launchId, "non-gzipped").inc() } + agent.metrics { scrapeResultCount.labels(agent.launchId, "gzipped").inc() } } else { - val zipped = scrapeResults.contentAsZipped - val chunkContentSize = options.chunkContentSizeKbs - - logger.debug { "Comparing ${zipped.size} and $chunkContentSize" } + scrapeResults.toScrapeResponseHeader() + .also { + logger.debug { "Writing header length: ${zipped.size} for scrapeId: $scrapeId " } + chunkedChannel.send(it.toProto()) + } - if (zipped.size < chunkContentSize) { - logger.debug { "Writing zipped non-chunked msg scrapeId: $scrapeId length: ${zipped.size}" } - nonChunkedChannel.send(scrapeResults.toScrapeResponse().toProto()) - agent.metrics { scrapeResultCount.labels(agent.launchId, "gzipped").inc() } - } else { - scrapeResults.toScrapeResponseHeader() - .also { - logger.debug { "Writing header length: ${zipped.size} for scrapeId: $scrapeId " } - chunkedChannel.send(it.toProto()) - } + var totalByteCount = 0 + var totalChunkCount = 0 + val checksum = CRC32() + val bais = ByteArrayInputStream(zipped) + val buffer = ByteArray(chunkContentSize) + var readByteCount: Int - var totalByteCount = 0 - var totalChunkCount = 0 - val checksum = CRC32() - val bais = ByteArrayInputStream(zipped) - val buffer = ByteArray(chunkContentSize) - var readByteCount: Int - - while (bais.read(buffer).also { bytesRead -> readByteCount = bytesRead } > 0) { - totalChunkCount++ - totalByteCount += readByteCount - checksum.update(buffer, 0, buffer.size) - - newScrapeResponseChunk(scrapeId, totalChunkCount, readByteCount, checksum, buffer) - .also { - logger.debug { "Writing chunk $totalChunkCount for scrapeId: $scrapeId" } - chunkedChannel.send(it.toProto()) - } - } + while (bais.read(buffer).also { bytesRead -> readByteCount = bytesRead } > 0) { + totalChunkCount++ + totalByteCount += readByteCount + checksum.update(buffer, 0, buffer.size) - newScrapeResponseSummary(scrapeId, totalChunkCount, totalByteCount, checksum) + newScrapeResponseChunk(scrapeId, totalChunkCount, readByteCount, checksum, buffer) .also { - logger.debug { "Writing summary totalChunkCount: $totalChunkCount for scrapeID: $scrapeId" } + logger.debug { "Writing chunk $totalChunkCount for scrapeId: $scrapeId" } chunkedChannel.send(it.toProto()) - agent.metrics { scrapeResultCount.labels(agent.launchId, "chunked").inc() } } } - } - agent.markMsgSent() - agent.scrapeRequestBacklogSize.decrementAndGet() + newScrapeResponseSummary(scrapeId, totalChunkCount, totalByteCount, checksum) + .also { + logger.debug { "Writing summary totalChunkCount: $totalChunkCount for scrapeID: $scrapeId" } + chunkedChannel.send(it.toProto()) + agent.metrics { scrapeResultCount.labels(agent.launchId, "chunked").inc() } + } + } } - } finally { - nonChunkedChannel.close() - chunkedChannel.close() + + agent.markMsgSent() + agent.scrapeRequestBacklogSize.decrementAndGet() } + } finally { + nonChunkedChannel.close() + chunkedChannel.close() + } - suspend fun writeResponsesToProxyUntilDisconnected(agent: Agent, connectionContext: AgentConnectionContext) { + suspend fun writeResponsesToProxyUntilDisconnected( + agent: Agent, + connectionContext: AgentConnectionContext, + ) { fun exceptionHandler() = CoroutineExceptionHandler { _, e -> if (agent.isRunning) @@ -393,4 +400,4 @@ internal class AgentGrpcService( } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/AgentHttpService.kt b/src/main/kotlin/io/prometheus/agent/AgentHttpService.kt index ce4eedab..6f096e63 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentHttpService.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentHttpService.kt @@ -47,11 +47,10 @@ import kotlin.text.Charsets.UTF_8 import kotlin.time.Duration.Companion.seconds internal class AgentHttpService(val agent: Agent) { - suspend fun fetchScrapeUrl(request: ScrapeRequest): ScrapeResults = ScrapeResults( agentId = request.agentId, - scrapeId = request.scrapeId + scrapeId = request.scrapeId, ).also { scrapeResults -> val scrapeMsg = AtomicReference("") val path = request.path @@ -73,10 +72,12 @@ internal class AgentHttpService(val agent: Agent) { val requestTimer = if (agent.isMetricsEnabled) agent.startTimer(agent) else null // Add the incoming query params to the url val url = pathContext.url + - (if (encodedQueryParams.isNotEmpty()) + ( + if (encodedQueryParams.isNotEmpty()) "?${URLDecoder.decode(encodedQueryParams, UTF_8.name())}" else - "") + "" + ) logger.debug { "Fetching $pathContext" } if (encodedQueryParams.isNotEmpty()) @@ -104,9 +105,9 @@ internal class AgentHttpService(val agent: Agent) { install(HttpRequestRetry) { agent.options.scrapeMaxRetries.also { maxRetries -> - if (maxRetries <= 0) + if (maxRetries <= 0) { noRetry() - else { + } else { retryOnException(maxRetries) retryIf(maxRetries) { _, response -> !response.status.isSuccess() && response.status != HttpStatusCode.NotFound @@ -139,7 +140,7 @@ internal class AgentHttpService(val agent: Agent) { timeout { requestTimeoutMillis = scrapeTimeout.inWholeMilliseconds } authHeader?.also { header(io.ktor.http.HttpHeaders.Authorization, it) } }, - getBlock(url, scrapeResults, scrapeMsg, request.debugEnabled) + getBlock(url, scrapeResults, scrapeMsg, request.debugEnabled), ) } }.onFailure { e -> @@ -148,7 +149,8 @@ internal class AgentHttpService(val agent: Agent) { is TimeoutCancellationException, is HttpConnectTimeoutException, is SocketTimeoutException, - is HttpRequestTimeoutException -> { + is HttpRequestTimeoutException, + -> { logger.warn(e) { "fetchScrapeUrl() $e - $url" } HttpStatusCode.RequestTimeout.value } @@ -178,7 +180,7 @@ internal class AgentHttpService(val agent: Agent) { url: String, responseArg: ScrapeResults, scrapeCounterMsg: AtomicReference, - debugEnabled: Boolean + debugEnabled: Boolean, ): suspend (HttpResponse) -> Unit = { response -> responseArg.statusCode = response.status.value @@ -206,4 +208,4 @@ internal class AgentHttpService(val agent: Agent) { } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/AgentMetrics.kt b/src/main/kotlin/io/prometheus/agent/AgentMetrics.kt index 0d9e22fc..495d2129 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentMetrics.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentMetrics.kt @@ -25,7 +25,6 @@ import com.github.pambrose.common.metrics.SamplerGaugeCollector import io.prometheus.Agent internal class AgentMetrics(agent: Agent) { - val scrapeRequestCount = counter { name("agent_scrape_request_count") @@ -66,7 +65,7 @@ internal class AgentMetrics(agent: Agent) { "Agent scrape backlog size", labelNames = listOf(LAUNCH_ID), labelValues = listOf(agent.launchId), - data = { agent.scrapeRequestBacklogSize.get().toDouble() } + data = { agent.scrapeRequestBacklogSize.get().toDouble() }, ) } @@ -75,4 +74,4 @@ internal class AgentMetrics(agent: Agent) { private const val AGENT_NAME = "agent_name" private const val TYPE = "type" } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/AgentOptions.kt b/src/main/kotlin/io/prometheus/agent/AgentOptions.kt index fe599e94..926ad7e3 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentOptions.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentOptions.kt @@ -25,14 +25,15 @@ import io.prometheus.common.EnvVars.* import mu.two.KLogging import kotlin.time.Duration.Companion.seconds -class AgentOptions(argv: Array, exitOnMissingConfig: Boolean) : - BaseOptions(Agent::class.java.name, argv, AGENT_CONFIG.name, exitOnMissingConfig) { - +class AgentOptions( + argv: Array, + exitOnMissingConfig: Boolean, +) : BaseOptions(Agent::class.java.name, argv, AGENT_CONFIG.name, exitOnMissingConfig) { constructor(args: List, exitOnMissingConfig: Boolean) : - this(args.toTypedArray(), exitOnMissingConfig) + this(args.toTypedArray(), exitOnMissingConfig) constructor(configFilename: String, exitOnMissingConfig: Boolean) : - this(listOf("--config", configFilename), exitOnMissingConfig) + this(listOf("--config", configFilename), exitOnMissingConfig) @Parameter(names = ["-p", "--proxy"], description = "Proxy hostname") var proxyHostname = "" @@ -80,12 +81,11 @@ class AgentOptions(argv: Array, exitOnMissingConfig: Boolean) : if (proxyHostname.isEmpty()) { val configHostname = agentConfigVals.proxy.hostname - proxyHostname = PROXY_HOSTNAME.getEnv( - if (":" in configHostname) - configHostname - else - "$configHostname:${agentConfigVals.proxy.port}" - ) + val str = if (":" in configHostname) + configHostname + else + "$configHostname:${agentConfigVals.proxy.port}" + proxyHostname = PROXY_HOSTNAME.getEnv(str) } logger.info { "proxyHostname: $proxyHostname" } @@ -137,10 +137,14 @@ class AgentOptions(argv: Array, exitOnMissingConfig: Boolean) : logger.info { "agent.scrapeTimeoutSecs: ${agentConfigVals.scrapeTimeoutSecs.seconds}" } logger.info { "agent.internal.cioTimeoutSecs: ${agentConfigVals.internal.cioTimeoutSecs.seconds}" } - logger.info { "agent.internal.heartbeatCheckPauseMillis: ${agentConfigVals.internal.heartbeatCheckPauseMillis}" } - logger.info { "agent.internal.heartbeatMaxInactivitySecs: ${agentConfigVals.internal.heartbeatMaxInactivitySecs}" } + logger.info { + "agent.internal.heartbeatCheckPauseMillis: ${agentConfigVals.internal.heartbeatCheckPauseMillis}" + } + logger.info { + "agent.internal.heartbeatMaxInactivitySecs: ${agentConfigVals.internal.heartbeatMaxInactivitySecs}" + } } } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/AgentPathManager.kt b/src/main/kotlin/io/prometheus/agent/AgentPathManager.kt index 7abed1b7..b7e15f27 100644 --- a/src/main/kotlin/io/prometheus/agent/AgentPathManager.kt +++ b/src/main/kotlin/io/prometheus/agent/AgentPathManager.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -26,7 +26,6 @@ import io.prometheus.common.Messages.EMPTY_PATH_MSG import mu.two.KLogging internal class AgentPathManager(private val agent: Agent) { - private val agentConfigVals = agent.configVals.agent private val pathContextMap = newConcurrentMap() @@ -42,7 +41,7 @@ internal class AgentPathManager(private val agent: Agent) { mapOf( NAME to """"${it.name}"""", PATH to it.path, - URL to it.url + URL to it.url, ) } .onEach { logger.info { "Proxy path /${it[PATH]} will be assigned to ${it[URL]}" } } @@ -57,7 +56,10 @@ internal class AgentPathManager(private val agent: Agent) { logger.error { "Null path/url values: $path/$url" } } - suspend fun registerPath(pathVal: String, url: String) { + suspend fun registerPath( + pathVal: String, + url: String, + ) { require(pathVal.isNotEmpty()) { EMPTY_PATH_MSG } require(url.isNotEmpty()) { "Empty URL" } @@ -84,7 +86,7 @@ internal class AgentPathManager(private val agent: Agent) { val maxName = pathConfigs.maxOfOrNull { it[NAME]?.length ?: 0 } ?: 0 val maxPath = pathConfigs.maxOfOrNull { it[PATH]?.length ?: 0 } ?: 0 return "Agent Path Configs:\n" + "Name".padEnd(maxName + 1) + "Path".padEnd(maxPath + 2) + "URL\n" + - pathConfigs.joinToString("\n") { c -> "${c[NAME]?.padEnd(maxName)} /${c[PATH]?.padEnd(maxPath)} ${c[URL]}" } + pathConfigs.joinToString("\n") { c -> "${c[NAME]?.padEnd(maxName)} /${c[PATH]?.padEnd(maxPath)} ${c[URL]}" } } companion object : KLogging() { @@ -94,4 +96,4 @@ internal class AgentPathManager(private val agent: Agent) { } data class PathContext(val pathId: Long, val path: String, val url: String) -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/EmbeddedAgentInfo.kt b/src/main/kotlin/io/prometheus/agent/EmbeddedAgentInfo.kt index cbf11401..acbdff55 100644 --- a/src/main/kotlin/io/prometheus/agent/EmbeddedAgentInfo.kt +++ b/src/main/kotlin/io/prometheus/agent/EmbeddedAgentInfo.kt @@ -16,4 +16,4 @@ package io.prometheus.agent -data class EmbeddedAgentInfo(val launchId: String, val agentName: String) \ No newline at end of file +data class EmbeddedAgentInfo(val launchId: String, val agentName: String) diff --git a/src/main/kotlin/io/prometheus/agent/RequestFailureException.kt b/src/main/kotlin/io/prometheus/agent/RequestFailureException.kt index 4e540856..c9f8babc 100644 --- a/src/main/kotlin/io/prometheus/agent/RequestFailureException.kt +++ b/src/main/kotlin/io/prometheus/agent/RequestFailureException.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -22,4 +22,4 @@ internal class RequestFailureException(message: String) : Exception(message) { companion object { private const val serialVersionUID = 8748724180953791199L } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/agent/SslSettings.kt b/src/main/kotlin/io/prometheus/agent/SslSettings.kt index 6ddcc065..f78cd97e 100644 --- a/src/main/kotlin/io/prometheus/agent/SslSettings.kt +++ b/src/main/kotlin/io/prometheus/agent/SslSettings.kt @@ -26,7 +26,10 @@ import javax.net.ssl.X509TrustManager @Suppress("unused") object SslSettings { - fun getKeyStore(fileName: String, password: String): KeyStore = + fun getKeyStore( + fileName: String, + password: String, + ): KeyStore = KeyStore.getInstance(KeyStore.getDefaultType()) .apply { val keyStoreFile = FileInputStream(fileName) @@ -34,18 +37,27 @@ object SslSettings { load(keyStoreFile, keyStorePassword) } - fun getTrustManagerFactory(fileName: String, password: String): TrustManagerFactory? = + fun getTrustManagerFactory( + fileName: String, + password: String, + ): TrustManagerFactory? = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) .apply { init(getKeyStore(fileName, password)) } - fun getSslContext(fileName: String, password: String): SSLContext? = + fun getSslContext( + fileName: String, + password: String, + ): SSLContext? = SSLContext.getInstance("TLS") .apply { init(null, getTrustManagerFactory(fileName, password)?.trustManagers, null) } - fun getTrustManager(fileName: String, password: String): X509TrustManager = + fun getTrustManager( + fileName: String, + password: String, + ): X509TrustManager = getTrustManagerFactory(fileName, password)?.trustManagers?.first { it is X509TrustManager } as X509TrustManager } diff --git a/src/main/kotlin/io/prometheus/agent/TrustAllX509TrustManager.kt b/src/main/kotlin/io/prometheus/agent/TrustAllX509TrustManager.kt index a9ee0bd1..016b1379 100644 --- a/src/main/kotlin/io/prometheus/agent/TrustAllX509TrustManager.kt +++ b/src/main/kotlin/io/prometheus/agent/TrustAllX509TrustManager.kt @@ -26,7 +26,15 @@ object TrustAllX509TrustManager : X509TrustManager { override fun getAcceptedIssuers(): Array = EMPTY_CERTIFICATES - override fun checkClientTrusted(certs: Array?, authType: String?) {} + override fun checkClientTrusted( + certs: Array?, + authType: String?, + ) { + } - override fun checkServerTrusted(certs: Array?, authType: String?) {} -} \ No newline at end of file + override fun checkServerTrusted( + certs: Array?, + authType: String?, + ) { + } +} diff --git a/src/main/kotlin/io/prometheus/common/BaseOptions.kt b/src/main/kotlin/io/prometheus/common/BaseOptions.kt index d4799fa9..2877f91b 100644 --- a/src/main/kotlin/io/prometheus/common/BaseOptions.kt +++ b/src/main/kotlin/io/prometheus/common/BaseOptions.kt @@ -37,14 +37,13 @@ import java.util.* import kotlin.properties.Delegates.notNull import kotlin.system.exitProcess -//@Parameters(separators = "=") +// @Parameters(separators = "=") abstract class BaseOptions protected constructor( private val progName: String, private val argv: Array, private val envConfig: String, - private val exitOnMissingConfig: Boolean = false + private val exitOnMissingConfig: Boolean = false, ) { - @Parameter(names = ["-c", "--conf", "--config"], description = "Configuration file or url") private var configSource = "" @@ -87,9 +86,8 @@ abstract class BaseOptions protected constructor( @Parameter( names = ["-v", "--version"], description = "Print version info and exit", - validateWith = [VersionValidator::class] + validateWith = [VersionValidator::class], ) - private var version = false @Parameter(names = ["-u", "--usage"], help = true) @@ -187,14 +185,17 @@ abstract class BaseOptions protected constructor( logger.info { "trustCertCollectionFilePath: $trustCertCollectionFilePath" } } - private fun readConfig(envConfig: String, exitOnMissingConfig: Boolean) { + private fun readConfig( + envConfig: String, + exitOnMissingConfig: Boolean, + ) { config = readConfig( configSource.ifEmpty { System.getenv(envConfig).orEmpty() }, envConfig, ConfigParseOptions.defaults().setAllowMissing(false), ConfigFactory.load().resolve(), - exitOnMissingConfig + exitOnMissingConfig, ) .resolve(ConfigResolveOptions.defaults()) .resolve() @@ -215,7 +216,7 @@ abstract class BaseOptions protected constructor( envConfig: String, configParseOptions: ConfigParseOptions, fallback: Config, - exitOnMissingConfig: Boolean + exitOnMissingConfig: Boolean, ): Config { fun String.isUrlPrefix() = lowercase(Locale.getDefault()).startsWith(HTTP_PREFIX) || lowercase(Locale.getDefault()).startsWith(HTTPS_PREFIX) @@ -276,4 +277,4 @@ abstract class BaseOptions protected constructor( const val HTTP_PREFIX = "http://" const val HTTPS_PREFIX = "https://" } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/common/ConfigWrappers.kt b/src/main/kotlin/io/prometheus/common/ConfigWrappers.kt index c0b9a4cc..28cab548 100644 --- a/src/main/kotlin/io/prometheus/common/ConfigWrappers.kt +++ b/src/main/kotlin/io/prometheus/common/ConfigWrappers.kt @@ -24,67 +24,79 @@ import com.github.pambrose.common.service.ZipkinConfig @Suppress("unused") internal object ConfigWrappers { - fun newAdminConfig(enabled: Boolean, port: Int, admin: ConfigVals.Proxy2.Admin2) = - AdminConfig( - enabled, - port, - admin.pingPath, - admin.versionPath, - admin.healthCheckPath, - admin.threadDumpPath - ) + fun newAdminConfig( + enabled: Boolean, + port: Int, + admin: ConfigVals.Proxy2.Admin2, + ) = AdminConfig( + enabled = enabled, + port = port, + pingPath = admin.pingPath, + versionPath = admin.versionPath, + healthCheckPath = admin.healthCheckPath, + threadDumpPath = admin.threadDumpPath, + ) - fun newAdminConfig(enabled: Boolean, port: Int, admin: ConfigVals.Agent.Admin) = - AdminConfig( - enabled, - port, - admin.pingPath, - admin.versionPath, - admin.healthCheckPath, - admin.threadDumpPath - ) + fun newAdminConfig( + enabled: Boolean, + port: Int, + admin: ConfigVals.Agent.Admin, + ) = AdminConfig( + enabled = enabled, + port = port, + pingPath = admin.pingPath, + versionPath = admin.versionPath, + healthCheckPath = admin.healthCheckPath, + threadDumpPath = admin.threadDumpPath, + ) - fun newMetricsConfig(enabled: Boolean, port: Int, metrics: ConfigVals.Proxy2.Metrics2) = - MetricsConfig( - enabled, - port, - metrics.path, - metrics.standardExportsEnabled, - metrics.memoryPoolsExportsEnabled, - metrics.garbageCollectorExportsEnabled, - metrics.threadExportsEnabled, - metrics.classLoadingExportsEnabled, - metrics.versionInfoExportsEnabled - ) + fun newMetricsConfig( + enabled: Boolean, + port: Int, + metrics: ConfigVals.Proxy2.Metrics2, + ) = MetricsConfig( + enabled = enabled, + port = port, + path = metrics.path, + standardExportsEnabled = metrics.standardExportsEnabled, + memoryPoolsExportsEnabled = metrics.memoryPoolsExportsEnabled, + garbageCollectorExportsEnabled = metrics.garbageCollectorExportsEnabled, + threadExportsEnabled = metrics.threadExportsEnabled, + classLoadingExportsEnabled = metrics.classLoadingExportsEnabled, + versionInfoExportsEnabled = metrics.versionInfoExportsEnabled, + ) - fun newMetricsConfig(enabled: Boolean, port: Int, metrics: ConfigVals.Agent.Metrics) = - MetricsConfig( - enabled, - port, - metrics.path, - metrics.standardExportsEnabled, - metrics.memoryPoolsExportsEnabled, - metrics.garbageCollectorExportsEnabled, - metrics.threadExportsEnabled, - metrics.classLoadingExportsEnabled, - metrics.versionInfoExportsEnabled - ) + fun newMetricsConfig( + enabled: Boolean, + port: Int, + metrics: ConfigVals.Agent.Metrics, + ) = MetricsConfig( + enabled = enabled, + port = port, + path = metrics.path, + standardExportsEnabled = metrics.standardExportsEnabled, + memoryPoolsExportsEnabled = metrics.memoryPoolsExportsEnabled, + garbageCollectorExportsEnabled = metrics.garbageCollectorExportsEnabled, + threadExportsEnabled = metrics.threadExportsEnabled, + classLoadingExportsEnabled = metrics.classLoadingExportsEnabled, + versionInfoExportsEnabled = metrics.versionInfoExportsEnabled, + ) fun newZipkinConfig(zipkin: ConfigVals.Proxy2.Internal2.Zipkin2) = ZipkinConfig( - zipkin.enabled, - zipkin.hostname, - zipkin.port, - zipkin.path, - zipkin.serviceName + enabled = zipkin.enabled, + hostname = zipkin.hostname, + port = zipkin.port, + path = zipkin.path, + serviceName = zipkin.serviceName, ) fun newZipkinConfig(zipkin: ConfigVals.Agent.Internal.Zipkin) = ZipkinConfig( - zipkin.enabled, - zipkin.hostname, - zipkin.port, - zipkin.path, - zipkin.serviceName + enabled = zipkin.enabled, + hostname = zipkin.hostname, + port = zipkin.port, + path = zipkin.path, + serviceName = zipkin.serviceName, ) -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/common/Constants.kt b/src/main/kotlin/io/prometheus/common/Constants.kt index 66668c35..e89b8354 100644 --- a/src/main/kotlin/io/prometheus/common/Constants.kt +++ b/src/main/kotlin/io/prometheus/common/Constants.kt @@ -25,4 +25,4 @@ internal object Messages { internal object DefaultObjects { val EMPTY_INSTANCE: Empty = Empty.getDefaultInstance() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/common/EnvVars.kt b/src/main/kotlin/io/prometheus/common/EnvVars.kt index 10e52aa3..534c8a26 100644 --- a/src/main/kotlin/io/prometheus/common/EnvVars.kt +++ b/src/main/kotlin/io/prometheus/common/EnvVars.kt @@ -21,7 +21,6 @@ package io.prometheus.common import java.lang.System.getenv enum class EnvVars { - // Proxy PROXY_CONFIG, PROXY_PORT, @@ -52,7 +51,8 @@ enum class EnvVars { CERT_CHAIN_FILE_PATH, PRIVATE_KEY_FILE_PATH, TRUST_CERT_COLLECTION_FILE_PATH, - OVERRIDE_AUTHORITY; + OVERRIDE_AUTHORITY, + ; fun getEnv(defaultVal: String) = getenv(name) ?: defaultVal diff --git a/src/main/kotlin/io/prometheus/common/GrpcObjects.kt b/src/main/kotlin/io/prometheus/common/GrpcObjects.kt index 599cbd07..f19dee19 100644 --- a/src/main/kotlin/io/prometheus/common/GrpcObjects.kt +++ b/src/main/kotlin/io/prometheus/common/GrpcObjects.kt @@ -30,7 +30,6 @@ import io.prometheus.grpc.krotodc.SummaryData import java.util.zip.CRC32 internal object GrpcObjects { - fun ScrapeResponse.toScrapeResults() = ScrapeResults( agentId = agentId, @@ -40,7 +39,7 @@ internal object GrpcObjects { contentType = contentType, zipped = zipped, failureReason = failureReason, - url = url + url = url, ).also { results -> if (zipped) results.contentAsZipped = (contentOneOf as ContentAsZipped).contentAsZipped.toByteArray() @@ -53,34 +52,32 @@ internal object GrpcObjects { totalChunkCount: Int, readByteCount: Int, checksum: CRC32, - buffer: ByteArray - ) = - ChunkedScrapeResponse( - Chunk( - ChunkData( - chunkScrapeId = scrapeId, - chunkCount = totalChunkCount, - chunkByteCount = readByteCount, - chunkChecksum = checksum.value, - chunkBytes = ByteString.copyFrom(buffer), - ) - ) - ) + buffer: ByteArray, + ) = ChunkedScrapeResponse( + chunkOneOf = Chunk( + chunk = ChunkData( + chunkScrapeId = scrapeId, + chunkCount = totalChunkCount, + chunkByteCount = readByteCount, + chunkChecksum = checksum.value, + chunkBytes = ByteString.copyFrom(buffer), + ), + ), + ) fun newScrapeResponseSummary( scrapeId: Long, totalChunkCount: Int, totalByteCount: Int, - checksum: CRC32 - ) = - ChunkedScrapeResponse( - Summary( - SummaryData( - summaryScrapeId = scrapeId, - summaryChunkCount = totalChunkCount, - summaryByteCount = totalByteCount, - summaryChecksum = checksum.value, - ) - ) - ) + checksum: CRC32, + ) = ChunkedScrapeResponse( + chunkOneOf = Summary( + SummaryData( + summaryScrapeId = scrapeId, + summaryChunkCount = totalChunkCount, + summaryByteCount = totalByteCount, + summaryChecksum = checksum.value, + ), + ), + ) } diff --git a/src/main/kotlin/io/prometheus/common/ScrapeResults.kt b/src/main/kotlin/io/prometheus/common/ScrapeResults.kt index 0887b425..0fc12912 100644 --- a/src/main/kotlin/io/prometheus/common/ScrapeResults.kt +++ b/src/main/kotlin/io/prometheus/common/ScrapeResults.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -37,9 +37,12 @@ internal class ScrapeResults( var contentAsText: String = "", var contentAsZipped: ByteArray = EMPTY_BYTE_ARRAY, var failureReason: String = "", - var url: String = "" + var url: String = "", ) { - fun setDebugInfo(url: String, failureReason: String = "") { + fun setDebugInfo( + url: String, + failureReason: String = "", + ) { this.url = url this.failureReason = failureReason } @@ -58,13 +61,13 @@ internal class ScrapeResults( else ContentAsText(contentAsText), failureReason = failureReason, - url = url + url = url, ) fun toScrapeResponseHeader() = ChunkedScrapeResponse( - Header( - HeaderData( + chunkOneOf = Header( + header = HeaderData( headerValidResponse = validResponse, headerAgentId = agentId, headerScrapeId = scrapeId, @@ -72,7 +75,7 @@ internal class ScrapeResults( headerFailureReason = failureReason, headerUrl = url, headerContentType = contentType, - ) - ) + ), + ), ) -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/common/TypeAliases.kt b/src/main/kotlin/io/prometheus/common/TypeAliases.kt index 206d207a..27691bec 100644 --- a/src/main/kotlin/io/prometheus/common/TypeAliases.kt +++ b/src/main/kotlin/io/prometheus/common/TypeAliases.kt @@ -19,4 +19,4 @@ package io.prometheus.common @Suppress("unused") object TypeAliases -internal typealias ScrapeRequestAction = suspend () -> ScrapeResults \ No newline at end of file +internal typealias ScrapeRequestAction = suspend () -> ScrapeResults diff --git a/src/main/kotlin/io/prometheus/common/Utils.kt b/src/main/kotlin/io/prometheus/common/Utils.kt index 62ede801..ab382e68 100644 --- a/src/main/kotlin/io/prometheus/common/Utils.kt +++ b/src/main/kotlin/io/prometheus/common/Utils.kt @@ -27,9 +27,12 @@ import kotlin.system.exitProcess internal fun getVersionDesc(asJson: Boolean = false): String = Proxy::class.versionDesc(asJson) internal class VersionValidator : IParameterValidator { - override fun validate(name: String, value: String) { + override fun validate( + name: String, + value: String, + ) { val console = JCommander().console console.println(getVersionDesc(false)) exitProcess(0) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/AgentContext.kt b/src/main/kotlin/io/prometheus/proxy/AgentContext.kt index 852ab48e..919c52d0 100644 --- a/src/main/kotlin/io/prometheus/proxy/AgentContext.kt +++ b/src/main/kotlin/io/prometheus/proxy/AgentContext.kt @@ -29,7 +29,6 @@ import kotlin.time.TimeMark import kotlin.time.TimeSource.Monotonic internal class AgentContext(private val remoteAddr: String) { - val agentId = AGENT_ID_GENERATOR.incrementAndGet().toString() private val scrapeRequestChannel = Channel(Channel.UNLIMITED) @@ -108,7 +107,7 @@ internal class AgentContext(private val remoteAddr: String) { add("hostName", hostName) add("remoteAddr", remoteAddr) add("lastRequestDuration", lastRequestDuration) - //add("inactivityDuration", inactivityDuration) + // add("inactivityDuration", inactivityDuration) } override fun equals(other: Any?): Boolean { @@ -123,4 +122,4 @@ internal class AgentContext(private val remoteAddr: String) { companion object { private val AGENT_ID_GENERATOR = AtomicLong(0L) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/AgentContextCleanupService.kt b/src/main/kotlin/io/prometheus/proxy/AgentContextCleanupService.kt index 1d86bd49..1d967171 100644 --- a/src/main/kotlin/io/prometheus/proxy/AgentContextCleanupService.kt +++ b/src/main/kotlin/io/prometheus/proxy/AgentContextCleanupService.kt @@ -31,9 +31,8 @@ import kotlin.time.Duration.Companion.seconds internal class AgentContextCleanupService( private val proxy: Proxy, private val configVals: ConfigVals.Proxy2.Internal2, - initBlock: (AgentContextCleanupService.() -> Unit) = {} + initBlock: (AgentContextCleanupService.() -> Unit) = {}, ) : GenericExecutionThreadService() { - init { addListener(genericServiceListener(logger), MoreExecutors.directExecutor()) initBlock(this) @@ -47,7 +46,11 @@ internal class AgentContextCleanupService( .forEach { (agentId, agentContext) -> val inactivityDuration = agentContext.inactivityDuration if (inactivityDuration > maxAgentInactivityTime) { - logger.info { "Evicting agentId ${agentContext.agentId} after $inactivityDuration (max $maxAgentInactivityTime) of inactivity: $agentContext" } + logger.info { + val id = agentContext.agentId + val maxTime = maxAgentInactivityTime + "Evicting agentId $id after $inactivityDuration (max $maxTime) of inactivity: $agentContext" + } proxy.removeAgentContext(agentId, "Eviction") proxy.metrics { agentEvictionCount.inc() } } @@ -63,4 +66,4 @@ internal class AgentContextCleanupService( } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/AgentContextManager.kt b/src/main/kotlin/io/prometheus/proxy/AgentContextManager.kt index 55fe23fa..b1b1f09a 100644 --- a/src/main/kotlin/io/prometheus/proxy/AgentContextManager.kt +++ b/src/main/kotlin/io/prometheus/proxy/AgentContextManager.kt @@ -41,12 +41,15 @@ internal class AgentContextManager(private val isTestMode: Boolean) { fun getAgentContext(agentId: String) = agentContextMap[agentId] - fun removeFromContextManager(agentId: String, reason: String): AgentContext? = + fun removeFromContextManager( + agentId: String, + reason: String, + ): AgentContext? = agentContextMap.remove(agentId) .let { agentContext -> - if (agentContext.isNull()) + if (agentContext.isNull()) { logger.warn { "Missing AgentContext for agentId: $agentId ($reason)" } - else { + } else { if (!isTestMode) logger.info { "Removed $agentContext for agentId: $agentId ($reason)" } agentContext.invalidate() @@ -55,4 +58,4 @@ internal class AgentContextManager(private val isTestMode: Boolean) { } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ChunkedContext.kt b/src/main/kotlin/io/prometheus/proxy/ChunkedContext.kt index 2463d58b..b50d2b78 100644 --- a/src/main/kotlin/io/prometheus/proxy/ChunkedContext.kt +++ b/src/main/kotlin/io/prometheus/proxy/ChunkedContext.kt @@ -42,11 +42,16 @@ internal class ChunkedContext(response: ChunkedScrapeResponse) { zipped = true, failureReason = headerFailureReason, url = headerUrl, - contentType = headerContentType + contentType = headerContentType, ) } - fun applyChunk(data: ByteArray, chunkByteCount: Int, chunkCount: Int, chunkChecksum: Long) { + fun applyChunk( + data: ByteArray, + chunkByteCount: Int, + chunkCount: Int, + chunkChecksum: Long, + ) { totalChunkCount++ totalByteCount += chunkByteCount checksum.update(data, 0, data.size) @@ -56,7 +61,11 @@ internal class ChunkedContext(response: ChunkedScrapeResponse) { check(checksum.value == chunkChecksum) } - fun applySummary(summaryChunkCount: Int, summaryByteCount: Int, summaryChecksum: Long) { + fun applySummary( + summaryChunkCount: Int, + summaryByteCount: Int, + summaryChecksum: Long, + ) { check(totalChunkCount == summaryChunkCount) check(totalByteCount == summaryByteCount) check(checksum.value == summaryChecksum) @@ -64,4 +73,4 @@ internal class ChunkedContext(response: ChunkedScrapeResponse) { baos.flush() scrapeResults.contentAsZipped = baos.toByteArray() } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyGrpcService.kt b/src/main/kotlin/io/prometheus/proxy/ProxyGrpcService.kt index 734dd635..66ef37d8 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyGrpcService.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyGrpcService.kt @@ -40,9 +40,8 @@ import kotlin.time.Duration.Companion.seconds internal class ProxyGrpcService( private val proxy: Proxy, private val port: Int = -1, - private val inProcessName: String = "" + private val inProcessName: String = "", ) : GenericIdleService() { - val healthCheck = healthCheck { if (grpcServer.isShutdown || grpcServer.isTerminated) @@ -63,7 +62,7 @@ internal class ProxyGrpcService( buildServerTlsContext( certChainFilePath = options.certChainFilePath, privateKeyFilePath = options.privateKeyFilePath, - trustCertCollectionFilePath = options.trustCertCollectionFilePath + trustCertCollectionFilePath = options.trustCertCollectionFilePath, ) else PLAINTEXT_CONTEXT @@ -72,7 +71,7 @@ internal class ProxyGrpcService( server( port = port, tlsContext = tlsContext, - inProcessServerName = inProcessName + inProcessServerName = inProcessName, ) { val proxyService = ProxyServiceImpl(proxy) val interceptors = diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyHttpConfig.kt b/src/main/kotlin/io/prometheus/proxy/ProxyHttpConfig.kt index 61ca5bf3..6ec1a8ae 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyHttpConfig.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyHttpConfig.kt @@ -52,8 +52,10 @@ import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds internal object ProxyHttpConfig : KLogging() { - - fun Application.configServer(proxy: Proxy, isTestMode: Boolean) { + fun Application.configServer( + proxy: Proxy, + isTestMode: Boolean, + ) { install(DefaultHeaders) { header("X-Engine", "Ktor") } @@ -65,7 +67,8 @@ internal object ProxyHttpConfig : KLogging() { format { call -> when (val status = call.response.status()) { HttpStatusCode.Found -> { - "$status: ${call.request.toLogString()} -> ${call.response.headers[HttpHeaders.Location]} - ${call.request.origin.remoteHost}" + val str = call.request.toLogString() + "$status: $str -> ${call.response.headers[HttpHeaders.Location]} - ${call.request.origin.remoteHost}" } else -> "$status: ${call.request.toLogString()} - ${call.request.origin.remoteHost}" @@ -139,7 +142,9 @@ internal object ProxyHttpConfig : KLogging() { val responseResults = ResponseResults() val logger = ProxyHttpService.logger - logger.debug { "Servicing request for path: $path${if (queryParams.isNotEmpty()) " with query params $queryParams" else ""}" } + logger.debug { + "Servicing request for path: $path${if (queryParams.isNotEmpty()) " with query params $queryParams" else ""}" + } when { !proxy.isRunning -> { @@ -154,15 +159,21 @@ internal object ProxyHttpConfig : KLogging() { val msg = "Request missing path" proxy.logActivity(msg) logger.info { msg } - responseResults.apply { updateMsg = "missing_path"; statusCode = NotFound } + responseResults.apply { + updateMsg = "missing_path" + statusCode = NotFound + } } path == "favicon.ico" -> { - responseResults.apply { updateMsg = "invalid_path"; statusCode = NotFound } + responseResults.apply { + updateMsg = "invalid_path" + statusCode = NotFound + } } - proxyConfigVals.internal.blitz.enabled && path == proxyConfigVals.internal.blitz.path -> responseResults.contentText = - "42" + proxyConfigVals.internal.blitz.enabled && path == proxyConfigVals.internal.blitz.path -> + responseResults.contentText = "42" else -> { val agentContextInfo = proxy.pathManager.getAgentContextInfo(path) @@ -170,32 +181,35 @@ internal object ProxyHttpConfig : KLogging() { val msg = "Invalid path request /$path" proxy.logActivity(msg) logger.info { msg } - responseResults.apply { updateMsg = "invalid_path"; statusCode = NotFound } + responseResults.apply { + updateMsg = "invalid_path" + statusCode = NotFound + } } else { if (!agentContextInfo.consolidated && agentContextInfo.agentContexts[0].isNotValid()) { val msg = "Invalid AgentContext for /$path" proxy.logActivity(msg) logger.error { msg } - responseResults.apply { updateMsg = "invalid_agent_context"; statusCode = NotFound } - } else { - val jobs = agentContextInfo.agentContexts.map { - async { - submitScrapeRequest( - it, - proxy, - path, - queryParams, - call.request, - call.response - ) - } - }.map { it.await() }.onEach { response -> - var status = "/$path - ${response.updateMsg} - ${response.statusCode}" - if (!response.statusCode.isSuccess()) status += " reason: [${response.failureReason}]" - status += " time: ${response.fetchDuration} url: ${response.url}" - - proxy.logActivity(status) + responseResults.apply { + updateMsg = "invalid_agent_context" + statusCode = NotFound } + } else { + val jobs = + agentContextInfo.agentContexts + .map { + async { + submitScrapeRequest(it, proxy, path, queryParams, call.request, call.response) + } + } + .map { it.await() } + .onEach { response -> + var status = "/$path - ${response.updateMsg} - ${response.statusCode}" + if (!response.statusCode.isSuccess()) status += " reason: [${response.failureReason}]" + status += " time: ${response.fetchDuration} url: ${response.url}" + + proxy.logActivity(status) + } val statusCodes = jobs.map { it.statusCode }.toSet().toList() val contentTypes = jobs.map { it.contentType }.toSet().toList() @@ -222,14 +236,17 @@ internal object ProxyHttpConfig : KLogging() { } } - private fun updateScrapeRequests(proxy: Proxy, type: String) { + private fun updateScrapeRequests( + proxy: Proxy, + type: String, + ) { if (type.isNotEmpty()) proxy.metrics { scrapeRequestCount.labels(type).inc() } } private suspend fun ApplicationCall.respondWith( text: String, contentType: ContentType = Plain, - status: HttpStatusCode = OK + status: HttpStatusCode = OK, ) { response.header(HttpHeaders.CacheControl, "must-revalidate,no-store") response.status(status) @@ -242,16 +259,16 @@ internal object ProxyHttpConfig : KLogging() { path: String, encodedQueryParams: String, request: ApplicationRequest, - response: ApplicationResponse + response: ApplicationResponse, ): ScrapeRequestResponse { val scrapeRequest = ScrapeRequestWrapper( - agentContext, - proxy, - path, - encodedQueryParams, - request.header(HttpHeaders.Authorization) ?: "", - request.header(HttpHeaders.Accept), - proxy.options.debugEnabled + agentContext = agentContext, + proxy = proxy, + path = path, + encodedQueryParams = encodedQueryParams, + authHeader = request.header(HttpHeaders.Authorization) ?: "", + accept = request.header(HttpHeaders.Accept), + debugEnabled = proxy.options.debugEnabled, ) val logger = ProxyHttpService.logger @@ -266,11 +283,12 @@ internal object ProxyHttpConfig : KLogging() { // Returns false if timed out while (!scrapeRequest.suspendUntilComplete(checkTime)) { // Check if agent is disconnected or agent is hung - if (scrapeRequest.ageDuration() >= timeoutTime || !scrapeRequest.agentContext.isValid() || !proxy.isRunning) return ScrapeRequestResponse( - statusCode = HttpStatusCode.ServiceUnavailable, - updateMsg = "timed_out", - fetchDuration = scrapeRequest.ageDuration() - ) + if (scrapeRequest.ageDuration() >= timeoutTime || !scrapeRequest.agentContext.isValid() || !proxy.isRunning) + return ScrapeRequestResponse( + statusCode = HttpStatusCode.ServiceUnavailable, + updateMsg = "timed_out", + fetchDuration = scrapeRequest.ageDuration(), + ) } } finally { val scrapeId = scrapeRequest.scrapeId @@ -284,8 +302,11 @@ internal object ProxyHttpConfig : KLogging() { HttpStatusCode.fromValue(scrapeResults.statusCode).also { statusCode -> scrapeResults.contentType.split("/").also { contentTypeElems -> - val contentType = if (contentTypeElems.size == 2) ContentType(contentTypeElems[0], contentTypeElems[1]) - else Plain + val contentType = + if (contentTypeElems.size == 2) + ContentType(contentTypeElems[0], contentTypeElems[1]) + else + Plain // Do not return content on error status codes return if (!statusCode.isSuccess()) { @@ -296,7 +317,7 @@ internal object ProxyHttpConfig : KLogging() { failureReason = failureReason, url = url, updateMsg = "path_not_found", - fetchDuration = scrapeRequest.ageDuration() + fetchDuration = scrapeRequest.ageDuration(), ) } } else { @@ -309,7 +330,7 @@ internal object ProxyHttpConfig : KLogging() { failureReason = failureReason, url = url, updateMsg = "success", - fetchDuration = scrapeRequest.ageDuration() + fetchDuration = scrapeRequest.ageDuration(), ) } } @@ -326,12 +347,12 @@ private class ScrapeRequestResponse( var contentText: String = "", val failureReason: String = "", val url: String = "", - val fetchDuration: Duration + val fetchDuration: Duration, ) private class ResponseResults( var statusCode: HttpStatusCode = OK, var contentType: ContentType = Plain, var contentText: String = "", - var updateMsg: String = "" -) \ No newline at end of file + var updateMsg: String = "", +) diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyMetrics.kt b/src/main/kotlin/io/prometheus/proxy/ProxyMetrics.kt index 04bdb3ae..fca758f3 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyMetrics.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyMetrics.kt @@ -25,7 +25,6 @@ import com.github.pambrose.common.metrics.SamplerGaugeCollector import io.prometheus.Proxy internal class ProxyMetrics(proxy: Proxy) { - val scrapeRequestCount = counter { name("proxy_scrape_requests") @@ -66,31 +65,31 @@ internal class ProxyMetrics(proxy: Proxy) { SamplerGaugeCollector( name = "proxy_agent_map_size", help = "Proxy connected agents", - data = { proxy.agentContextManager.agentContextSize.toDouble() } + data = { proxy.agentContextManager.agentContextSize.toDouble() }, ) SamplerGaugeCollector( name = "proxy_chunk_context_map_size", help = "Proxy chunk context map size", - data = { proxy.agentContextManager.chunkedContextSize.toDouble() } + data = { proxy.agentContextManager.chunkedContextSize.toDouble() }, ) SamplerGaugeCollector( name = "proxy_path_map_size", help = "Proxy path map size", - data = { proxy.pathManager.pathMapSize.toDouble() } + data = { proxy.pathManager.pathMapSize.toDouble() }, ) SamplerGaugeCollector( name = "proxy_scrape_map_size", help = "Proxy scrape map size", - data = { proxy.scrapeRequestManager.scrapeMapSize.toDouble() } + data = { proxy.scrapeRequestManager.scrapeMapSize.toDouble() }, ) SamplerGaugeCollector( name = "proxy_cumulative_agent_backlog_size", help = "Proxy cumulative agent backlog size", - data = { proxy.agentContextManager.totalAgentScrapeRequestBacklogSize.toDouble() } + data = { proxy.agentContextManager.totalAgentScrapeRequestBacklogSize.toDouble() }, ) } } diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyOptions.kt b/src/main/kotlin/io/prometheus/proxy/ProxyOptions.kt index b99a2a32..41019174 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyOptions.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyOptions.kt @@ -24,7 +24,6 @@ import io.prometheus.common.BaseOptions import io.prometheus.common.EnvVars.* class ProxyOptions(argv: Array) : BaseOptions(Proxy::class.java.simpleName, argv, PROXY_CONFIG.name) { - constructor(args: List) : this(args.toTypedArray()) @Parameter(names = ["-p", "--port"], description = "Proxy listen port") @@ -97,4 +96,4 @@ class ProxyOptions(argv: Array) : BaseOptions(Proxy::class.java.simpleNa logger.info { "proxy.internal.maxAgentInactivitySecs: ${proxyConfigVals.internal.maxAgentInactivitySecs}" } } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyPathManager.kt b/src/main/kotlin/io/prometheus/proxy/ProxyPathManager.kt index b4036838..d505d667 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyPathManager.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyPathManager.kt @@ -28,7 +28,6 @@ import io.prometheus.grpc.krotodc.UnregisterPathResponse import mu.two.KLogging internal class ProxyPathManager(private val proxy: Proxy, private val isTestMode: Boolean) { - class AgentContextInfo(var consolidated: Boolean, val agentContexts: MutableList) { override fun toString(): String { return "AgentContextInfo(consolidated=$consolidated, agentContexts=$agentContexts)" @@ -47,7 +46,10 @@ internal class ProxyPathManager(private val proxy: Proxy, private val isTestMode return pathMap.keys.toList() } - fun addPath(path: String, agentContext: AgentContext) { + fun addPath( + path: String, + agentContext: AgentContext, + ) { require(path.isNotEmpty()) { EMPTY_PATH_MSG } synchronized(pathMap) { @@ -57,7 +59,9 @@ internal class ProxyPathManager(private val proxy: Proxy, private val isTestMode pathMap[path] = AgentContextInfo(true, mutableListOf(agentContext)) } else { if (agentContext.consolidated != agentInfo.consolidated) - logger.warn { "Mismatch of agent context types: ${agentContext.consolidated} and ${agentInfo.consolidated}" } + logger.warn { + "Mismatch of agent context types: ${agentContext.consolidated} and ${agentInfo.consolidated}" + } else agentInfo.agentContexts += agentContext } @@ -70,7 +74,10 @@ internal class ProxyPathManager(private val proxy: Proxy, private val isTestMode } } - fun removePath(path: String, agentId: String): UnregisterPathResponse { + fun removePath( + path: String, + agentId: String, + ): UnregisterPathResponse { require(path.isNotEmpty()) { EMPTY_PATH_MSG } require(agentId.isNotEmpty()) { EMPTY_AGENT_ID_MSG } @@ -106,7 +113,10 @@ internal class ProxyPathManager(private val proxy: Proxy, private val isTestMode } // This is called on agent disconnects - fun removeFromPathManager(agentId: String, reason: String) { + fun removeFromPathManager( + agentId: String, + reason: String, + ) { require(agentId.isNotEmpty()) { EMPTY_AGENT_ID_MSG } val agentContext = proxy.agentContextManager.getAgentContext(agentId) @@ -142,11 +152,11 @@ internal class ProxyPathManager(private val proxy: Proxy, private val isTestMode } else { val maxPath = pathMap.keys.maxOfOrNull { it.length } ?: 0 "Proxy Path Map:\n" + "Path".padEnd(maxPath + 2) + "Agent Context\n" + - pathMap - .toSortedMap() - .map { c -> "/${c.key.padEnd(maxPath)} ${c.value.agentContexts.size} ${c.value}" } - .joinToString("\n\n") + pathMap + .toSortedMap() + .map { c -> "/${c.key.padEnd(maxPath)} ${c.value.agentContexts.size} ${c.value}" } + .joinToString("\n\n") } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyServerInterceptor.kt b/src/main/kotlin/io/prometheus/proxy/ProxyServerInterceptor.kt index 0ae80dea..f56efde7 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyServerInterceptor.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyServerInterceptor.kt @@ -28,11 +28,10 @@ import io.prometheus.proxy.ProxyServerTransportFilter.Companion.AGENT_ID import io.prometheus.proxy.ProxyServerTransportFilter.Companion.AGENT_ID_KEY internal class ProxyServerInterceptor : ServerInterceptor { - override fun interceptCall( call: ServerCall, requestHeaders: Metadata, - handler: ServerCallHandler + handler: ServerCallHandler, ): ServerCall.Listener = handler.startCall( object : ForwardingServerCall.SimpleForwardingServerCall(call) { @@ -42,10 +41,10 @@ internal class ProxyServerInterceptor : ServerInterceptor { super.sendHeaders(headers) } }, - requestHeaders + requestHeaders, ) companion object { internal val META_AGENT_ID_KEY = Metadata.Key.of(AGENT_ID, ASCII_STRING_MARSHALLER) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyServerTransportFilter.kt b/src/main/kotlin/io/prometheus/proxy/ProxyServerTransportFilter.kt index 8faac6f3..87ae2fe8 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyServerTransportFilter.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyServerTransportFilter.kt @@ -27,7 +27,6 @@ import io.prometheus.proxy.ProxyServiceImpl.Companion.UNKNOWN_ADDRESS import mu.two.KLogging internal class ProxyServerTransportFilter(private val proxy: Proxy) : ServerTransportFilter() { - override fun transportReady(attributes: Attributes): Attributes { val remoteAddress = attributes.get(REMOTE_ADDR_KEY)?.toString() ?: UNKNOWN_ADDRESS val agentContext = AgentContext(remoteAddress) diff --git a/src/main/kotlin/io/prometheus/proxy/ProxyServiceImpl.kt b/src/main/kotlin/io/prometheus/proxy/ProxyServiceImpl.kt index 9626e7df..6565e8d8 100644 --- a/src/main/kotlin/io/prometheus/proxy/ProxyServiceImpl.kt +++ b/src/main/kotlin/io/prometheus/proxy/ProxyServiceImpl.kt @@ -57,7 +57,6 @@ import java.util.concurrent.CancellationException import java.util.concurrent.atomic.AtomicLong internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.ProxyServiceCoroutineImplBase() { - override suspend fun connectAgent(request: Empty): Empty { if (proxy.options.transportFilterDisabled) { "Agent (false) and Proxy (true) do not have matching transportFilterDisabled config values".also { msg -> @@ -101,7 +100,7 @@ internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.P return io.prometheus.grpc.krotodc.RegisterAgentResponse( valid = valid, reason = request.agentId, - agentId = "Invalid agentId: ${request.agentId} (registerAgent)" + agentId = "Invalid agentId: ${request.agentId} (registerAgent)", ).apply { require(this.agentId.isNotEmpty()) { EMPTY_AGENT_ID_MSG } } .toProto() } @@ -120,7 +119,7 @@ internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.P pathId = if (valid) PATH_ID_GENERATOR.getAndIncrement() else -1, valid = valid, reason = "Invalid agentId: ${request.agentId} (registerPath)", - pathCount = proxy.pathManager.pathMapSize + pathCount = proxy.pathManager.pathMapSize, ).toProto() } @@ -131,7 +130,7 @@ internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.P logger.error { "Missing AgentContext for agentId: $agentId" } io.prometheus.grpc.krotodc.UnregisterPathResponse( valid = false, - reason = "Invalid agentId: $agentId (unregisterPath)" + reason = "Invalid agentId: $agentId (unregisterPath)", ) } else { proxy.pathManager.removePath(request.path, agentId).apply { agentContext.markActivityTime(false) } @@ -149,7 +148,7 @@ internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.P ?: logger.info { "sendHeartBeat() missing AgentContext agentId: ${request.agentId}" } HeartBeatResponse( valid = agentContext.isNotNull(), - reason = "Invalid agentId: ${request.agentId} (sendHeartBeat)" + reason = "Invalid agentId: ${request.agentId} (sendHeartBeat)", ).toProto() } @@ -206,7 +205,11 @@ internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.P .apply { val context = chunkedContextMap.remove(summaryScrapeId) check(context.isNotNull()) { "Missing chunked context with scrapeId: $summaryScrapeId" } - logger.debug { "Reading summary chunkCount: ${context.totalChunkCount} byteCount: ${context.totalByteCount} for scrapeId: $summaryScrapeId" } + logger.debug { + val ccnt = context.totalChunkCount + val bcnt = context.totalByteCount + "Reading summary chunkCount: $ccnt byteCount: $bcnt for scrapeId: $summaryScrapeId" + } context.applySummary(summaryChunkCount, summaryByteCount, summaryChecksum) proxy.scrapeRequestManager.assignScrapeResults(context.scrapeResults) } @@ -230,4 +233,4 @@ internal class ProxyServiceImpl(private val proxy: Proxy) : ProxyServiceGrpcKt.P private val PATH_ID_GENERATOR = AtomicLong(0L) internal const val UNKNOWN_ADDRESS = "Unknown" } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ScrapeRequestManager.kt b/src/main/kotlin/io/prometheus/proxy/ScrapeRequestManager.kt index 16ec3938..ecb7e2c9 100644 --- a/src/main/kotlin/io/prometheus/proxy/ScrapeRequestManager.kt +++ b/src/main/kotlin/io/prometheus/proxy/ScrapeRequestManager.kt @@ -52,4 +52,4 @@ internal class ScrapeRequestManager { } companion object : KLogging() -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/prometheus/proxy/ScrapeRequestWrapper.kt b/src/main/kotlin/io/prometheus/proxy/ScrapeRequestWrapper.kt index 8654a763..b0eb11aa 100644 --- a/src/main/kotlin/io/prometheus/proxy/ScrapeRequestWrapper.kt +++ b/src/main/kotlin/io/prometheus/proxy/ScrapeRequestWrapper.kt @@ -39,7 +39,7 @@ internal class ScrapeRequestWrapper( encodedQueryParams: String, authHeader: String, accept: String?, - debugEnabled: Boolean + debugEnabled: Boolean, ) { private val clock = Monotonic private val createTimeMark = clock.markNow() @@ -90,4 +90,4 @@ internal class ScrapeRequestWrapper( companion object { private val SCRAPE_ID_GENERATOR = AtomicLong(0L) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/AdminDefaultPathTest.kt b/src/test/kotlin/io/prometheus/AdminDefaultPathTest.kt index 0f1a83ca..182a5328 100644 --- a/src/test/kotlin/io/prometheus/AdminDefaultPathTest.kt +++ b/src/test/kotlin/io/prometheus/AdminDefaultPathTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -32,7 +32,6 @@ import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test class AdminDefaultPathTest { - private val agentConfigVals = agent.configVals.agent private val proxyConfigVals = proxy.configVals.proxy @@ -119,17 +118,16 @@ class AdminDefaultPathTest { } companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { startProxy(adminEnabled = true) }, - { startAgent(adminEnabled = true) } + proxySetup = { startProxy(adminEnabled = true) }, + agentSetup = { startAgent(adminEnabled = true) }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/AdminEmptyPathTest.kt b/src/test/kotlin/io/prometheus/AdminEmptyPathTest.kt index 859429c7..32c52e4d 100644 --- a/src/test/kotlin/io/prometheus/AdminEmptyPathTest.kt +++ b/src/test/kotlin/io/prometheus/AdminEmptyPathTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -29,7 +29,6 @@ import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test class AdminEmptyPathTest { - private val proxyConfigVals: ConfigVals.Proxy2 = proxy.configVals.proxy @Test @@ -83,12 +82,11 @@ class AdminEmptyPathTest { } companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { + proxySetup = { startProxy( adminEnabled = true, argv = listOf( @@ -96,15 +94,15 @@ class AdminEmptyPathTest { "-Dproxy.admin.pingPath=\"\"", "-Dproxy.admin.versionPath=\"\"", "-Dproxy.admin.healthCheckPath=\"\"", - "-Dproxy.admin.threadDumpPath=\"\"" - ) + "-Dproxy.admin.threadDumpPath=\"\"", + ), ) }, - { startAgent(adminEnabled = true) } + agentSetup = { startAgent(adminEnabled = true) }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/AdminNonDefaultPathTest.kt b/src/test/kotlin/io/prometheus/AdminNonDefaultPathTest.kt index d58f2ea1..bff3136b 100644 --- a/src/test/kotlin/io/prometheus/AdminNonDefaultPathTest.kt +++ b/src/test/kotlin/io/prometheus/AdminNonDefaultPathTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -33,7 +33,6 @@ import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test class AdminNonDefaultPathTest { - private val proxyConfigVals: ConfigVals.Proxy2 = proxy.configVals.proxy @Test @@ -90,12 +89,11 @@ class AdminNonDefaultPathTest { } companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { + proxySetup = { startProxy( adminEnabled = true, argv = listOf( @@ -103,15 +101,15 @@ class AdminNonDefaultPathTest { "-Dproxy.admin.pingPath=pingPath2", "-Dproxy.admin.versionPath=versionPath2", "-Dproxy.admin.healthCheckPath=healthCheckPath2", - "-Dproxy.admin.threadDumpPath=threadDumpPath2" - ) + "-Dproxy.admin.threadDumpPath=threadDumpPath2", + ), ) }, - { startAgent(adminEnabled = true) } + agentSetup = { startAgent(adminEnabled = true) }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/CommonCompanion.kt b/src/test/kotlin/io/prometheus/CommonCompanion.kt index 31d15d90..7d97a946 100644 --- a/src/test/kotlin/io/prometheus/CommonCompanion.kt +++ b/src/test/kotlin/io/prometheus/CommonCompanion.kt @@ -31,7 +31,11 @@ open class CommonCompanion : KLogging() { protected var proxy: Proxy by notNull() protected var agent: Agent by notNull() - protected fun setItUp(proxySetup: () -> Proxy, agentSetup: () -> Agent, actions: () -> Unit = {}) { + protected fun setItUp( + proxySetup: () -> Proxy, + agentSetup: () -> Agent, + actions: () -> Unit = {}, + ) { CollectorRegistry.defaultRegistry.clear() runBlocking { @@ -59,4 +63,4 @@ open class CommonCompanion : KLogging() { logger.info { "Stopped ${proxy.simpleClassName} and ${agent.simpleClassName}" } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/CommonTests.kt b/src/test/kotlin/io/prometheus/CommonTests.kt index 37bb7faa..f6c8962d 100644 --- a/src/test/kotlin/io/prometheus/CommonTests.kt +++ b/src/test/kotlin/io/prometheus/CommonTests.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -29,7 +29,6 @@ import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Test abstract class CommonTests(private val args: ProxyCallTestArgs) { - @Test fun proxyCallTest() = runBlocking { ProxyTests.proxyCallTest(args) } @@ -59,4 +58,4 @@ abstract class CommonTests(private val args: ProxyCallTestArgs) { const val MIN_DELAY_MILLIS = 400 const val MAX_DELAY_MILLIS = 600 } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/DataClassTest.kt b/src/test/kotlin/io/prometheus/DataClassTest.kt index e25dc702..e23b7b37 100644 --- a/src/test/kotlin/io/prometheus/DataClassTest.kt +++ b/src/test/kotlin/io/prometheus/DataClassTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -31,7 +31,6 @@ import org.amshove.kluent.shouldBeTrue import org.junit.jupiter.api.Test class DataClassTest { - private fun configVals(str: String): ConfigVals { val config = ConfigFactory.parseString(str, ConfigParseOptions.defaults().setSyntax(ConfigSyntax.CONF)) return ConfigVals(config.withFallback(ConfigFactory.load().resolve()).resolve()) diff --git a/src/test/kotlin/io/prometheus/InProcessTestNoAdminMetricsTest.kt b/src/test/kotlin/io/prometheus/InProcessTestNoAdminMetricsTest.kt index e4dd115b..fbedea5f 100644 --- a/src/test/kotlin/io/prometheus/InProcessTestNoAdminMetricsTest.kt +++ b/src/test/kotlin/io/prometheus/InProcessTestNoAdminMetricsTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -33,18 +33,18 @@ class InProcessTestNoAdminMetricsTest : @BeforeAll fun setUp() = setItUp( - { startProxy("nometrics") }, - { + proxySetup = { startProxy("nometrics") }, + agentSetup = { startAgent( serverName = "nometrics", scrapeTimeoutSecs = DEFAULT_TIMEOUT, - chunkContentSizeKbs = DEFAULT_CHUNK_SIZE + chunkContentSizeKbs = DEFAULT_CHUNK_SIZE, ) - } + }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/InProcessTestWithAdminMetricsTest.kt b/src/test/kotlin/io/prometheus/InProcessTestWithAdminMetricsTest.kt index 6c3a529b..16aebcf5 100644 --- a/src/test/kotlin/io/prometheus/InProcessTestWithAdminMetricsTest.kt +++ b/src/test/kotlin/io/prometheus/InProcessTestWithAdminMetricsTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -28,26 +28,25 @@ import org.junit.jupiter.api.BeforeAll class InProcessTestWithAdminMetricsTest : CommonTests(ProxyCallTestArgs(agent = agent, startPort = 10700, caller = simpleClassName)) { - companion object : CommonCompanion() { @JvmStatic @BeforeAll fun setUp() = setItUp( - { startProxy("withmetrics", adminEnabled = true, metricsEnabled = true) }, - { + proxySetup = { startProxy("withmetrics", adminEnabled = true, metricsEnabled = true) }, + agentSetup = { startAgent( serverName = "withmetrics", adminEnabled = true, metricsEnabled = true, scrapeTimeoutSecs = DEFAULT_TIMEOUT, - chunkContentSizeKbs = DEFAULT_CHUNK_SIZE + chunkContentSizeKbs = DEFAULT_CHUNK_SIZE, ) - } + }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/NettyTestNoAdminMetricsTest.kt b/src/test/kotlin/io/prometheus/NettyTestNoAdminMetricsTest.kt index a64eb940..7b242a33 100644 --- a/src/test/kotlin/io/prometheus/NettyTestNoAdminMetricsTest.kt +++ b/src/test/kotlin/io/prometheus/NettyTestNoAdminMetricsTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -30,27 +30,25 @@ class NettyTestNoAdminMetricsTest : CommonTests( ProxyCallTestArgs( agent = agent, startPort = 10900, - caller = simpleClassName - ) + caller = simpleClassName, + ), ) { - companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { startProxy() }, - { + proxySetup = { startProxy() }, + agentSetup = { startAgent( scrapeTimeoutSecs = DEFAULT_TIMEOUT, - chunkContentSizeKbs = DEFAULT_CHUNK_SIZE + chunkContentSizeKbs = DEFAULT_CHUNK_SIZE, ) - } + }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/NettyTestWithAdminMetricsTest.kt b/src/test/kotlin/io/prometheus/NettyTestWithAdminMetricsTest.kt index 3ed965b7..5b0d778a 100644 --- a/src/test/kotlin/io/prometheus/NettyTestWithAdminMetricsTest.kt +++ b/src/test/kotlin/io/prometheus/NettyTestWithAdminMetricsTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -40,10 +40,9 @@ class NettyTestWithAdminMetricsTest : CommonTests( ProxyCallTestArgs( agent = agent, startPort = 10300, - caller = simpleClassName - ) + caller = simpleClassName, + ), ) { - @Test fun adminDebugCallsTest() { runBlocking { @@ -66,35 +65,34 @@ class NettyTestWithAdminMetricsTest : CommonTests( } companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { + proxySetup = { startProxy( adminEnabled = true, debugEnabled = true, - metricsEnabled = true + metricsEnabled = true, ) }, - { + agentSetup = { startAgent( adminEnabled = true, debugEnabled = true, metricsEnabled = true, scrapeTimeoutSecs = DEFAULT_TIMEOUT, - chunkContentSizeKbs = DEFAULT_CHUNK_SIZE + chunkContentSizeKbs = DEFAULT_CHUNK_SIZE, ) }, - { + actions = { // Wait long enough to trigger heartbeat for code coverage sleep(15.seconds) - } + }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/OptionsTest.kt b/src/test/kotlin/io/prometheus/OptionsTest.kt index 8563788d..07b64065 100644 --- a/src/test/kotlin/io/prometheus/OptionsTest.kt +++ b/src/test/kotlin/io/prometheus/OptionsTest.kt @@ -27,7 +27,6 @@ import org.amshove.kluent.shouldBeTrue import org.junit.jupiter.api.Test class OptionsTest { - @Test fun verifyDefaultValues() { val configVals = readProxyOptions(listOf()) @@ -94,4 +93,4 @@ class OptionsTest { private fun readProxyOptions(argList: List) = ProxyOptions(argList).configVals private fun readAgentOptions(argList: List) = AgentOptions(argList, false).configVals -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/ProxyTests.kt b/src/test/kotlin/io/prometheus/ProxyTests.kt index f67ee702..cb1f99b2 100644 --- a/src/test/kotlin/io/prometheus/ProxyTests.kt +++ b/src/test/kotlin/io/prometheus/ProxyTests.kt @@ -66,17 +66,16 @@ class ProxyCallTestArgs( val sequentialQueryCount: Int = SEQUENTIAL_QUERY_COUNT, val parallelQueryCount: Int = PARALLEL_QUERY_COUNT, val startPort: Int = 9600, - val caller: String + val caller: String, ) internal object ProxyTests : KLogging() { - suspend fun timeoutTest( pathManager: AgentPathManager, caller: String, agentPort: Int = 9900, agentPath: String = "agent-timeout", - proxyPath: String = "proxy-timeout" + proxyPath: String = "proxy-timeout", ) { logger.debug { "Calling timeoutTest() from $caller" } @@ -153,7 +152,7 @@ internal object ProxyTests : KLogging() { call.respondText(content, Text.Plain) } } - } + }, ) } @@ -259,7 +258,11 @@ internal object ProxyTests : KLogging() { logger.info { "Finished shutting down ${httpServers.size} httpServers" } } - private suspend fun callProxy(httpClient: HttpClient, pathMap: Map, msg: String) { + private suspend fun callProxy( + httpClient: HttpClient, + pathMap: Map, + msg: String, + ) { logger.debug { "Launched $msg" } // Randomly choose one of the pathMap values @@ -275,4 +278,4 @@ internal object ProxyTests : KLogging() { } } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/SimpleTests.kt b/src/test/kotlin/io/prometheus/SimpleTests.kt index 643e5392..061cceb2 100644 --- a/src/test/kotlin/io/prometheus/SimpleTests.kt +++ b/src/test/kotlin/io/prometheus/SimpleTests.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -34,7 +34,6 @@ import org.amshove.kluent.shouldNotBeNull import kotlin.time.Duration.Companion.seconds internal object SimpleTests : KLogging() { - fun missingPathTest(caller: String) { logger.debug { "Calling missingPathTest() from $caller" } blockingGet("$PROXY_PORT/".withPrefix()) { response -> @@ -49,7 +48,10 @@ internal object SimpleTests : KLogging() { } } - suspend fun addRemovePathsTest(pathManager: AgentPathManager, caller: String) { + suspend fun addRemovePathsTest( + pathManager: AgentPathManager, + caller: String, + ) { logger.debug { "Calling addRemovePathsTest() from $caller" } // Take into account pre-existing paths already registered @@ -69,7 +71,11 @@ internal object SimpleTests : KLogging() { } } - suspend fun invalidAgentUrlTest(pathManager: AgentPathManager, caller: String, badPath: String = "badPath") { + suspend fun invalidAgentUrlTest( + pathManager: AgentPathManager, + caller: String, + badPath: String = "badPath", + ) { logger.debug { "Calling invalidAgentUrlTest() from $caller" } pathManager.registerPath(badPath, "33/metrics".withPrefix()) @@ -79,7 +85,10 @@ internal object SimpleTests : KLogging() { pathManager.unregisterPath(badPath) } - suspend fun threadedAddRemovePathsTest(pathManager: AgentPathManager, caller: String) { + suspend fun threadedAddRemovePathsTest( + pathManager: AgentPathManager, + caller: String, + ) { logger.debug { "Calling threadedAddRemovePathsTest() from $caller" } val paths: MutableList = mutableListOf() @@ -123,4 +132,4 @@ internal object SimpleTests : KLogging() { pathManager.pathMapSize() shouldBeEqualTo originalSize } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/TestConstants.kt b/src/test/kotlin/io/prometheus/TestConstants.kt index 7c1a7c39..cdef8a5c 100644 --- a/src/test/kotlin/io/prometheus/TestConstants.kt +++ b/src/test/kotlin/io/prometheus/TestConstants.kt @@ -26,11 +26,11 @@ object TestConstants { const val DEFAULT_TIMEOUT = 3 const val DEFAULT_CHUNK_SIZE = 5 - private const val travisFile = "etc/test-configs/travis.conf" - private const val junitFile = "etc/test-configs/junit-test.conf" - private const val ghPrefix = "https://raw.githubusercontent.com/pambrose/prometheus-proxy/master/" + private const val TRAVIS_FILE = "etc/test-configs/travis.conf" + private const val JUNIT_FILE = "etc/test-configs/junit-test.conf" + private const val GH_PREFIX = "https://raw.githubusercontent.com/pambrose/prometheus-proxy/master/" - val CONFIG_ARG = listOf("--config", "${if (File(travisFile).exists()) "" else ghPrefix}$travisFile") + val CONFIG_ARG = listOf("--config", "${if (File(TRAVIS_FILE).exists()) "" else GH_PREFIX}$TRAVIS_FILE") - val OPTIONS_CONFIG = "${if (File(junitFile).exists()) ghPrefix else ""}$junitFile" + val OPTIONS_CONFIG = "${if (File(JUNIT_FILE).exists()) GH_PREFIX else ""}$JUNIT_FILE" } diff --git a/src/test/kotlin/io/prometheus/TestUtils.kt b/src/test/kotlin/io/prometheus/TestUtils.kt index c7e1267e..8f0a7c6b 100644 --- a/src/test/kotlin/io/prometheus/TestUtils.kt +++ b/src/test/kotlin/io/prometheus/TestUtils.kt @@ -34,7 +34,7 @@ object TestUtils : KLogging() { adminEnabled: Boolean = false, debugEnabled: Boolean = false, metricsEnabled: Boolean = false, - argv: List = emptyList() + argv: List = emptyList(), ): Proxy { logger.apply { info { getBanner("banners/proxy.txt", logger) } @@ -49,13 +49,13 @@ object TestUtils : KLogging() { add("-Dproxy.admin.enabled=$adminEnabled") add("-Dproxy.admin.debugEnabled=$debugEnabled") add("-Dproxy.metrics.enabled=$metricsEnabled") - } + }, ) return Proxy( options = proxyOptions, proxyHttpPort = PROXY_PORT, inProcessServerName = serverName, - testMode = true + testMode = true, ) { startSync() } } @@ -66,7 +66,7 @@ object TestUtils : KLogging() { metricsEnabled: Boolean = false, scrapeTimeoutSecs: Int = -1, chunkContentSizeKbs: Int = -1, - argv: List = emptyList() + argv: List = emptyList(), ): Agent { logger.apply { info { getBanner("banners/agent.txt", logger) } @@ -74,7 +74,7 @@ object TestUtils : KLogging() { } val agentOptions = AgentOptions( - mutableListOf() + args = mutableListOf() .apply { addAll(TestConstants.CONFIG_ARG) addAll(argv) @@ -86,7 +86,7 @@ object TestUtils : KLogging() { if (chunkContentSizeKbs != -1) add("-Dagent.chunkContentSizeKbs=$chunkContentSizeKbs") }, - false + exitOnMissingConfig = false, ) return Agent(options = agentOptions, inProcessServerName = serverName, testMode = true) { startSync() } } @@ -100,5 +100,4 @@ fun exceptionHandler(logger: KLogger) = logger.warn(e) { "CoroutineExceptionHandler caught: $e" } } -fun String.withPrefix(prefix: String = "http://localhost:") = - if (this.startsWith(prefix)) this else (prefix + this) \ No newline at end of file +fun String.withPrefix(prefix: String = "http://localhost:") = if (this.startsWith(prefix)) this else (prefix + this) diff --git a/src/test/kotlin/io/prometheus/TlsNoMutualAuthTest.kt b/src/test/kotlin/io/prometheus/TlsNoMutualAuthTest.kt index b73a6885..a0aa5dff 100644 --- a/src/test/kotlin/io/prometheus/TlsNoMutualAuthTest.kt +++ b/src/test/kotlin/io/prometheus/TlsNoMutualAuthTest.kt @@ -4,9 +4,9 @@ * Licensed 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. @@ -30,17 +30,15 @@ class TlsNoMutualAuthTest : CommonTests( ProxyCallTestArgs( agent = agent, startPort = 10200, - caller = simpleClassName - ) + caller = simpleClassName, + ), ) { - companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { + proxySetup = { startProxy( serverName = "nomutualauth", argv = listOf( @@ -49,11 +47,11 @@ class TlsNoMutualAuthTest : CommonTests( "--cert", "testing/certs/server1.pem", "--key", - "testing/certs/server1.key" - ) + "testing/certs/server1.key", + ), ) }, - { + agentSetup = { startAgent( serverName = "nomutualauth", scrapeTimeoutSecs = DEFAULT_TIMEOUT, @@ -64,14 +62,14 @@ class TlsNoMutualAuthTest : CommonTests( "--trust", "testing/certs/ca.pem", "--override", - "foo.test.google.fr" - ) + "foo.test.google.fr", + ), ) - } + }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/prometheus/TlsWithMutualAuthTest.kt b/src/test/kotlin/io/prometheus/TlsWithMutualAuthTest.kt index e89df844..35ccdf61 100644 --- a/src/test/kotlin/io/prometheus/TlsWithMutualAuthTest.kt +++ b/src/test/kotlin/io/prometheus/TlsWithMutualAuthTest.kt @@ -30,17 +30,15 @@ class TlsWithMutualAuthTest : CommonTests( ProxyCallTestArgs( agent = agent, startPort = 10800, - caller = simpleClassName - ) + caller = simpleClassName, + ), ) { - companion object : CommonCompanion() { - @JvmStatic @BeforeAll fun setUp() = setItUp( - { + proxySetup = { startProxy( serverName = "withmutualauth", argv = listOf( @@ -51,11 +49,11 @@ class TlsWithMutualAuthTest : CommonTests( "--key", "testing/certs/server1.key", "--trust", - "testing/certs/ca.pem" - ) + "testing/certs/ca.pem", + ), ) }, - { + agentSetup = { startAgent( serverName = "withmutualauth", scrapeTimeoutSecs = DEFAULT_TIMEOUT, @@ -70,14 +68,14 @@ class TlsWithMutualAuthTest : CommonTests( "--trust", "testing/certs/ca.pem", "--override", - "foo.test.google.fr" - ) + "foo.test.google.fr", + ), ) - } + }, ) @JvmStatic @AfterAll fun takeDown() = takeItDown() } -} \ No newline at end of file +}