From e17f4b122f2994a17e0ff017145657738ec3923a Mon Sep 17 00:00:00 2001 From: Paul Ambrose Date: Thu, 2 Nov 2023 17:31:29 -0700 Subject: [PATCH] 1.19.0 (#96) * Upgrade to kotlin 1.9.20 * Upgrade to kotlinter 4.0.0 * Update jars --- .editorconfig | 17 + Makefile | 7 +- README.md | 15 +- bin/docker-agent.sh | 2 +- bin/docker-proxy.sh | 2 +- build.gradle | 385 +++++++++--------- docs/release.md | 2 +- etc/compose/proxy.yml | 2 +- gradle.properties | 33 +- gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 63375 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 5 +- src/main/kotlin/io/prometheus/Agent.kt | 85 ++-- src/main/kotlin/io/prometheus/Proxy.kt | 64 +-- .../agent/AgentClientInterceptor.kt | 16 +- .../agent/AgentConnectionContext.kt | 2 +- .../io/prometheus/agent/AgentGrpcService.kt | 123 +++--- .../io/prometheus/agent/AgentHttpService.kt | 22 +- .../io/prometheus/agent/AgentMetrics.kt | 5 +- .../io/prometheus/agent/AgentOptions.kt | 32 +- .../io/prometheus/agent/AgentPathManager.kt | 16 +- .../io/prometheus/agent/EmbeddedAgentInfo.kt | 2 +- .../agent/RequestFailureException.kt | 6 +- .../kotlin/io/prometheus/agent/SslSettings.kt | 20 +- .../agent/TrustAllX509TrustManager.kt | 14 +- .../io/prometheus/common/BaseOptions.kt | 19 +- .../io/prometheus/common/ConfigWrappers.kt | 118 +++--- .../kotlin/io/prometheus/common/Constants.kt | 2 +- .../kotlin/io/prometheus/common/EnvVars.kt | 4 +- .../io/prometheus/common/GrpcObjects.kt | 51 ++- .../io/prometheus/common/ScrapeResults.kt | 23 +- .../io/prometheus/common/TypeAliases.kt | 2 +- src/main/kotlin/io/prometheus/common/Utils.kt | 7 +- .../io/prometheus/proxy/AgentContext.kt | 5 +- .../proxy/AgentContextCleanupService.kt | 11 +- .../prometheus/proxy/AgentContextManager.kt | 11 +- .../io/prometheus/proxy/ChunkedContext.kt | 17 +- .../io/prometheus/proxy/ProxyGrpcService.kt | 7 +- .../io/prometheus/proxy/ProxyHttpConfig.kt | 121 +++--- .../io/prometheus/proxy/ProxyMetrics.kt | 11 +- .../io/prometheus/proxy/ProxyOptions.kt | 3 +- .../io/prometheus/proxy/ProxyPathManager.kt | 30 +- .../proxy/ProxyServerInterceptor.kt | 7 +- .../proxy/ProxyServerTransportFilter.kt | 1 - .../io/prometheus/proxy/ProxyServiceImpl.kt | 17 +- .../prometheus/proxy/ScrapeRequestManager.kt | 2 +- .../prometheus/proxy/ScrapeRequestWrapper.kt | 4 +- .../io/prometheus/AdminDefaultPathTest.kt | 12 +- .../io/prometheus/AdminEmptyPathTest.kt | 16 +- .../io/prometheus/AdminNonDefaultPathTest.kt | 16 +- .../kotlin/io/prometheus/CommonCompanion.kt | 8 +- src/test/kotlin/io/prometheus/CommonTests.kt | 7 +- .../kotlin/io/prometheus/DataClassTest.kt | 5 +- .../InProcessTestNoAdminMetricsTest.kt | 14 +- .../InProcessTestWithAdminMetricsTest.kt | 15 +- .../prometheus/NettyTestNoAdminMetricsTest.kt | 20 +- .../NettyTestWithAdminMetricsTest.kt | 24 +- src/test/kotlin/io/prometheus/OptionsTest.kt | 3 +- src/test/kotlin/io/prometheus/ProxyTests.kt | 15 +- src/test/kotlin/io/prometheus/SimpleTests.kt | 23 +- .../kotlin/io/prometheus/TestConstants.kt | 10 +- src/test/kotlin/io/prometheus/TestUtils.kt | 15 +- .../io/prometheus/TlsNoMutualAuthTest.kt | 26 +- .../io/prometheus/TlsWithMutualAuthTest.kt | 22 +- 64 files changed, 865 insertions(+), 739 deletions(-) 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 c1962a79e29d3e0ab67b14947c167a862655af9b..033e24c4cdf41af1ab109bc7f253b2b887023340 100644 GIT binary patch delta 16170 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 delta 14892 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 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 +}