@@ -19,10 +19,11 @@ package kamon.instrumentation.play
1919import java .time .Duration
2020import java .util .concurrent .atomic .AtomicLong
2121
22+ import com .typesafe .config .Config
2223import io .netty .channel .Channel
2324import io .netty .handler .codec .http .{HttpRequest , HttpResponse }
2425import io .netty .util .concurrent .GenericFutureListener
25- import kamon .Kamon
26+ import kamon .{ ClassLoading , Kamon }
2627import kamon .context .Storage
2728import kamon .instrumentation .akka .http .ServerFlowWrapper
2829import kamon .instrumentation .context .{CaptureCurrentTimestampOnExit , HasTimestamp }
@@ -33,12 +34,13 @@ import kanela.agent.api.instrumentation.InstrumentationBuilder
3334import kanela .agent .api .instrumentation .classloader .ClassRefiner
3435import kanela .agent .api .instrumentation .mixin .Initializer
3536import kanela .agent .libs .net .bytebuddy .asm .Advice
37+ import org .slf4j .LoggerFactory
3638import play .api .mvc .RequestHeader
3739import play .api .routing .{HandlerDef , Router }
3840import play .core .server .NettyServer
3941
4042import scala .collection .JavaConverters .asScalaBufferConverter
41- import scala .collection . concurrent . TrieMap
43+ import scala .util . Try
4244import scala .util .{Failure , Success }
4345
4446class PlayServerInstrumentation extends InstrumentationBuilder {
@@ -243,32 +245,61 @@ object HasServerInstrumentation {
243245
244246object GenerateOperationNameOnFilterHandler {
245247
246- private val _operationNameCache = TrieMap .empty[String , String ]
247- private val _normalizePattern = """ \$([^<]+)<[^>]+>""" .r
248+ private val defaultRouterNameGenerator = new DefaultRouterOperationNameGenerator ()
249+ private val _logger = LoggerFactory .getLogger(GenerateOperationNameOnFilterHandler .getClass)
250+
251+ @ volatile private var _routerNameGenerator : RouterOperationNameGenerator = rebuildRouterNameGenerator(Kamon .config())
252+
253+ Kamon .onReconfigure(newConfig => _routerNameGenerator = rebuildRouterNameGenerator(newConfig))
254+
255+ private def rebuildRouterNameGenerator (config : Config ): RouterOperationNameGenerator = {
256+ val nameGeneratorClazz = config.getString(" kamon.instrumentation.play.http.server.extra.name-generator" )
257+ Try (ClassLoading .createInstance[RouterOperationNameGenerator ](nameGeneratorClazz)) match {
258+ case Failure (exception) =>
259+ _logger.error(s " Exception occurred on $nameGeneratorClazz instance creation, used default " , exception)
260+ defaultRouterNameGenerator
261+ case Success (value) =>
262+ value
263+ }
264+ }
248265
249266 @ Advice .OnMethodEnter
250267 def enter (@ Advice .Argument (0 ) request : RequestHeader ): Unit = {
251268 request.attrs.get(Router .Attrs .HandlerDef ).map(handler => {
252269 val span = Kamon .currentSpan()
253- span.name(generateOperationName(handler))
270+ span.name(_routerNameGenerator. generateOperationName(handler))
254271 span.takeSamplingDecision()
255272 })
256273 }
257274
258- private def generateOperationName (handlerDef : HandlerDef ): String =
259- _operationNameCache.getOrElseUpdate(handlerDef.path, {
260- // Convert paths of form /foo/bar/$paramname<regexp>/blah to /foo/bar/paramname/blah
261- _normalizePattern.replaceAllIn(handlerDef.path, " $1" )
262- })
263-
264275}
265276
266277object GenerateGRPCOperationName {
278+
279+ private val defaultGrpcRouterNameGenerator = new DefaultGrpcRouterNameGenerator ()
280+ private val _logger = LoggerFactory .getLogger(GenerateOperationNameOnFilterHandler .getClass)
281+
282+ @ volatile private var _grpcRouterNameGenerator : GrpcRouterNameGenerator = rebuildRouterNameGenerator(Kamon .config())
283+
284+ Kamon .onReconfigure(newConfig => _grpcRouterNameGenerator = rebuildRouterNameGenerator(newConfig))
285+
286+ private def rebuildRouterNameGenerator (config : Config ): GrpcRouterNameGenerator = {
287+ val nameGeneratorClazz = config.getString(" kamon.instrumentation.play.http.server.extra.grpc-name-generator" )
288+ Try (ClassLoading .createInstance[GrpcRouterNameGenerator ](nameGeneratorClazz)) match {
289+ case Failure (exception) =>
290+ _logger.error(s " Exception occurred on $nameGeneratorClazz instance creation, used default " , exception)
291+ defaultGrpcRouterNameGenerator
292+ case Success (value) =>
293+ value
294+ }
295+ }
296+
267297 @ Advice .OnMethodEnter
268298 def enter (@ Advice .Argument (0 ) request : akka.http.scaladsl.model.HttpRequest ): Unit = {
269299 val span = Kamon .currentSpan()
270- span.name(request.uri.toRelative.toString )
300+ span.name(_grpcRouterNameGenerator.generateOperationName(request) )
271301 span.tag(" http.protocol" , request.protocol.value)
272302 span.takeSamplingDecision()
273303 }
304+
274305}
0 commit comments