ktor net attribute extraction (#5027)
* ktor net attribute extraction * spotless
This commit is contained in:
parent
12c15b226f
commit
55e44d790c
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.ktor.v1_0
|
package io.opentelemetry.instrumentation.ktor.v1_0
|
||||||
|
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.request.*
|
import io.ktor.request.*
|
||||||
import io.opentelemetry.context.propagation.TextMapGetter
|
import io.opentelemetry.context.propagation.TextMapGetter
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.ktor.v1_0
|
||||||
|
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
// Source: Regular Expressions Cookbook 2nd edition - 8.17.
|
||||||
|
// Matching IPv6 Addresses
|
||||||
|
private val ipv6 = Pattern.compile( // Non Compressed
|
||||||
|
"^(?:(?:(?:[A-F0-9]{1,4}:){6}" + // Compressed with at most 6 colons
|
||||||
|
"|(?=(?:[A-F0-9]{0,4}:){0,6}" + // and 4 bytes and anchored
|
||||||
|
"(?:[0-9]{1,3}\\.){3}[0-9]{1,3}(?![:.\\w]))" + // and at most 1 double colon
|
||||||
|
"(([0-9A-F]{1,4}:){0,5}|:)((:[0-9A-F]{1,4}){1,5}:|:)" + // Compressed with 7 colons and 5 numbers
|
||||||
|
"|::(?:[A-F0-9]{1,4}:){5})" + // 255.255.255.
|
||||||
|
"(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}" + // 255
|
||||||
|
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" + // Standard
|
||||||
|
"|(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}" + // Compressed with at most 7 colons and anchored
|
||||||
|
"|(?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}(?![:.\\w]))" + // and at most 1 double colon
|
||||||
|
"(([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:)" + // Compressed with 8 colons
|
||||||
|
"|(?:[A-F0-9]{1,4}:){7}:|:(:[A-F0-9]{1,4}){7})(?![:.\\w])\$",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
)
|
||||||
|
|
||||||
|
// Source: Regular Expressions Cookbook 2nd edition - 8.16.
|
||||||
|
// Matching IPv4 Addresses
|
||||||
|
private val ipv4 = Pattern.compile(
|
||||||
|
"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}" +
|
||||||
|
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\$"
|
||||||
|
)
|
||||||
|
|
||||||
|
fun isIpAddress(address: String): Boolean {
|
||||||
|
return ipv4.matcher(address).matches() || ipv6.matcher(address).matches()
|
||||||
|
}
|
|
@ -5,11 +5,9 @@
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.ktor.v1_0
|
package io.opentelemetry.instrumentation.ktor.v1_0
|
||||||
|
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.features.*
|
import io.ktor.features.*
|
||||||
import io.ktor.request.*
|
import io.ktor.request.*
|
||||||
import io.ktor.response.*
|
import io.ktor.response.*
|
||||||
import io.ktor.routing.*
|
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.http.CapturedHttpHeaders
|
import io.opentelemetry.instrumentation.api.instrumenter.http.CapturedHttpHeaders
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor
|
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.ktor.v1_0
|
package io.opentelemetry.instrumentation.ktor.v1_0
|
||||||
|
|
||||||
import io.ktor.features.*
|
|
||||||
import io.ktor.request.*
|
import io.ktor.request.*
|
||||||
import io.ktor.response.*
|
import io.ktor.response.*
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesExtractor
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesExtractor
|
||||||
|
@ -16,15 +15,23 @@ internal class KtorNetServerAttributesExtractor : NetServerAttributesExtractor<A
|
||||||
return SemanticAttributes.NetTransportValues.IP_TCP
|
return SemanticAttributes.NetTransportValues.IP_TCP
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun peerName(request: ApplicationRequest): String {
|
override fun peerName(request: ApplicationRequest): String? {
|
||||||
return request.origin.host
|
var remote = request.local.remoteHost
|
||||||
|
if (remote != null && "unknown" != remote && !isIpAddress(remote)) {
|
||||||
|
return remote
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun peerPort(request: ApplicationRequest): Int {
|
override fun peerPort(request: ApplicationRequest): Int? {
|
||||||
return request.origin.port
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun peerIp(request: ApplicationRequest): String {
|
override fun peerIp(request: ApplicationRequest): String? {
|
||||||
return request.origin.remoteHost
|
var remote = request.local.remoteHost
|
||||||
|
if (remote != null && "unknown" != remote && isIpAddress(remote)) {
|
||||||
|
return remote
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.ktor.v1_0
|
||||||
|
|
||||||
|
import spock.lang.Specification
|
||||||
|
|
||||||
|
class IpAddressUtilTest extends Specification {
|
||||||
|
|
||||||
|
def "test ip address"() {
|
||||||
|
expect:
|
||||||
|
assert IpAddressUtilKt.isIpAddress("2001:0660:7401:0200:0000:0000:0edf:bdd7")
|
||||||
|
assert !IpAddressUtilKt.isIpAddress("2001:0660:7401:0200:0000:0000:0edf:bdd7:33")
|
||||||
|
assert IpAddressUtilKt.isIpAddress("127.0.0.1")
|
||||||
|
assert !IpAddressUtilKt.isIpAddress("127.0.0.1.1")
|
||||||
|
assert !IpAddressUtilKt.isIpAddress("localhost")
|
||||||
|
}
|
||||||
|
}
|
|
@ -679,7 +679,7 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
|
||||||
}
|
}
|
||||||
// net.peer.name resolves to "127.0.0.1" on windows which is same as net.peer.ip so then not captured
|
// net.peer.name resolves to "127.0.0.1" on windows which is same as net.peer.ip so then not captured
|
||||||
"$SemanticAttributes.NET_PEER_NAME" { it == null || it == address.host }
|
"$SemanticAttributes.NET_PEER_NAME" { it == null || it == address.host }
|
||||||
"$SemanticAttributes.NET_PEER_PORT" { it == null || it instanceof Long }
|
"$SemanticAttributes.NET_PEER_PORT" { it == null || (it instanceof Long && it != port) }
|
||||||
"$SemanticAttributes.NET_PEER_IP" { it == null || it == peerIp(endpoint) } // Optional
|
"$SemanticAttributes.NET_PEER_IP" { it == null || it == peerIp(endpoint) } // Optional
|
||||||
|
|
||||||
"$SemanticAttributes.HTTP_CLIENT_IP" { it == null || it == TEST_CLIENT_IP }
|
"$SemanticAttributes.HTTP_CLIENT_IP" { it == null || it == TEST_CLIENT_IP }
|
||||||
|
|
Loading…
Reference in New Issue