Skip to content

Commit

Permalink
Add Attribute containing middleware version
Browse files Browse the repository at this point in the history
  • Loading branch information
NthPortal committed Jan 7, 2025
1 parent b570fe6 commit 731e509
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ import java.util.Locale
/** Methods for creating appropriate `Attribute`s from typed HTTP objects. */
object TypedAttributes {
private[this] lazy val knownMethods: Set[Method] = Method.all.toSet
private[middleware] val middlewareVersion: Attribute[String] =
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
)

/** The http.request.method `Attribute` with the special value _OTHER */
val httpRequestMethodOther: Attribute[String] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,23 @@ trait AttributeProvider { self =>
self.exceptionAttributes(cause) ++ that.exceptionAttributes(cause)
}
}

object AttributeProvider {

/** Provides an `Attribute` containing this middleware's version. */
val middlewareVersion: AttributeProvider =
new AttributeProvider {
def requestAttributes[F[_]](
request: Request[F],
urlTemplateClassifier: UriTemplateClassifier,
urlRedactor: UriRedactor,
headersAllowedAsAttributes: Set[AuthScheme],
): Attributes = Attributes(TypedAttributes.middlewareVersion)
def responseAttributes[F[_]](
response: Response[F],
headersAllowedAsAttributes: Set[AuthScheme],
): Attributes = Attributes.empty
def exceptionAttributes(cause: Throwable): Attributes =
Attributes.empty
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,6 @@ trait SpanDataProvider extends AttributeProvider { self =>

object SpanDataProvider {

/** The default provider, which follows OpenTelemetry semantic conventions. */
def default: SpanDataProvider = openTelemetry

/** A `SpanAndAttributeProvider` following OpenTelemetry semantic conventions. */
val openTelemetry: SpanDataProvider = {
final case class Data(httpRequestMethod: Attribute[String]) {
Expand Down Expand Up @@ -246,4 +243,9 @@ object SpanDataProvider {
Attributes(TypedAttributes.errorType(cause))
}
}

/** The default provider, which follows OpenTelemetry semantic conventions
* and includes this middleware's version.
*/
val default: SpanDataProvider = openTelemetry.and(AttributeProvider.middlewareVersion)
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class ClientMiddlewareTests extends CatsEffectSuite {
assertEquals(span.status, StatusData.Unset)

val attributes = span.attributes.elements
assertEquals(attributes.size, 9)
assertEquals(attributes.size, 10)
def getAttr[A: AttributeKey.KeySelect](name: String): Option[A] =
attributes.get[A](name).map(_.value)

Expand All @@ -103,6 +103,10 @@ class ClientMiddlewareTests extends CatsEffectSuite {
assertEquals(getAttr[Long]("http.response.status_code"), Some(200L))
assertEquals(getAttr[Seq[String]]("http.response.header.foo"), None)
assertEquals(getAttr[Seq[String]]("http.response.header.baz"), Some(Seq("qux")))
assertEquals(
getAttr[String]("org.http4s.otel4s.middleware.version"),
Some(org.http4s.otel4s.middleware.BuildInfo.version),
)
}
}
}
Expand Down Expand Up @@ -249,6 +253,10 @@ class ClientMiddlewareTests extends CatsEffectSuite {
Attribute("server.port", 80L),
Attribute("url.full", "http://localhost/"),
Attribute("url.scheme", "http"),
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
),
)

for {
Expand Down Expand Up @@ -339,6 +347,10 @@ class ClientMiddlewareTests extends CatsEffectSuite {
Attribute("server.port", 80L),
Attribute("url.full", "http://localhost/"),
Attribute("url.scheme", "http"),
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
),
)

for {
Expand Down Expand Up @@ -416,6 +428,10 @@ class ClientMiddlewareTests extends CatsEffectSuite {
Attribute("server.port", 80L),
Attribute("url.full", "http://localhost/"),
Attribute("url.scheme", "http"),
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
),
)

for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,23 @@ trait AttributeProvider { self =>
self.exceptionAttributes(cause) ++ that.exceptionAttributes(cause)
}
}

object AttributeProvider {

/** Provides an `Attribute` containing this middleware's version. */
val middlewareVersion: AttributeProvider =
new AttributeProvider {
def requestAttributes[F[_]](
request: Request[F],
routeClassifier: RouteClassifier,
redactor: PathAndQueryRedactor,
headersAllowedAsAttributes: Set[AuthScheme],
): Attributes = Attributes(TypedAttributes.middlewareVersion)
def responseAttributes[F[_]](
response: Response[F],
headersAllowedAsAttributes: Set[AuthScheme],
): Attributes = Attributes.empty
def exceptionAttributes(cause: Throwable): Attributes =
Attributes.empty
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@ trait SpanDataProvider extends AttributeProvider { self =>

object SpanDataProvider {

/** The default provider, which follows OpenTelemetry semantic conventions. */
def default: SpanDataProvider = openTelemetry

/** A `SpanAndAttributeProvider` following OpenTelemetry semantic conventions. */
val openTelemetry: SpanDataProvider = {
final case class Data(
Expand Down Expand Up @@ -261,4 +258,9 @@ object SpanDataProvider {
Attributes(TypedAttributes.errorType(cause))
}
}

/** The default provider, which follows OpenTelemetry semantic conventions
* and includes this middleware's version.
*/
val default: SpanDataProvider = openTelemetry.and(AttributeProvider.middlewareVersion)
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class ServerMiddlewareTests extends CatsEffectSuite {
assertEquals(span.status, StatusData.Unset)

val attributes = span.attributes.elements
assertEquals(attributes.size, 8)
assertEquals(attributes.size, 9)
def getAttr[A: AttributeKey.KeySelect](name: String): Option[A] =
attributes.get[A](name).map(_.value)

Expand All @@ -93,6 +93,10 @@ class ServerMiddlewareTests extends CatsEffectSuite {
assertEquals(getAttr[Long]("http.response.status_code"), Some(200L))
assertEquals(getAttr[Seq[String]]("http.response.header.foo"), None)
assertEquals(getAttr[Seq[String]]("http.response.header.baz"), Some(Seq("qux")))
assertEquals(
getAttr[String]("org.http4s.otel4s.middleware.version"),
Some(org.http4s.otel4s.middleware.BuildInfo.version),
)
}
}
}
Expand Down Expand Up @@ -131,6 +135,10 @@ class ServerMiddlewareTests extends CatsEffectSuite {
Attribute("network.protocol.version", "1.1"),
Attribute("url.path", "/"),
Attribute("url.scheme", "http"),
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
),
)

for {
Expand Down Expand Up @@ -166,6 +174,10 @@ class ServerMiddlewareTests extends CatsEffectSuite {
Attribute("network.protocol.version", "1.1"),
Attribute("url.path", "/"),
Attribute("url.scheme", "http"),
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
),
)

for {
Expand Down Expand Up @@ -199,6 +211,10 @@ class ServerMiddlewareTests extends CatsEffectSuite {
Attribute("network.protocol.version", "1.1"),
Attribute("url.path", "/"),
Attribute("url.scheme", "http"),
Attribute(
"org.http4s.otel4s.middleware.version",
org.http4s.otel4s.middleware.BuildInfo.version,
),
)

for {
Expand Down

0 comments on commit 731e509

Please sign in to comment.