Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement tracing API #37

Merged
merged 52 commits into from
Jan 23, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
ff8ed12
Define tracing API
iRevive Jul 29, 2022
9f05624
Add `spanBuilder` to `Tracer`. Better naming of `SpanContext` members
iRevive Jul 30, 2022
e77a192
Rename `SamplingStrategy` -> `SamplingDecision`
iRevive Jul 30, 2022
9ab5d68
Update scaladoc. Add `SpanFinalizer`
iRevive Jul 30, 2022
42cdd4b
Fix scaladoc
iRevive Jul 30, 2022
7f0846f
Implement tracing API
iRevive Jul 30, 2022
a7a390f
Improve Scaladoc
iRevive Jul 31, 2022
87c23ee
Merge branch 'tracing-api' into tracing-api-impl
iRevive Jul 31, 2022
b53d00c
Improve Scaladoc
iRevive Jul 31, 2022
bbe21d7
Better phrasing
iRevive Jul 31, 2022
94a1fe6
Merge branch 'tracing-api' into tracing-api-impl
iRevive Jul 31, 2022
bc95fba
Docs cleanup
iRevive Jul 31, 2022
2cc0cae
Properly handle 'noop' scope
iRevive Aug 1, 2022
8f74413
Hide implementation of `SpanFinalizer`
iRevive Aug 1, 2022
c4046f0
Merge branch 'tracing-api' into tracing-api-impl
iRevive Aug 1, 2022
5fdb830
Docs update
iRevive Aug 2, 2022
f000a93
Replace `asChildOf` with `childScope` and `withParent`
iRevive Aug 2, 2022
13d4ebb
Add `withParent` to `SpanBuilder`
iRevive Aug 2, 2022
6d3f38f
Replace `childOf` with `childScope` in `Tracer`
iRevive Aug 2, 2022
1e56fc8
Make `Span` always return `SpanContext`
iRevive Aug 3, 2022
461f3b5
Merge branch 'main' into tracing-api-impl
iRevive Aug 3, 2022
d70a57d
Test propagation of trace info over stream scopes
iRevive Aug 3, 2022
3a14e52
Make `Span` always have a `SpanContext`
iRevive Aug 4, 2022
3d51acb
Merge branch 'main' into tracing-api
iRevive Aug 4, 2022
9ce4cfe
Merge branch 'tracing-api' into tracing-api-impl
iRevive Aug 4, 2022
b1d4b15
Add `setAttribute` method to `Span`
iRevive Aug 8, 2022
95f3fc4
Use `IO.to` syntax
iRevive Aug 29, 2022
a9b5f30
Merge branch 'main' into tracing-api
iRevive Sep 25, 2022
39ee6eb
Update layout
iRevive Sep 25, 2022
bb99d2a
Run `sbt githubWorkflowGenerate`
iRevive Sep 25, 2022
ff80ca4
Merge branch 'tracing-api' into tracing-api-impl
iRevive Sep 25, 2022
815b8c2
Update layout
iRevive Sep 25, 2022
f2db47d
Revert redundant changes
iRevive Sep 25, 2022
67e8019
Merge branch 'tracing-api' into tracing-api-impl
iRevive Sep 25, 2022
f3b66f8
Cleanup
iRevive Sep 25, 2022
b2b218e
Run `sbt githubWorkflowGenerate`
iRevive Sep 25, 2022
5ec119f
Update layout
iRevive Sep 25, 2022
b963f03
run `scalafixAll`
iRevive Sep 25, 2022
fe1fbea
Implement `Span#setAttribute` via macro
iRevive Sep 25, 2022
0d25702
Fix method name
iRevive Sep 25, 2022
42a6851
Merge branch 'main' into tracing-api-impl
iRevive Oct 17, 2022
d1a5a84
Update implementation
iRevive Oct 17, 2022
9ff15db
Minor cleanup of `build.sbt`
iRevive Oct 17, 2022
d9fb79d
Remove duplicated `munit` dependency
iRevive Oct 18, 2022
851aeab
Discard statement instead of calling `void`
iRevive Oct 18, 2022
45e312e
Hide implementation details behind `package[java]`
iRevive Oct 18, 2022
fadef2b
Rename `withAttribute` -> `addAttribute`
iRevive Oct 18, 2022
b17d7cd
Merge branch 'main' into tracing-api-impl
iRevive Oct 18, 2022
f3c1c3b
Merge upstream
iRevive Oct 18, 2022
2ce752b
Merge branch 'main' into tracing-api-impl
rossabaker Jan 17, 2023
9ec2b1a
Rename `SpanBuilder.create` -> `SpanBuilder.start`, `SpanBuilder.crea…
iRevive Jan 21, 2023
7501d01
Rename sbt modules `tracing` -> `trace`
iRevive Jan 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ jobs:

- name: Make target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
run: mkdir -p testkit/metrics/jvm/target java/metrics/target testkit/common/jvm/target core/tracing/.jvm/target core/tracing/.js/target target core/common/.jvm/target .js/target site/target core/metrics/.jvm/target core/all/.js/target java/all/target java/common/target core/metrics/.js/target core/all/.jvm/target .jvm/target .native/target core/common/.js/target testkit/all/jvm/target project/target
run: mkdir -p testkit/metrics/jvm/target java/metrics/target testkit/common/jvm/target core/tracing/.jvm/target core/tracing/.js/target target core/common/.jvm/target .js/target site/target core/metrics/.jvm/target core/all/.js/target java/all/target java/common/target java/tracing/target core/metrics/.js/target core/all/.jvm/target .jvm/target .native/target core/common/.js/target testkit/all/jvm/target project/target

- name: Compress target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
run: tar cf targets.tar testkit/metrics/jvm/target java/metrics/target testkit/common/jvm/target core/tracing/.jvm/target core/tracing/.js/target target core/common/.jvm/target .js/target site/target core/metrics/.jvm/target core/all/.js/target java/all/target java/common/target core/metrics/.js/target core/all/.jvm/target .jvm/target .native/target core/common/.js/target testkit/all/jvm/target project/target
run: tar cf targets.tar testkit/metrics/jvm/target java/metrics/target testkit/common/jvm/target core/tracing/.jvm/target core/tracing/.js/target target core/common/.jvm/target .js/target site/target core/metrics/.jvm/target core/all/.js/target java/all/target java/common/target java/tracing/target core/metrics/.js/target core/all/.jvm/target .jvm/target .native/target core/common/.js/target testkit/all/jvm/target project/target

- name: Upload target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
Expand Down
38 changes: 29 additions & 9 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ ThisBuild / scalaVersion := Scala213 // the default Scala

val CatsVersion = "2.8.0"
val CatsEffectVersion = "3.3.14"
val FS2Version = "3.3.0"
val MUnitVersion = "0.7.29"
val MUnitCatsEffectVersion = "1.0.7"
val OpenTelemetryVersion = "1.19.0"
Expand All @@ -35,6 +36,13 @@ lazy val scalaReflectDependency = Def.settings(
}
)

lazy val munitDependencies = Def.settings(
libraryDependencies ++= Seq(
"org.scalameta" %%% "munit" % MUnitVersion % Test,
"org.typelevel" %%% "munit-cats-effect-3" % MUnitCatsEffectVersion % Test
)
)

lazy val root = tlCrossRootProject
.aggregate(
`core-common`,
Expand All @@ -46,6 +54,7 @@ lazy val root = tlCrossRootProject
testkit,
`java-common`,
`java-metrics`,
`java-tracing`,
java
)
.settings(name := "otel4s")
Expand All @@ -66,12 +75,11 @@ lazy val `core-metrics` = crossProject(JVMPlatform, JSPlatform)
.in(file("core/metrics"))
.dependsOn(`core-common`)
.settings(scalaReflectDependency)
.settings(munitDependencies)
.settings(
name := "otel4s-core-metrics",
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-effect-kernel" % CatsEffectVersion,
"org.scalameta" %%% "munit" % MUnitVersion % Test,
"org.typelevel" %%% "munit-cats-effect-3" % MUnitCatsEffectVersion % Test,
"org.typelevel" %%% "cats-effect-testkit" % CatsEffectVersion % Test
)
)
Expand All @@ -81,14 +89,13 @@ lazy val `core-tracing` = crossProject(JVMPlatform, JSPlatform)
.in(file("core/tracing"))
.dependsOn(`core-common`)
.settings(scalaReflectDependency)
.settings(munitDependencies)
.settings(
name := "otel4s-core-tracing",
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-effect-kernel" % CatsEffectVersion,
"org.scodec" %%% "scodec-bits" % ScodecVersion,
"org.scalameta" %%% "munit" % MUnitVersion % Test,
"org.typelevel" %%% "munit-cats-effect-3" % MUnitCatsEffectVersion % Test,
"org.typelevel" %%% "cats-effect-testkit" % CatsEffectVersion % Test
"org.scalameta" %%% "munit" % MUnitVersion % Test
rossabaker marked this conversation as resolved.
Show resolved Hide resolved
)
)

Expand Down Expand Up @@ -150,20 +157,33 @@ lazy val `java-common` = project
lazy val `java-metrics` = project
.in(file("java/metrics"))
.dependsOn(`java-common`, `core-metrics`.jvm, `testkit-metrics`.jvm)
.settings(munitDependencies)
.settings(
name := "otel4s-java-metrics",
libraryDependencies ++= Seq(
"io.opentelemetry" % "opentelemetry-api" % OpenTelemetryVersion,
"io.opentelemetry" % "opentelemetry-sdk" % OpenTelemetryVersion % Test,
"io.opentelemetry" % "opentelemetry-sdk-testing" % OpenTelemetryVersion % Test
)
)

lazy val `java-tracing` = project
.in(file("java/tracing"))
.dependsOn(`java-common`, `core-tracing`.jvm)
.settings(munitDependencies)
.settings(
name := "otel4s-java-tracing",
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-effect" % CatsEffectVersion,
"io.opentelemetry" % "opentelemetry-sdk" % OpenTelemetryVersion % Test,
"io.opentelemetry" % "opentelemetry-sdk-testing" % OpenTelemetryVersion % Test,
"org.scalameta" %% "munit" % MUnitVersion % Test,
"org.typelevel" %% "munit-cats-effect-3" % MUnitCatsEffectVersion % Test
"org.typelevel" %%% "cats-effect-testkit" % CatsEffectVersion % Test,
"co.fs2" %% "fs2-core" % FS2Version % Test
)
)

lazy val java = project
.in(file("java/all"))
.dependsOn(core.jvm, `java-metrics`)
.dependsOn(core.jvm, `java-metrics`, `java-tracing`)
.settings(
name := "otel4s-java"
)
Expand Down
5 changes: 5 additions & 0 deletions core/all/src/main/scala/org/typelevel/otel4s/Otel4s.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
package org.typelevel.otel4s

import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.trace.TracerProvider

trait Otel4s[F[_]] {

/** A registry for creating named meters.
*/
def meterProvider: MeterProvider[F]

/** An entry point of the tracing API.
*/
def tracerProvider: TracerProvider[F]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/*
* Copyright 2022 Typelevel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.typelevel.otel4s
package trace

import scala.concurrent.duration.FiniteDuration

private[otel4s] trait SpanMacro[F[_]] {
self: Span[F] =>

/** Adds an event to the span with the given attributes. The timestamp of the
* event will be the current time.
*
* @param name
* the name of the event
*
* @param attributes
* the set of attributes to associate with the event
*/
def addEvent(name: String, attributes: Attribute[_]*): F[Unit] =
macro SpanMacro.addEvent

/** Adds an event to the span with the given attributes and timestamp.
*
* '''Note''': the timestamp should be based on `Clock[F].realTime`. Using
* `Clock[F].monotonic` may lead to an incorrect data.
*
* @param name
* the name of the event
*
* @param timestamp
* the explicit event timestamp since epoch
*
* @param attributes
* the set of attributes to associate with the event
*/
def addEvent(
name: String,
timestamp: FiniteDuration,
attributes: Attribute[_]*
): F[Unit] =
macro SpanMacro.addEventWithTimestamp

/** Records information about the `Throwable` to the span.
*
* @param exception
* the `Throwable` to record
*
* @param attributes
* the set of attributes to associate with the value
*/
def recordException(
exception: Throwable,
attributes: Attribute[_]*
): F[Unit] =
macro SpanMacro.recordException

/** Sets an attribute to the span. If the span previously contained a mapping
* for the key, the old value is replaced by the specified value.
*
* @param attribute
* the attribute to add to the span
*/
def setAttribute[A](attribute: Attribute[A]): F[Unit] =
macro SpanMacro.setAttribute[A]

/** Sets attributes to the span. If the span previously contained a mapping
* for any of the keys, the old values are replaced by the specified values.
*
* @param attributes
* the set of attributes to add to the span
*/
def setAttributes(attributes: Attribute[_]*): F[Unit] =
macro SpanMacro.setAttributes

/** Sets the status to the span.
*
* Only the value of the last call will be recorded, and implementations are
* free to ignore previous calls.
*
* @param status
* the [[Status]] to set
*/
def setStatus(status: Status): F[Unit] =
macro SpanMacro.setStatus

/** Sets the status to the span.
*
* Only the value of the last call will be recorded, and implementations are
* free to ignore previous calls.
*
* @param status
* the [[Status]] to set
*
* @param description
* the description of the [[Status]]
*/
def setStatus(status: Status, description: String): F[Unit] =
macro SpanMacro.setStatusWithDescription

}

object SpanMacro {
import scala.reflect.macros.blackbox

def addEvent(c: blackbox.Context)(
name: c.Expr[String],
attributes: c.Expr[Attribute[_]]*
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.addEvent($name, ..$attributes) else $meta.unit"
}

def addEventWithTimestamp(c: blackbox.Context)(
name: c.Expr[String],
timestamp: c.Expr[FiniteDuration],
attributes: c.Expr[Attribute[_]]*
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.addEvent($name, $timestamp, ..$attributes) else $meta.unit"
}

def recordException(c: blackbox.Context)(
exception: c.Expr[Throwable],
attributes: c.Expr[Attribute[_]]*
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.recordException($exception, ..$attributes) else $meta.unit"
}

def setAttribute[A](c: blackbox.Context)(
attribute: c.Expr[Attribute[A]]
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.setAttributes($attribute) else $meta.unit"
}

def setAttributes(c: blackbox.Context)(
attributes: c.Expr[Attribute[_]]*
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.setAttributes(..$attributes) else $meta.unit"
}

def setStatus(c: blackbox.Context)(
status: c.Expr[Status]
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.setStatus($status) else $meta.unit"
}

def setStatusWithDescription(c: blackbox.Context)(
status: c.Expr[Status],
description: c.Expr[String]
): c.universe.Tree = {
import c.universe._

val backend = q"${c.prefix}.backend"
val meta = q"$backend.meta"

q"if ($meta.isEnabled) $backend.setStatus($status, $description) else $meta.unit"
}

}
Loading