Skip to content

[Do not merge] Trace API playground #35

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

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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 target .js/target site/target core/.js/target core/.jvm/target .jvm/target .native/target java/.jvm/target project/target
run: mkdir -p target .js/target site/target core/.js/target core/.jvm/target .jvm/target .native/target examples/.jvm/target java/.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 target .js/target site/target core/.js/target core/.jvm/target .jvm/target .native/target java/.jvm/target project/target
run: tar cf targets.tar target .js/target site/target core/.js/target core/.jvm/target .jvm/target .native/target examples/.jvm/target java/.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
20 changes: 18 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ThisBuild / crossScalaVersions := Seq(Scala213, "3.1.3")
ThisBuild / scalaVersion := Scala213 // the default Scala

lazy val root = tlCrossRootProject
.aggregate(core, java)
.aggregate(core, java, examples)
.settings(name := "otel4s")

lazy val core = crossProject(JVMPlatform, JSPlatform)
Expand Down Expand Up @@ -52,9 +52,25 @@ lazy val java = crossProject(JVMPlatform)
libraryDependencies ++= Seq(
"io.opentelemetry" % "opentelemetry-api" % "1.15.0",
"io.opentelemetry" % "opentelemetry-exporter-logging" % "1.15.0" % Test,
"io.opentelemetry" % "opentelemetry-sdk-extension-autoconfigure" % "1.13.0-alpha" % Test
"io.opentelemetry" % "opentelemetry-sdk-extension-autoconfigure" % "1.13.0-alpha" % Test,
"io.opentelemetry" % "opentelemetry-sdk-testing" % "1.15.0" % Test,
"org.scalameta" %% "munit" % "0.7.29" % Test,
"org.typelevel" %% "munit-cats-effect-3" % "1.0.7" % Test,
"org.typelevel" %%% "cats-effect-testkit" % "3.3.13" % Test
)
)
.dependsOn(core % "compile->compile,test->test")

lazy val examples = crossProject(JVMPlatform)
.crossType(CrossType.Pure)
.in(file("examples"))
.settings(
name := "otel4s-examples",
libraryDependencies ++= Seq(
"co.fs2" %% "fs2-core" % "3.2.11",
"io.opentelemetry" % "opentelemetry-exporter-jaeger" % "1.15.0"
)
)
.dependsOn(core, java)

lazy val docs = project.in(file("site")).enablePlugins(TypelevelSitePlugin)
32 changes: 32 additions & 0 deletions core/src/main/scala-2/org/typelevel/otel4s/trace/SpanMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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

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

def recordException(
exception: Throwable,
attributes: Attribute[_]*
): F[Unit] =
macro TracesMacro.recordException

def setAttributes(attributes: Attribute[_]*): F[Unit] =
macro TracesMacro.setAttributes

}
89 changes: 89 additions & 0 deletions core/src/main/scala-2/org/typelevel/otel4s/trace/TracerMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 cats.effect.Resource

private[otel4s] trait TracerMacro[F[_]] {
self: Tracer[F] =>

/** Creates a new child span. The span is automatically attached to a parent
* span (based on the scope).
*
* The lifecycle of the span is managed automatically. That means the span is
* ended upon the finalization of a resource.
*
* To attach span to a specific parent, use [[childOf]].
*
* @example
* attaching span to a specific parent
* {{{
* val tracer: Tracer[F] = ???
* val span: Span[F] = ???
* val customParent: Resource[F, Span.Auto[F]] = tracer.childOf(span).span("custom-parent")
* }}}
*
* @see
* [[spanBuilder]] to make a fully manual span (explicit end)
*
* @param name
* the name of the span
*
* @param attributes
* the set of attributes to associate with the span
*/
def span(name: String, attributes: Attribute[_]*): Resource[F, Span.Auto[F]] =
macro TracesMacro.span

/** Creates a new root span. Even if a parent span is available in the
* context, the span is created without a parent.
*
* @param name
* the name of the span
*
* @param attributes
* the set of attributes to associate with the span
*/
def rootSpan(
name: String,
attributes: Attribute[_]*
): Resource[F, Span.Auto[F]] =
macro TracesMacro.rootSpan

/** Creates a new child span. The span is automatically attached to a parent
* span (based on the scope).
*
* The structure of the inner spans:
* {{{
* > name
* > acquire
* > use
* > release
* }}}
*
* @param name
* the name of the span
*
* @param attributes
* the set of attributes to associate with the span
*/
def resourceSpan[A](name: String, attributes: Attribute[_]*)(
resource: Resource[F, A]
): Resource[F, Span.Res[F, A]] =
macro TracesMacro.resourceSpan[F, A]
}
77 changes: 77 additions & 0 deletions core/src/main/scala-2/org/typelevel/otel4s/trace/TracesMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 cats.effect.Resource

