1
1
# Tracing - interop with Java-instrumented libraries
2
2
3
- ### Glossary
3
+ ## Glossary
4
4
5
5
| Name | Description |
6
6
| ------------------------------------------| --------------------------------------------------------------|
@@ -74,7 +74,7 @@ val run: IO[Unit] =
74
74
## How to use OpenTelemetry Java context with otel4s
75
75
76
76
There are several scenarios when you want to run an effect with an explicit OpenTelemetry Java context.
77
- For example, when you need to materialize an effect inside [ Play Framework ] [ play-framework ] request handler.
77
+ For example, when you need to materialize an effect inside [ Pekko HTTP ] [ pekko-http ] request handler.
78
78
79
79
To make it work, we can define a utility method:
80
80
``` scala mdoc:silent:reset
@@ -91,27 +91,55 @@ def withJContext[F[_], A](ctx: JContext)(fa: F[A])(implicit L: Local[F, Context]
91
91
92
92
_____
93
93
94
- Let's say you use [ Play Framework] [ play-framework ] and want to materialize an ` IO ` using the current tracing context:
95
- ``` scala
96
- class Application @ Inject () (implicit
97
- cc : ControllerComponents ,
98
- tracer : Tracer [IO ],
99
- local : Local [IO , Cointext ]
100
- ) extends AbstractController (cc) {
101
-
102
- def findUser (userId : Long ) = Action {
103
- val current = JContext .current() // get current JContext
104
- withJContext(current)(search(userId)).unsafeRunSync() // materialize IO
105
- }
106
-
107
- def search (userId : Long ): IO [String ] =
108
- tracer.span(" find-user" ).surround {
109
- IO .pure(" the-result" )
94
+ Let's say you use [ Pekko HTTP] [ pekko-http ] and want to materialize an ` IO ` using the current tracing context:
95
+ ``` scala mdoc:silent:reset
96
+ import cats .effect .{Async , IO }
97
+ import cats .effect .std .Random
98
+ import cats .effect .syntax .temporal ._
99
+ import cats .effect .unsafe .implicits .global
100
+ import cats .mtl .Local
101
+ import cats .syntax .all ._
102
+ import org .apache .pekko .http .scaladsl .model .StatusCodes .OK
103
+ import org .apache .pekko .http .scaladsl .server .Directives ._
104
+ import org .apache .pekko .http .scaladsl .server .Route
105
+ import org .typelevel .otel4s .Attribute
106
+ import org .typelevel .otel4s .trace .Tracer
107
+ import org .typelevel .otel4s .java .context .Context
108
+ import io .opentelemetry .instrumentation .annotations .WithSpan
109
+ import io .opentelemetry .context .{Context => JContext }
110
+ import scala .concurrent .duration ._
111
+
112
+ def route (implicit T : Tracer [IO ], L : Local [IO , Context ]): Route =
113
+ path(" gen-random-name" ) {
114
+ get {
115
+ complete {
116
+ OK -> generateRandomName(length = 10 )
117
+ }
110
118
}
119
+ }
111
120
112
- def withJContext [F [_], A ](ctx : JContext )(fa : F [A ])(implicit L : Local [F , Context ]): F [A ] =
113
- Local [F , Context ].scope(fa)(Context .wrap(ctx))
114
- }
121
+ @ WithSpan (" generate-random-name" )
122
+ def generateRandomName (length : Int )(implicit T : Tracer [IO ], L : Local [IO , Context ]): String =
123
+ withJContext(JContext .current())(generate[IO ](length)).unsafeRunSync()
124
+
125
+ def generate [F [_]: Async : Tracer ](length : Int ): F [String ] =
126
+ Tracer [F ].span(" generate" , Attribute (" length" , length.toLong)).surround {
127
+ for {
128
+ random <- Random .scalaUtilRandom[F ]
129
+ delay <- random.betweenInt(100 , 2000 )
130
+ chars <- random.nextAlphaNumeric.replicateA(length).delayBy(delay.millis)
131
+ } yield chars.mkString
132
+ }
133
+
134
+ def withJContext [F [_], A ](ctx : JContext )(fa : F [A ])(implicit L : Local [F , Context ]): F [A ] =
135
+ Local [F , Context ].scope(fa)(Context .wrap(ctx))
136
+ ```
137
+
138
+ When you invoke the ` gen-random-name ` endpoint, the spans will be structured in the following way:
139
+ ```
140
+ > GET { http.method = GET, http.target = /gen-random-name, ... }
141
+ > generate-random-name
142
+ > generate { length = 10 }
115
143
```
116
144
117
145
## How to use otel4s context with OpenTelemetry Java
@@ -127,7 +155,7 @@ import org.typelevel.otel4s.java.context.Context
127
155
import io .opentelemetry .context .{Context => JContext }
128
156
import scala .util .Using
129
157
130
- def withJContext [F [_]: Sync , A ](use : JContext => A )(implicit L : Local [F , Context ]): F [A ] =
158
+ def useJContext [F [_]: Sync , A ](use : JContext => A )(implicit L : Local [F , Context ]): F [A ] =
131
159
Local [F , Context ].ask.flatMap { ctx => // <1>
132
160
Sync [F ].defer {
133
161
Sync [F ].fromTry {
@@ -148,7 +176,7 @@ Depending on your use case, you may prefer `Sync[F].interruptible` or `Sync[F].b
148
176
Now we can run a slightly modified original 'problematic' example:
149
177
``` scala
150
178
tracer.span(" test" ).use { span => // start 'test' span using otel4s
151
- IO .println(s " Otel4s ctx: ${span.context}" ) >> withJContext [IO , Unit ] { _ =>
179
+ IO .println(s " Otel4s ctx: ${span.context}" ) >> useJContext [IO , Unit ] { _ =>
152
180
val jSpanContext = JSpan .current().getSpanContext // get a span from the ThreadLocal variable
153
181
println(s " Java ctx: $jSpanContext" )
154
182
}
@@ -162,12 +190,18 @@ Otel4s ctx: {traceId=06f5d9112efbe711947ebbded1287a30, spanId=26ed80c398cc039f,
162
190
```
163
191
164
192
As we can see, the tracing information is in sync now,
165
- and you can use Java-instrumented libraries within the ` withJContext ` block.
193
+ and you can use Java-instrumented libraries within the ` useJContext ` block.
194
+
195
+ ## The example
196
+
197
+ [ PekkoHttpExample] [ pekko-http-example ] is a complete example that shows how to use otel4s
198
+ with OpenTelemetry Java instrumented libraries.
166
199
167
200
[ opentelemetry-java ] : https://github.com/open-telemetry/opentelemetry-java
168
201
[ opentelemetry-java-autoconfigure ] : https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md
169
202
[ opentelemetry-java-context ] : https://github.com/open-telemetry/opentelemetry-java/blob/main/context/src/main/java/io/opentelemetry/context/Context.java
170
203
[ opentelemetry-java-span ] : https://github.com/open-telemetry/opentelemetry-java/blob/main/api/all/src/main/java/io/opentelemetry/api/trace/Span.java
171
204
[ otel4s-context ] : https://github.com/typelevel/otel4s/blob/main/java/common/src/main/scala/org/typelevel/otel4s/java/context/Context.scala
172
205
[ cats-mtl-local ] : https://typelevel.org/cats-mtl/mtl-classes/local.html
173
- [ play-framework ] : https://github.com/playframework/playframework
206
+ [ pekko-http ] : https://pekko.apache.org/docs/pekko-http/current
207
+ [ pekko-http-example ] : https://github.com/typelevel/otel4s/blob/main/examples/src/main/scala/PekkoHttpExample.scala
0 commit comments