Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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

trait AttributesScalaVersionCompanion { self: Attributes.type =>

trait MakeCompanion { self: Attributes.Make.type =>

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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

import scala.collection.immutable

type AttributeOrOption[A] = Attribute[A] | Option[Attribute[A]]
type AttributeOrIterableOnce = Attribute[?] | IterableOnce[Attribute[?]]

trait AttributesScalaVersionCompanion { self: Attributes.type =>

trait MakeCompanion { self: Attributes.Make.type =>

given [A]: Attributes.Make[AttributeOrOption[A]] = {
case attribute: Attribute[?] => Attributes(attribute)
case option: Option[Attribute[?]] => Attributes.fromSpecific(option)
}

given Attributes.Make[AttributeOrIterableOnce] = {
case attribute: Attribute[?] => Attributes(attribute)
case iterable: IterableOnce[Attribute[?]] => Attributes.fromSpecific(iterable)
}

given Attributes.Make[immutable.Iterable[AttributeOrIterableOnce]] = { iterable =>
Attributes.fromSpecific(iterable.flatMap(Attributes.from))
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ sealed trait Attributes
Show[Attributes].show(this)
}

object Attributes extends SpecificIterableFactory[Attribute[_], Attributes] {
object Attributes extends SpecificIterableFactory[Attribute[_], Attributes] with AttributesScalaVersionCompanion {
private val Empty = new MapAttributes(Map.empty)

/** Allows creating [[Attributes]] from an arbitrary type `A`.
Expand All @@ -138,10 +138,12 @@ object Attributes extends SpecificIterableFactory[Attribute[_], Attributes] {
* @tparam A
* the type of the value
*/
trait Make[A] {
trait Make[-A] {
def make(a: A): Attributes
}

object Make extends MakeCompanion

/** Creates [[Attributes]] with the given `attributes`.
*
* @note
Expand Down
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

import munit.FunSuite

import scala.collection.immutable

class AttributesSuite extends FunSuite {

test("Attributes.from supports AttributeOrOption: Attribute") {
val attribute = Attribute("key", "value")

val result = Attributes.from(attribute: AttributeOrOption[String])

assertEquals(result, Attributes(attribute))
}

test("Attributes.from supports AttributeOrOption: Some(attribute)") {
val attribute = Attribute("key", "value")

val result = Attributes.from(Some(attribute): AttributeOrOption[String])

assertEquals(result, Attributes(attribute))
}

test("Attributes.from supports AttributeOrOption: None") {
val result = Attributes.from(None: AttributeOrOption[String])

assertEquals(result, Attributes.empty)
}

test("Attributes.from supports AttributeOrIterableOnce: Attribute") {
val attribute = Attribute("key", "value")

val result = Attributes.from(attribute: AttributeOrIterableOnce)

assertEquals(result, Attributes(attribute))
}

test("Attributes.from supports AttributeOrIterableOnce: IterableOnce[Attribute]") {
val a1 = Attribute("key1", "value1")
val a2 = Attribute("key2", "value2")

val result = Attributes.from(List(a1, a2): AttributeOrIterableOnce)

assertEquals(result, Attributes(a1, a2))
}

test("Attributes.from supports Iterable[AttributeOrIterableOnce] and flattens nested collections") {
val a1 = Attribute("key1", "value1")
val a2 = Attribute("key2", "value2")
val a3 = Attribute("key3", "value3")

val values: immutable.Iterable[AttributeOrIterableOnce] =
List(a1, List(a2, a3), Vector(a1))

val result = Attributes.from(values)

assertEquals(result, Attributes(a1, a2, a3, a1))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private[otel4s] trait CounterMacro[F[_], A] {
* @param attributes
* the set of attributes to associate with the value
*/
inline def add(inline value: A, inline attributes: Attribute[_]*): F[Unit] =
inline def add(inline value: A, inline attributes: AttributeOrIterableOnce*): F[Unit] =
${ CounterMacro.add('backend, 'value, 'attributes) }

/** Records a value with a set of attributes.
Expand All @@ -53,7 +53,7 @@ private[otel4s] trait CounterMacro[F[_], A] {
* @param attributes
* the set of attributes to associate with the value
*/
inline def inc(inline attributes: Attribute[_]*): F[Unit] =
inline def inc(inline attributes: AttributeOrIterableOnce*): F[Unit] =
${ CounterMacro.inc('backend, 'attributes) }

/** Increments a counter by one.
Expand All @@ -71,14 +71,14 @@ object CounterMacro {
def add[F[_], A](
backend: Expr[Counter.Backend[F, A]],
value: Expr[A],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.add($value, $attributes)) }
'{ $backend.meta.whenEnabled($backend.add($value, Attributes.from($attributes))) }

def inc[F[_], A](
backend: Expr[Counter.Backend[F, A]],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.inc($attributes)) }
'{ $backend.meta.whenEnabled($backend.inc(Attributes.from($attributes))) }

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ private[otel4s] trait GaugeMacro[F[_], A] {
*/
inline def record(
inline value: A,
inline attributes: Attribute[_]*
inline attributes: AttributeOrIterableOnce*
): F[Unit] =
${ GaugeMacro.record('backend, 'value, 'attributes) }

Expand All @@ -58,8 +58,8 @@ object GaugeMacro {
def record[F[_], A](
backend: Expr[Gauge.Backend[F, A]],
value: Expr[A],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.record($value, $attributes)) }
'{ $backend.meta.whenEnabled($backend.record($value, Attributes.from($attributes))) }

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private[otel4s] trait HistogramMacro[F[_], A] {
*/
inline def record(
inline value: A,
inline attributes: Attribute[_]*
inline attributes: AttributeOrIterableOnce*
): F[Unit] =
${ HistogramMacro.record('backend, 'value, 'attributes) }

Expand Down Expand Up @@ -75,9 +75,9 @@ private[otel4s] trait HistogramMacro[F[_], A] {
*/
inline def recordDuration(
inline timeUnit: TimeUnit,
inline attributes: Attribute[_]*
inline attributes: AttributeOrIterableOnce*
): Resource[F, Unit] =
recordDuration(timeUnit, _ => attributes)
recordDuration(timeUnit, _ => Attributes.from(attributes))

/** Records duration of the given effect.
*
Expand Down Expand Up @@ -145,18 +145,18 @@ object HistogramMacro {
def record[F[_], A](
backend: Expr[Histogram.Backend[F, A]],
value: Expr[A],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.record($value, $attributes)) }
'{ $backend.meta.whenEnabled($backend.record($value, Attributes.from($attributes))) }

def recordDuration[F[_], A](
backend: Expr[Histogram.Backend[F, A]],
timeUnit: Expr[TimeUnit],
attributes: Expr[Resource.ExitCase => immutable.Iterable[Attribute[_]]]
attributes: Expr[Resource.ExitCase => immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{
_root_.cats.effect.kernel.Resource.eval($backend.meta.isEnabled).flatMap { isEnabled =>
if (isEnabled) $backend.recordDuration($timeUnit, $attributes)
if (isEnabled) $backend.recordDuration($timeUnit, ec => Attributes.from($attributes(ec)))
else _root_.cats.effect.kernel.Resource.unit
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private[otel4s] trait UpDownCounterMacro[F[_], A] {
* @param attributes
* the set of attributes to associate with the value
*/
inline def add(inline value: A, inline attributes: Attribute[_]*): F[Unit] =
inline def add(inline value: A, inline attributes: AttributeOrIterableOnce*): F[Unit] =
${ UpDownCounterMacro.add('backend, 'value, 'attributes) }

/** Records a value with a set of attributes.
Expand All @@ -53,7 +53,7 @@ private[otel4s] trait UpDownCounterMacro[F[_], A] {
* @param attributes
* the set of attributes to associate with the value
*/
inline def inc(inline attributes: Attribute[_]*): F[Unit] =
inline def inc(inline attributes: AttributeOrIterableOnce*): F[Unit] =
${ UpDownCounterMacro.inc('backend, 'attributes) }

/** Increments a counter by one.
Expand All @@ -69,7 +69,7 @@ private[otel4s] trait UpDownCounterMacro[F[_], A] {
* @param attributes
* the set of attributes to associate with the value
*/
inline def dec(inline attributes: Attribute[_]*): F[Unit] =
inline def dec(inline attributes: AttributeOrIterableOnce*): F[Unit] =
${ UpDownCounterMacro.dec('backend, 'attributes) }

/** Decrements a counter by one.
Expand All @@ -87,20 +87,20 @@ object UpDownCounterMacro {
def add[F[_], A](
backend: Expr[UpDownCounter.Backend[F, A]],
value: Expr[A],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.add($value, $attributes)) }
'{ $backend.meta.whenEnabled($backend.add($value, Attributes.from($attributes))) }

def inc[F[_], A](
backend: Expr[UpDownCounter.Backend[F, A]],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.inc($attributes)) }
'{ $backend.meta.whenEnabled($backend.inc(Attributes.from($attributes))) }

def dec[F[_], A](
backend: Expr[UpDownCounter.Backend[F, A]],
attributes: Expr[immutable.Iterable[Attribute[_]]]
attributes: Expr[immutable.Iterable[AttributeOrIterableOnce]]
)(using Quotes, Type[F], Type[A]) =
'{ $backend.meta.whenEnabled($backend.dec($attributes)) }
'{ $backend.meta.whenEnabled($backend.dec(Attributes.from($attributes))) }

}
Loading