1
- package de .innfactory .bootstrapplay2 .filters
1
+ package de .innfactory .bootstrapplay2 .filters . tracing
2
2
3
3
import akka .stream .Materializer
4
4
import com .google .cloud .opentelemetry .shadow .semconv .trace .attributes .SemanticAttributes
@@ -11,6 +11,9 @@ import de.innfactory.play.tracing.GoogleTracingIdentifier.GoogleAttributes.{
11
11
}
12
12
import de .innfactory .play .tracing .GoogleTracingIdentifier .XTRACINGID
13
13
import de .innfactory .play .tracing .{OpentelemetryProvider , TraceLogger }
14
+ import de .innfactory .smithy4play
15
+ import de .innfactory .smithy4play .middleware .MiddlewareBase
16
+ import de .innfactory .smithy4play .{EndpointResult , RouteResult , RoutingContext }
14
17
import io .opentelemetry .api .GlobalOpenTelemetry
15
18
import io .opentelemetry .context .Context
16
19
import org .joda .time .DateTime
@@ -19,21 +22,30 @@ import play.api.mvc._
19
22
20
23
import javax .inject .Inject
21
24
import scala .concurrent .ExecutionContext .Implicits .global
22
- import scala .concurrent .Future
23
25
24
- class TracingFilter @ Inject () (config : Config , implicit val mat : Materializer ) extends Filter with ImplicitLogContext {
26
+ class TracingFilter @ Inject () (config : Config , implicit val mat : Materializer )
27
+ extends MiddlewareBase
28
+ with ImplicitLogContext {
25
29
private val healthEndpoints : Map [String , Seq [String ]] = Map (" GET" -> Seq (" /" , " /liveness" , " /readiness" ))
26
30
private val healthLogger = Logger (" health" ).logger
27
31
private val configAccessStatus = config.getIntList(" logging.access.statusList" )
28
32
29
- def apply (next : RequestHeader => Future [Result ])(request : RequestHeader ): Future [Result ] =
30
- if (! healthEndpoints.getOrElse(request.method, Seq .empty).contains(request.path))
31
- handleLoggingAndTracing(next)(request)
32
- else
33
- handleHealthChecksLogging(next, request)
34
-
35
- def handleLoggingAndTracing (next : RequestHeader => Future [Result ])(request : RequestHeader ): Future [Result ] = {
33
+ override protected def logic (
34
+ r : RoutingContext ,
35
+ next : RoutingContext => RouteResult [smithy4play.EndpointResult ]
36
+ ): RouteResult [smithy4play.EndpointResult ] = if (
37
+ ! healthEndpoints.getOrElse(r.requestHeader.method, Seq .empty).contains(r.requestHeader.path)
38
+ )
39
+ handleLoggingAndTracing(next, r)
40
+ else
41
+ handleHealthChecksLogging(next, r)
42
+
43
+ def handleLoggingAndTracing (
44
+ next : RoutingContext => RouteResult [smithy4play.EndpointResult ],
45
+ r : RoutingContext
46
+ ): RouteResult [smithy4play.EndpointResult ] = {
36
47
// Start Trace Span Root
48
+ val request = r.requestHeader
37
49
val span = OpentelemetryProvider .getTracer().spanBuilder(request.path).startSpan()
38
50
val latencyRecorder = OpentelemetryProvider
39
51
.getMeter()
@@ -68,21 +80,25 @@ class TracingFilter @Inject() (config: Config, implicit val mat: Materializer) e
68
80
69
81
map.addOne(xTracingId)
70
82
83
+ // Check Start Time
84
+ val start = DateTime .now
85
+
71
86
// Call Next Filter with new Headers
72
- val result = next(request.withHeaders(request.headers.add(map.toList: _* )))
87
+ val result = next(
88
+ r.copy(
89
+ requestHeader = request.withHeaders(request.headers.add(map.toList: _* ))
90
+ )
91
+ )
73
92
74
93
val logger = new TraceLogger (Some (span))
75
94
val msg : String = logStart(request, xTracingId)(logger)
76
95
77
- // Check Start Time
78
- val start = DateTime .now
79
-
80
96
// Process Result
81
97
result.map { res =>
82
98
// Add more Attributes to trace
83
- span.setAttribute(HTTP_STATUS_CODE , res.header.status )
84
- span.setAttribute(STATUS , res.header.status )
85
- span.setAttribute(HTTP_RESPONSE_SIZE , res.body.contentLength. getOrElse(0L ))
99
+ span.setAttribute(HTTP_STATUS_CODE , res.code )
100
+ span.setAttribute(STATUS , res.code )
101
+ span.setAttribute(HTTP_RESPONSE_SIZE , res.body.map(_.length). getOrElse(0 ))
86
102
87
103
// Finish Root Span
88
104
span.end()
@@ -96,17 +112,21 @@ class TracingFilter @Inject() (config: Config, implicit val mat: Materializer) e
96
112
logResult(xTracingId, msg, res, request)(logger)
97
113
98
114
// Add xTracingId to Result Header
99
- res.withHeaders(xTracingId)
115
+ res.copy(
116
+ headers = res.headers + xTracingId
117
+ )
100
118
}
101
119
102
120
}
103
121
104
- private def handleHealthChecksLogging (next : RequestHeader => Future [Result ], request : RequestHeader ) = {
105
- // Handle Health Check Logging
106
- val result = next(request)
107
- result.map { res =>
108
- if (res.header.status != 200 ) healthLogger.error(s " [HealthCheck] FAILED with ${res.header.status}" )
109
- res
122
+ private def handleHealthChecksLogging (
123
+ next : RoutingContext => RouteResult [smithy4play.EndpointResult ],
124
+ r : RoutingContext
125
+ ): RouteResult [smithy4play.EndpointResult ] = {
126
+ val result = next.apply(r)
127
+ result.leftMap { e =>
128
+ if (e.statusCode != 200 ) healthLogger.error(s " [HealthCheck] FAILED with ${e.statusCode}" )
129
+ e
110
130
}
111
131
}
112
132
@@ -118,12 +138,11 @@ class TracingFilter @Inject() (config: Config, implicit val mat: Materializer) e
118
138
msg
119
139
}
120
140
121
- private def logResult (xTracingId : (String , String ), msg : String , res : Result , req : RequestHeader )(
141
+ private def logResult (xTracingId : (String , String ), msg : String , res : EndpointResult , req : RequestHeader )(
122
142
logger : TraceLogger
123
143
): Unit =
124
- if (configAccessStatus.contains(res.header.status ))
125
- logger.warn(s " [Trace- ${xTracingId._2}] $msg status= ${res.header.status } END " )
144
+ if (configAccessStatus.contains(res.code ))
145
+ logger.warn(s " [Trace- ${xTracingId._2}] $msg status= ${res.code } END " )
126
146
else
127
- logger.info(s " [Trace- ${xTracingId._2}] $msg status= ${res.header.status} END " )
128
-
147
+ logger.info(s " [Trace- ${xTracingId._2}] $msg status= ${res.code} END " )
129
148
}
0 commit comments