@@ -19,10 +19,11 @@ package kamon.instrumentation.play
19
19
import java .time .Duration
20
20
import java .util .concurrent .atomic .AtomicLong
21
21
22
+ import com .typesafe .config .Config
22
23
import io .netty .channel .Channel
23
24
import io .netty .handler .codec .http .{HttpRequest , HttpResponse }
24
25
import io .netty .util .concurrent .GenericFutureListener
25
- import kamon .Kamon
26
+ import kamon .{ ClassLoading , Kamon }
26
27
import kamon .context .Storage
27
28
import kamon .instrumentation .akka .http .ServerFlowWrapper
28
29
import kamon .instrumentation .context .{CaptureCurrentTimestampOnExit , HasTimestamp }
@@ -33,12 +34,13 @@ import kanela.agent.api.instrumentation.InstrumentationBuilder
33
34
import kanela .agent .api .instrumentation .classloader .ClassRefiner
34
35
import kanela .agent .api .instrumentation .mixin .Initializer
35
36
import kanela .agent .libs .net .bytebuddy .asm .Advice
37
+ import org .slf4j .LoggerFactory
36
38
import play .api .mvc .RequestHeader
37
39
import play .api .routing .{HandlerDef , Router }
38
40
import play .core .server .NettyServer
39
41
40
42
import scala .collection .JavaConverters .asScalaBufferConverter
41
- import scala .collection . concurrent . TrieMap
43
+ import scala .util . Try
42
44
import scala .util .{Failure , Success }
43
45
44
46
class PlayServerInstrumentation extends InstrumentationBuilder {
@@ -243,32 +245,61 @@ object HasServerInstrumentation {
243
245
244
246
object GenerateOperationNameOnFilterHandler {
245
247
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
+ }
248
265
249
266
@ Advice .OnMethodEnter
250
267
def enter (@ Advice .Argument (0 ) request : RequestHeader ): Unit = {
251
268
request.attrs.get(Router .Attrs .HandlerDef ).map(handler => {
252
269
val span = Kamon .currentSpan()
253
- span.name(generateOperationName(handler))
270
+ span.name(_routerNameGenerator. generateOperationName(handler))
254
271
span.takeSamplingDecision()
255
272
})
256
273
}
257
274
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
-
264
275
}
265
276
266
277
object 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
+
267
297
@ Advice .OnMethodEnter
268
298
def enter (@ Advice .Argument (0 ) request : akka.http.scaladsl.model.HttpRequest ): Unit = {
269
299
val span = Kamon .currentSpan()
270
- span.name(request.uri.toRelative.toString )
300
+ span.name(_grpcRouterNameGenerator.generateOperationName(request) )
271
301
span.tag(" http.protocol" , request.protocol.value)
272
302
span.takeSamplingDecision()
273
303
}
304
+
274
305
}
0 commit comments