import scala.reflect.macros.blackbox

private[otel4s] object TracesMacro {

def span(c: blackbox.Context)(
name: c.Expr[String],
attributes: c.Expr[Attribute[_]]*
): c.universe.Tree = {
import c.universe._
val meta = q"${c.prefix}.meta"

q"if ($meta.isEnabled) ${c.prefix}.spanBuilder($name).withAttributes(..$attributes).createAuto else $meta.noopAutoSpan"
}

def rootSpan(c: blackbox.Context)(
name: c.Expr[String],
attributes: c.Expr[Attribute[_]]*
): c.universe.Tree = {
import c.universe._
val meta = q"${c.prefix}.meta"

q"if ($meta.isEnabled) ${c.prefix}.spanBuilder($name).root.withAttributes(..$attributes).createAuto else $meta.noopAutoSpan"
}

def resourceSpan[F[_], A](c: blackbox.Context)(
name: c.Expr[String],
attributes: c.Expr[Attribute[_]]*
)(resource: c.Expr[Resource[F, A]]): c.universe.Tree = {
import c.universe._
val meta = q"${c.prefix}.meta"

q"if ($meta.isEnabled) ${c.prefix}.spanBuilder($name).withAttributes(..$attributes).createRes($resource) else $meta.noopResSpan($resource)"
}

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 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"
}

}
34 changes: 34 additions & 0 deletions core/src/main/scala-3/org/typelevel/otel4s/trace/SpanMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.quoted.*

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

inline def recordException(
inline exception: Throwable,
inline attributes: Attribute[_]*
): F[Unit] =
${ TracesMacro.recordException('self, 'exception, 'attributes) }

inline def setAttributes(inline attributes: Attribute[_]*): F[Unit] =
${ TracesMacro.setAttributes('self, 'attributes) }

}
95 changes: 95 additions & 0 deletions core/src/main/scala-3/org/typelevel/otel4s/trace/TracerMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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 cats.effect.Resource

import scala.quoted.*

private[otel4s] trait TracerMacro[F[_]] {
self: Tracer[F] =>

/** Creates a new child span. The span is automatically attached to a parent
* span (based on the scope).
*
* The lifecycle of the span is managed automatically. That means the span is
* ended upon the finalization of a resource.
*
* To attach span to a specific parent, use [[childOf]].
*
* @example
* attaching span to a specific parent
* {{{
* val tracer: Tracer[F] = ???
* val span: Span[F] = ???
* val customParent: Resource[F, Span.Auto[F]] = tracer.childOf(span).span("custom-parent")
* }}}
*
* @see
* [[spanBuilder]] to make a fully manual span (explicit end)
*
* @param name
* the name of the span
*
* @param attributes
* the set of attributes to associate with the span
*/
inline def span(
inline name: String,
inline attributes: Attribute[_]*
): Resource[F, Span[F]] =
${ TracesMacro.span('self, 'name, 'attributes) }

/** Creates a new root span. Even if a parent span is available in the
* context, the span is created without a parent.
*
* @param name
* the name of the span
*
* @param attributes
* the set of attributes to associate with the span
*/
inline def rootSpan(
inline name: String,
inline attributes: Attribute[_]*
): Resource[F, Span[F]] =
${ TracesMacro.rootSpan('self, 'name, 'attributes) }

/** Creates a new child span. The span is automatically attached to a parent
* span (based on the scope).
*
* The structure of the inner spans:
* {{{
* > name
* > acquire
* > use
* > release
* }}}
*
* @param name
* the name of the span
* @param attributes
* the set of attributes to associate with the span
*/
inline def resourceSpan[A](
inline name: String,
inline attributes: Attribute[_]*
)(inline resource: Resource[F, A]): Resource[F, Span.Res[F, A]] =
${ TracesMacro.resourceSpan('self, 'name, 'attributes, 'resource) }

}
Loading