From 027717197e9b5d62a62ccfc90e45688883c8cd18 Mon Sep 17 00:00:00 2001 From: Maksym Ochenashko Date: Tue, 21 Nov 2023 14:10:01 +0200 Subject: [PATCH] Make `Attributes` extend `Iterable[Attribute[_]]` --- .../org/typelevel/otel4s/sdk/Attributes.scala | 47 ++----------------- .../otel4s/sdk/AttributesProps.scala | 23 +++++---- .../typelevel/otel4s/sdk/ResourceProps.scala | 3 +- 3 files changed, 16 insertions(+), 57 deletions(-) diff --git a/sdk/common/src/main/scala/org/typelevel/otel4s/sdk/Attributes.scala b/sdk/common/src/main/scala/org/typelevel/otel4s/sdk/Attributes.scala index 7a70e7e14..5eb93fce0 100644 --- a/sdk/common/src/main/scala/org/typelevel/otel4s/sdk/Attributes.scala +++ b/sdk/common/src/main/scala/org/typelevel/otel4s/sdk/Attributes.scala @@ -16,9 +16,7 @@ package org.typelevel.otel4s.sdk -import cats.Applicative import cats.Hash -import cats.Monad import cats.Monoid import cats.Show import cats.implicits._ @@ -31,7 +29,7 @@ import org.typelevel.otel4s.AttributeKey * @see * [[https://opentelemetry.io/docs/specs/otel/common/#attribute-collections]] */ -sealed trait Attributes { +sealed trait Attributes extends Iterable[Attribute[_]] { /** Returns an attribute for the given attribute name, or `None` if not found. */ @@ -41,31 +39,10 @@ sealed trait Attributes { */ def get[T](key: AttributeKey[T]): Option[Attribute[T]] - /** Whether the attributes collection is empty or not. - */ - def isEmpty: Boolean - - /** The size of the attributes collection. - */ - def size: Int - /** Whether this attributes collection contains the given key. */ def contains(key: AttributeKey[_]): Boolean - /** Applies an operation to each attribute and accumulates the results from - * left to right. - */ - def foldLeft[F[_]: Monad, B](z: B)(f: (B, Attribute[_]) => F[B]): F[B] - - /** Checks if the given predicate holds for all attributes in the collection. - */ - def forall[F[_]: Monad](p: Attribute[_] => F[Boolean]): F[Boolean] - - /** Applies the given operation to each attribute in the collection. - */ - def foreach[F[_]: Applicative](f: Attribute[_] => F[Unit]): F[Unit] - /** Returns the `Map` representation of the attributes collection. */ def toMap: Map[AttributeKey[_], Attribute[_]] @@ -208,29 +185,13 @@ object Attributes { def get[T](key: AttributeKey[T]): Option[Attribute[T]] = m.get(key).map(_.asInstanceOf[Attribute[T]]) - def isEmpty: Boolean = m.isEmpty - - def size: Int = m.size - def contains(key: AttributeKey[_]): Boolean = m.contains(key) - def foldLeft[F[_]: Monad, B](z: B)(f: (B, Attribute[_]) => F[B]): F[B] = - m.foldLeft(Monad[F].pure(z)) { (acc, v) => - acc.flatMap(b => f(b, v._2)) - } - - def forall[F[_]: Monad](p: Attribute[_] => F[Boolean]): F[Boolean] = - foldLeft(true) { (b, a) => - if (b) p(a).map(b && _) - else Monad[F].pure(false) - } - - def foreach[F[_]: Applicative](f: Attribute[_] => F[Unit]): F[Unit] = - m.foldLeft(Applicative[F].unit)((acc, v) => acc *> f(v._2)) - def toMap: Map[AttributeKey[_], Attribute[_]] = m - def toList: List[Attribute[_]] = m.values.toList + def iterator: Iterator[Attribute[_]] = m.values.iterator + + override def toList: List[Attribute[_]] = m.values.toList } private final class MutableBuilder extends Builder { diff --git a/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/AttributesProps.scala b/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/AttributesProps.scala index e189b504b..32d66cb2a 100644 --- a/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/AttributesProps.scala +++ b/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/AttributesProps.scala @@ -16,7 +16,6 @@ package org.typelevel.otel4s.sdk -import cats.Id import cats.Show import cats.syntax.semigroup._ import munit.ScalaCheckSuite @@ -34,7 +33,7 @@ class AttributesProps extends ScalaCheckSuite { property("Attributes#size is equal to the number of unique keys") { forAll(listOfAttributes) { attributes => val keysSet = attributes.map(_.key).toSet - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) keysSet.size == attrs.size } @@ -43,7 +42,7 @@ class AttributesProps extends ScalaCheckSuite { property("Attributes#isEmpty is true when there are no attributes") { forAll(listOfAttributes) { attributes => val keysSet = attributes.map(_.key).toSet - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) keysSet.isEmpty == attrs.isEmpty } @@ -52,7 +51,7 @@ class AttributesProps extends ScalaCheckSuite { property("Attributes#contains is true when the key is present") { forAll(listOfAttributes) { attributes => val keysSet = attributes.map(_.key).toSet - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) keysSet.forall(attrs.contains) } @@ -60,10 +59,10 @@ class AttributesProps extends ScalaCheckSuite { property("Attributes#foreach iterates over all attributes") { forAll(listOfAttributes) { attributes => - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) var count = 0 - attrs.foreach[Id] { _ => count += 1 } + attrs.foreach(_ => count += 1) count == attrs.size } @@ -71,7 +70,7 @@ class AttributesProps extends ScalaCheckSuite { property("Attributes#toList returns a list of all attributes") { forAll(listOfAttributes) { attributes => - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) val list = attrs.toList list.size == attrs.size && list.forall(a => attrs.contains(a.key)) @@ -80,10 +79,10 @@ class AttributesProps extends ScalaCheckSuite { property("Attributes#foldLeft folds over all attributes") { forAll(listOfAttributes) { attributes => - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) val list = attrs.toList - val folded = attrs.foldLeft[Id, Int](0) { (acc, _) => acc + 1 } + val folded = attrs.foldLeft[Int](0) { (acc, _) => acc + 1 } folded == list.size } @@ -93,15 +92,15 @@ class AttributesProps extends ScalaCheckSuite { "Attributes#forall returns true when all attributes match the predicate" ) { forAll(listOfAttributes) { attributes => - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) - attrs.forall[Id](_ => true) + attrs.forall(_ => true) } } property("Attributes#toMap returns a map of all attributes") { forAll(listOfAttributes) { attributes => - val attrs = Attributes(attributes: _*) + val attrs = Attributes.fromIterable(attributes) val map = attrs.toMap map.size == attrs.size && map.forall { case (k, v) => diff --git a/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/ResourceProps.scala b/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/ResourceProps.scala index 488016cb4..63a646bb1 100644 --- a/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/ResourceProps.scala +++ b/sdk/common/src/test/scala/org/typelevel/otel4s/sdk/ResourceProps.scala @@ -16,7 +16,6 @@ package org.typelevel.otel4s.sdk -import cats.Id import cats.Show import cats.syntax.show._ import munit.ScalaCheckSuite @@ -34,7 +33,7 @@ class ResourceProps extends ScalaCheckSuite { val keys = resource1.attributes.toMap.keySet ++ resource2.attributes.toMap.keySet - mergedAttrs.size == keys.size && mergedAttrs.forall[Id] { a => + mergedAttrs.size == keys.size && mergedAttrs.forall { a => resource2.attributes .get(a.key) .orElse(resource1.attributes.get(a.key))