Skip to content

Commit

Permalink
Refactor labels to tags in metering and tracing events
Browse files Browse the repository at this point in the history
Replaced all instances of labels with tags for consistency and clarity across metering and tracing events. Introduced new type aliases, `Tags` and `MutableTags`, to streamline type definitions and improve code readability.
  • Loading branch information
smyrgeorge committed Nov 14, 2024
1 parent 53a6b58 commit ff0d0ac
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 82 deletions.
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ repeat(1_000_000) {
// # ...
// # After some ~4k logs starts to drop.
// 991339 2024-10-24T07:19:38.294933Z [native-1] - INFO Main - 991224
// 2024-10-24T07:19:38.295050Z [native-13] - WARN FlowFloodProtectedAppender - Dropped 6556 log messages due to flooding (total: 987299).
// 2024-10-24T07:19:38.295050Z [native-13] - WARN FlowFloodProtectedAppender - Dropped 6556 log messages due to flooding (total dropped: 987299).
// 995897 2024-10-24T07:19:38.314454Z [native-1] - INFO Main - 995782
// 2024-10-24T07:19:38.315134Z [native-19] - WARN FlowFloodProtectedAppender - Dropped 4557 log messages due to flooding (total: 991856).
// 2024-10-24T07:19:38.315134Z [native-19] - WARN FlowFloodProtectedAppender - Dropped 4557 log messages due to flooding (total dropped: 991856).
```

To tackle similar issues, we can apply dynamic rate-limiting based on system load or log severity, prioritizing critical
Expand Down Expand Up @@ -189,19 +189,23 @@ span.end()
Similarly to the logging API, we also support a more kotlin style API:

```kotlin
// Starts immediately the span.
trace.span("test") {
// it is [TracingEvent.Span.Local]
trace.span("test", parent) {
log.info(this, "this is a test with span") // The log will contain the span id.
// Set span tags.
it.tags["key"] = "value"
tags["key"] = "value"
// Send events that are related to the current span.
it.event(name = "event-1", level = Level.DEBUG)
it.debug(name = "event-1") // Same as event(name = "event-1", level = Level.DEBUG)
event(name = "event-1", level = Level.DEBUG)
debug(name = "event-1") // Same as event(name = "event-1", level = Level.DEBUG)
// Include tags in the event.
it.event(name = "event-2", tags = mapOf("key" to "value"))
it.event(name = "event-2") { tags: MutableMap<String, Any?> ->
event(name = "event-2", tags = mapOf("key" to "value"))
event(name = "event-2") { tags ->
tags["key"] = "value"
}
// Nested Span.
trace.span("test-2", this) {
event(name = "event-3", tags = mapOf("key" to "value"))
log.info(this@span, "this is a test with span") // The log will contain the span id.
}
// Automatically closes at the end of te scope.
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,18 +120,23 @@ class Main {
// NOTICE: we do not start it, since it's already started.
val parent: TracingEvent.Span.Remote = trace.span(id = "ID_EXAMPLE", traceId = "TRACE_ID_EXAMPLE")
// Starts immediately the span.
trace.span("test", parent) {
log.info(it, "this is a test with span") // The log will contain the span id.
trace.span("test-1", parent) {
log.info(this, "this is a test with span") // The log will contain the span id.
// Set span tags.
it.tags["key"] = "value"
tags["key"] = "value"
// Send events that are related to the current span.
it.event(name = "event-1", level = Level.DEBUG)
it.debug(name = "event-1") // Same as event(name = "event-1", level = Level.DEBUG)
event(name = "event-1", level = Level.DEBUG)
debug(name = "event-1") // Same as event(name = "event-1", level = Level.DEBUG)
// Include tags in the event.
it.event(name = "event-2", tags = mapOf("key" to "value"))
it.event(name = "event-2") { tags ->
event(name = "event-2", tags = mapOf("key" to "value"))
event(name = "event-2") { tags ->
tags["key"] = "value"
}
// Nested Span.
trace.span("test-2", this) {
event(name = "event-3", tags = mapOf("key" to "value"))
log.info(this@span, "this is a test with span") // The log will contain the span id.
}
// Automatically closes at the end of te scope.
}

Expand Down
32 changes: 16 additions & 16 deletions log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Meter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -147,28 +147,28 @@ abstract class Meter(
description: String? = null,
) : Instrument(name, meter, kind, unit, description) {
/**
* Sets the counter to the specified non-negative value with associated labels.
* Sets the counter to the specified non-negative value with associated tags.
*
* @param value The non-negative value to set the counter to.
* @param labels A vararg of pairs representing additional labels/metadata associated with the set action.
* @param tags A vararg of pairs representing additional tags/metadata associated with the set action.
*/
fun set(value: T, vararg labels: Pair<String, Any>) {
fun set(value: T, vararg tags: Pair<String, Any>) {
if (meter.isMuted()) return
if (value.isLessThanZero()) error("Only non-negative values are allowed.")
val event = MeteringEvent.Set(name = name, labels = labels.toMap(), value = value)
val event = MeteringEvent.Set(name = name, tags = tags.toMap(), value = value)
RootLogger.meter(event)
}

/**
* Increments the counter by the specified non-negative value with associated labels.
* Increments the counter by the specified non-negative value with associated tags.
*
* @param value The non-negative value by which to increment the counter.
* @param labels A vararg of pairs representing additional labels/metadata associated with the increment action.
* @param tags A vararg of pairs representing additional tags/metadata associated with the increment action.
*/
fun increment(value: T, vararg labels: Pair<String, Any>) {
fun increment(value: T, vararg tags: Pair<String, Any>) {
if (meter.isMuted()) return
if (value.isLessThanZero()) error("Only non-negative values are allowed.")
val event = MeteringEvent.Increment(name = name, labels = labels.toMap(), value = value)
val event = MeteringEvent.Increment(name = name, tags = tags.toMap(), value = value)
RootLogger.meter(event)
}

Expand All @@ -182,7 +182,7 @@ abstract class Meter(
}

/**
* AbstractRecorder is a sealed class used for recording numerical data attached to specific labels.
* AbstractRecorder is a sealed class used for recording numerical data attached to specific tags.
* It extends the Instrument class and provides functionality for recording and periodically polling data.
*
* @param T the type of numerical data to be recorded, constrained by the Number class.
Expand All @@ -200,15 +200,15 @@ abstract class Meter(
description: String? = null,
) : Instrument(name, meter, kind, unit, description) {
/**
* Records a metering event with a specified value and optional labels.
* Records a metering event with a specified value and optional tags.
* If the meter is muted, the event will not be recorded.
*
* @param value The value to be recorded.
* @param labels A variable number of pairs representing the labels associated with the event.
* @param tags A variable number of pairs representing the tags associated with the event.
*/
fun record(value: T, vararg labels: Pair<String, Any>) {
fun record(value: T, vararg tags: Pair<String, Any>) {
if (meter.isMuted()) return
val event = MeteringEvent.Record(name = name, labels = labels.toMap(), value = value)
val event = MeteringEvent.Record(name = name, tags = tags.toMap(), value = value)
RootLogger.meter(event)
}

Expand Down Expand Up @@ -281,12 +281,12 @@ abstract class Meter(
* The value must be non-negative.
*
* @param value The non-negative value to decrement from the counter.
* @param labels Optional key-value pairs of labels associated with the decrement event.
* @param tags Optional key-value pairs of tags associated with the decrement event.
*/
fun decrement(value: T, vararg labels: Pair<String, Any>) {
fun decrement(value: T, vararg tags: Pair<String, Any>) {
if (meter.isMuted()) return
if (value.isLessThanZero()) error("Only non-negative values are allowed.")
val event = MeteringEvent.Increment(name = name, labels = labels.toMap(), value = value)
val event = MeteringEvent.Increment(name = name, tags = tags.toMap(), value = value)
RootLogger.meter(event)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.smyrgeorge.log4k

import io.github.smyrgeorge.log4k.Meter.Instrument.Kind
import io.github.smyrgeorge.log4k.impl.Tags
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant

Expand Down Expand Up @@ -28,39 +29,39 @@ sealed interface MeteringEvent {
}

sealed interface ValueEvent : MeteringEvent {
val labels: Map<String, Any>
val tags: Tags
val value: Number
override fun key(): Int = "$name.${labels.hashCode()}".hashCode()
override fun key(): Int = "$name.${tags.hashCode()}".hashCode()
}

data class Set(
override var id: Long = 0L,
override val name: String,
override val labels: Map<String, Any>,
override val tags: Tags,
override val timestamp: Instant = Clock.System.now(),
override val value: Number,
) : ValueEvent

data class Increment(
override var id: Long = 0L,
override val name: String,
override val labels: Map<String, Any>,
override val tags: Tags,
override val timestamp: Instant = Clock.System.now(),
override val value: Number,
) : ValueEvent

data class Decrement(
override var id: Long = 0L,
override val name: String,
override val labels: Map<String, Any>,
override val tags: Tags,
override val timestamp: Instant = Clock.System.now(),
override val value: Number,
) : ValueEvent

data class Record(
override var id: Long = 0L,
override val name: String,
override val labels: Map<String, Any>,
override val tags: Tags,
override val timestamp: Instant = Clock.System.now(),
override val value: Number,
) : ValueEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ abstract class Tracer(
inline fun <T> span(
name: String,
parent: TracingEvent.Span? = null,
f: (TracingEvent.Span.Local) -> T
f: TracingEvent.Span.Local.() -> T
): T {
val span = span(name, parent).start()
return try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package io.github.smyrgeorge.log4k
import io.github.smyrgeorge.log4k.TracingEvent.Span.Local
import io.github.smyrgeorge.log4k.TracingEvent.Span.Remote
import io.github.smyrgeorge.log4k.impl.OpenTelemetry
import io.github.smyrgeorge.log4k.impl.MutableTags
import io.github.smyrgeorge.log4k.impl.Tags
import io.github.smyrgeorge.log4k.impl.extensions.toName
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
Expand Down Expand Up @@ -35,7 +37,7 @@ sealed interface TracingEvent {
open val parent: Span?,
var startAt: Instant?,
var endAt: Instant?,
val tags: MutableMap<String, Any?>,
val tags: MutableTags,
val events: MutableList<Event>,
var status: Status,
) : TracingEvent {
Expand All @@ -45,7 +47,7 @@ sealed interface TracingEvent {
*
* This constructor initializes a local Span with the provided identifier, name,
* level, tracer, parent span, and trace identifier. The start and end timestamps
* are initially set to null. Tags and events are initialized to empty mutable
* are initially set to null. MutableTags and events are initialized to empty mutable
* collections, and the status is initialized to a default Status object.
*
* @param id Unique identifier for the span.
Expand Down Expand Up @@ -158,7 +160,7 @@ sealed interface TracingEvent {
* @param level The logging level of the event, determining its severity.
* @param tags A map of tags associated with the event, defaults to an empty map.
*/
fun event(name: String, level: Level, tags: Map<String, Any?> = emptyMap()) {
fun event(name: String, level: Level, tags: Tags = emptyMap()) {
if (!shouldStart()) return
if (!shouldLogEvent(level)) return
if (!started || closed) return
Expand All @@ -178,7 +180,7 @@ sealed interface TracingEvent {
* @param escaped A boolean indicating if the exception was propagated.
* @param tags A map of additional tags to associate with the exception event.
*/
fun exception(error: Throwable, escaped: Boolean, tags: Map<String, Any?> = emptyMap()) {
fun exception(error: Throwable, escaped: Boolean, tags: Tags = emptyMap()) {
val event = Event(
name = OpenTelemetry.EXCEPTION,
timestamp = Clock.System.now(),
Expand All @@ -199,29 +201,30 @@ sealed interface TracingEvent {
* @param escaped Boolean indicating if the exception was propagated.
* @param f Function to populate a mutable map of additional tags to associate with the exception event.
*/
fun exception(error: Throwable, escaped: Boolean, f: (MutableMap<String, Any?>) -> Unit) {
val tags: MutableMap<String, Any?> = mutableMapOf()
f(tags)
exception(error, escaped, tags)
fun exception(error: Throwable, escaped: Boolean, f: (MutableTags) -> Unit) {
mutableMapOf<String, Any>().also {
f(it)
exception(error, escaped, it)
}
}

inline fun trace(name: String, f: (MutableMap<String, Any?>) -> Unit) = event(name, Level.TRACE, f)
inline fun debug(name: String, f: (MutableMap<String, Any?>) -> Unit) = event(name, Level.DEBUG, f)
inline fun info(name: String, f: (MutableMap<String, Any?>) -> Unit) = event(name, Level.INFO, f)
inline fun warn(name: String, f: (MutableMap<String, Any?>) -> Unit) = event(name, Level.WARN, f)
inline fun error(name: String, f: (MutableMap<String, Any?>) -> Unit) = event(name, Level.ERROR, f)
inline fun trace(name: String, f: (Tags) -> Unit) = event(name, Level.TRACE, f)
inline fun debug(name: String, f: (Tags) -> Unit) = event(name, Level.DEBUG, f)
inline fun info(name: String, f: (Tags) -> Unit) = event(name, Level.INFO, f)
inline fun warn(name: String, f: (Tags) -> Unit) = event(name, Level.WARN, f)
inline fun error(name: String, f: (Tags) -> Unit) = event(name, Level.ERROR, f)

fun trace(name: String, tags: Map<String, Any?> = emptyMap()) = event(name, Level.TRACE, tags)
fun debug(name: String, tags: Map<String, Any?> = emptyMap()) = event(name, Level.DEBUG, tags)
fun info(name: String, tags: Map<String, Any?> = emptyMap()) = event(name, Level.INFO, tags)
fun warn(name: String, tags: Map<String, Any?> = emptyMap()) = event(name, Level.WARN, tags)
fun error(name: String, tags: Map<String, Any?> = emptyMap()) = event(name, Level.ERROR, tags)
fun trace(name: String, tags: Tags = emptyMap()) = event(name, Level.TRACE, tags)
fun debug(name: String, tags: Tags = emptyMap()) = event(name, Level.DEBUG, tags)
fun info(name: String, tags: Tags = emptyMap()) = event(name, Level.INFO, tags)
fun warn(name: String, tags: Tags = emptyMap()) = event(name, Level.WARN, tags)
fun error(name: String, tags: Tags = emptyMap()) = event(name, Level.ERROR, tags)

fun event(name: String, f: (MutableMap<String, Any?>) -> Unit) = event(name, level, f)
fun event(name: String, tags: Map<String, Any?> = emptyMap()) = event(name, level, tags)
fun event(name: String, f: (MutableTags) -> Unit) = event(name, level, f)
fun event(name: String, tags: Tags = emptyMap()) = event(name, level, tags)

inline fun event(name: String, level: Level, f: (MutableMap<String, Any?>) -> Unit) {
mutableMapOf<String, Any?>().also {
inline fun event(name: String, level: Level, f: (MutableTags) -> Unit) {
mutableMapOf<String, Any>().also {
f(it)
event(name, level, it)
}
Expand Down
Loading

0 comments on commit ff0d0ac

Please sign in to comment.