Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 75f8a68

Browse files
authored
Merge pull request #1073 from iRevive/sdk-logs/blrp-auto-configure
sdk-logs: add `BatchLogRecordProcessorAutoConfigure`
2 parents 12aef6d + 597c0e6 commit 75f8a68

File tree

2 files changed

+259
-0
lines changed

2 files changed

+259
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright 2025 Typelevel
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.typelevel.otel4s.sdk.logs.autoconfigure
18+
19+
import cats.effect.Resource
20+
import cats.effect.Temporal
21+
import cats.effect.std.Console
22+
import cats.syntax.flatMap._
23+
import cats.syntax.foldable._
24+
import org.typelevel.otel4s.sdk.autoconfigure.AutoConfigure
25+
import org.typelevel.otel4s.sdk.autoconfigure.Config
26+
import org.typelevel.otel4s.sdk.logs.exporter.LogRecordExporter
27+
import org.typelevel.otel4s.sdk.logs.processor.BatchLogRecordProcessor
28+
import org.typelevel.otel4s.sdk.logs.processor.LogRecordProcessor
29+
30+
import scala.concurrent.duration.FiniteDuration
31+
import scala.util.chaining._
32+
33+
/** Autoconfigures [[BatchLogRecordProcessor]].
34+
*
35+
* The configuration options:
36+
* {{{
37+
* | System property | Environment variable | Description |
38+
* |---------------------------------|---------------------------------|-----------------------------------------------------------------------|
39+
* | otel.blrp.schedule.delay | OTEL_BLRP_SCHEDULE_DELAY | The interval between two consecutive exports. Default is `5 seconds`. |
40+
* | otel.blrp.max.queue.size | OTEL_BLRP_MAX_QUEUE_SIZE | The maximum queue size. Default is `2048`. |
41+
* | otel.blrp.max.export.batch.size | OTEL_BLRP_MAX_EXPORT_BATCH_SIZE | The maximum batch size. Default is `512`. |
42+
* | otel.blrp.export.timeout | OTEL_BLRP_EXPORT_TIMEOUT | The maximum allowed time to export data. Default is `30 seconds`. |
43+
* }}}
44+
*
45+
* @see
46+
* [[https://opentelemetry.io/docs/specs/otel/logs/sdk/#batching-processor]]
47+
*
48+
* @see
49+
* [[https://opentelemetry.io/docs/languages/java/configuration/#properties-logs]]
50+
*
51+
* @param exporter
52+
* the exporter to use with the configured batch log record processor
53+
*/
54+
private final class BatchLogRecordProcessorAutoConfigure[F[_]: Temporal: Console](
55+
exporter: LogRecordExporter[F]
56+
) extends AutoConfigure.WithHint[F, LogRecordProcessor[F]](
57+
"BatchLogRecordProcessor",
58+
BatchLogRecordProcessorAutoConfigure.ConfigKeys.All
59+
) {
60+
61+
import BatchLogRecordProcessorAutoConfigure.ConfigKeys
62+
63+
def fromConfig(config: Config): Resource[F, LogRecordProcessor[F]] = {
64+
def configure =
65+
for {
66+
scheduleDelay <- config.get(ConfigKeys.ScheduleDelay)
67+
maxQueueSize <- config.get(ConfigKeys.MaxQueueSize)
68+
maxExportBatchSize <- config.get(ConfigKeys.MaxExportBatchSize)
69+
exporterTimeout <- config.get(ConfigKeys.ExporterTimeout)
70+
} yield BatchLogRecordProcessor
71+
.builder(exporter)
72+
.pipe(b => scheduleDelay.foldLeft(b)(_.withScheduleDelay(_)))
73+
.pipe(b => maxQueueSize.foldLeft(b)(_.withMaxQueueSize(_)))
74+
.pipe(b => maxExportBatchSize.foldLeft(b)(_.withMaxExportBatchSize(_)))
75+
.pipe(b => exporterTimeout.foldLeft(b)(_.withExporterTimeout(_)))
76+
.build
77+
78+
Resource.suspend(
79+
Temporal[F]
80+
.catchNonFatal(configure)
81+
.flatMap(e => Temporal[F].fromEither(e))
82+
)
83+
}
84+
85+
}
86+
87+
private[sdk] object BatchLogRecordProcessorAutoConfigure {
88+
89+
private object ConfigKeys {
90+
val ScheduleDelay: Config.Key[FiniteDuration] =
91+
Config.Key("otel.blrp.schedule.delay")
92+
93+
val MaxQueueSize: Config.Key[Int] =
94+
Config.Key("otel.blrp.max.queue.size")
95+
96+
val MaxExportBatchSize: Config.Key[Int] =
97+
Config.Key("otel.blrp.max.export.batch.size")
98+
99+
val ExporterTimeout: Config.Key[FiniteDuration] =
100+
Config.Key("otel.blrp.export.timeout")
101+
102+
val All: Set[Config.Key[_]] =
103+
Set(ScheduleDelay, MaxQueueSize, MaxExportBatchSize, ExporterTimeout)
104+
}
105+
106+
/** Autoconfigures [[BatchLogRecordProcessor]].
107+
*
108+
* The configuration options:
109+
* {{{
110+
* | System property | Environment variable | Description |
111+
* |---------------------------------|---------------------------------|-----------------------------------------------------------------------|
112+
* | otel.blrp.schedule.delay | OTEL_BLRP_SCHEDULE_DELAY | The interval between two consecutive exports. Default is `5 seconds`. |
113+
* | otel.blrp.max.queue.size | OTEL_BLRP_MAX_QUEUE_SIZE | The maximum queue size. Default is `2048`. |
114+
* | otel.blrp.max.export.batch.size | OTEL_BLRP_MAX_EXPORT_BATCH_SIZE | The maximum batch size. Default is `512`. |
115+
* | otel.blrp.export.timeout | OTEL_BLRP_EXPORT_TIMEOUT | The maximum allowed time to export data. Default is `30 seconds`. |
116+
* }}}
117+
*
118+
* @see
119+
* [[https://opentelemetry.io/docs/languages/java/configuration/#properties-logs]]
120+
*
121+
* @param exporter
122+
* the exporter to use with the configured batch log record processor
123+
*/
124+
def apply[F[_]: Temporal: Console](exporter: LogRecordExporter[F]): AutoConfigure[F, LogRecordProcessor[F]] =
125+
new BatchLogRecordProcessorAutoConfigure[F](exporter)
126+
127+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright 2025 Typelevel
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.typelevel.otel4s.sdk.logs.autoconfigure
18+
19+
import cats.effect.IO
20+
import cats.syntax.all._
21+
import munit.CatsEffectSuite
22+
import org.typelevel.otel4s.sdk.autoconfigure.Config
23+
import org.typelevel.otel4s.sdk.logs.exporter.LogRecordExporter
24+
25+
class BatchLogRecordProcessorAutoConfigureSuite extends CatsEffectSuite {
26+
27+
private val exporter = LogRecordExporter.noop[IO]
28+
29+
private val default =
30+
"BatchLogRecordProcessor{" +
31+
"exporter=LogRecordExporter.Noop, " +
32+
"scheduleDelay=5 seconds, " +
33+
"exporterTimeout=30 seconds, " +
34+
"maxQueueSize=2048, " +
35+
"maxExportBatchSize=512}"
36+
37+
test("load from an empty config - load default") {
38+
val config = Config(Map.empty, Map.empty, Map.empty)
39+
40+
BatchLogRecordProcessorAutoConfigure[IO](exporter)
41+
.configure(config)
42+
.use { processor =>
43+
IO(assertEquals(processor.name, default))
44+
}
45+
}
46+
47+
test("load from the config (empty string) - load default") {
48+
val props = Map(
49+
"otel.blrp.schedule.delay" -> "",
50+
"otel.blrp.max.queue.size" -> "",
51+
"otel.blrp.max.export.batch.size" -> "",
52+
"otel.blrp.export.timeout" -> "",
53+
)
54+
val config = Config.ofProps(props)
55+
56+
BatchLogRecordProcessorAutoConfigure[IO](exporter)
57+
.configure(config)
58+
.use { processor =>
59+
IO(assertEquals(processor.name, default))
60+
}
61+
}
62+
63+
test("load from the config - use given value") {
64+
val props = Map(
65+
"otel.blrp.schedule.delay" -> "1s",
66+
"otel.blrp.max.queue.size" -> "42",
67+
"otel.blrp.max.export.batch.size" -> "128",
68+
"otel.blrp.export.timeout" -> "120 millis",
69+
)
70+
val config = Config.ofProps(props)
71+
72+
val expected =
73+
"BatchLogRecordProcessor{" +
74+
"exporter=LogRecordExporter.Noop, " +
75+
"scheduleDelay=1 second, " +
76+
"exporterTimeout=120 milliseconds, " +
77+
"maxQueueSize=42, " +
78+
"maxExportBatchSize=128}"
79+
80+
BatchLogRecordProcessorAutoConfigure[IO](exporter)
81+
.configure(config)
82+
.use { processor =>
83+
IO(assertEquals(processor.name, expected))
84+
}
85+
}
86+
87+
test("invalid config values - fail") {
88+
val inputs = List(
89+
"otel.blrp.schedule.delay" -> "some delay",
90+
"otel.blrp.max.queue.size" -> "-128",
91+
"otel.blrp.max.export.batch.size" -> "not int",
92+
"otel.blrp.export.timeout" -> "non-parsable",
93+
)
94+
95+
val errors = Map(
96+
"otel.blrp.schedule.delay" -> "Invalid value for property otel.blrp.schedule.delay=some delay. Must be [FiniteDuration]",
97+
"otel.blrp.max.queue.size" -> "Dropping queue capacity must be positive, was: -128",
98+
"otel.blrp.max.export.batch.size" -> "Invalid value for property otel.blrp.max.export.batch.size=not int. Must be [Int]",
99+
"otel.blrp.export.timeout" -> "Invalid value for property otel.blrp.export.timeout=non-parsable. Must be [FiniteDuration]",
100+
)
101+
102+
inputs.traverse { case (key, value) =>
103+
val config = Config.ofProps(Map(key -> value))
104+
val error = errors(key)
105+
106+
val delay = if (key == "otel.blrp.schedule.delay") value else "N/A"
107+
val queueSize = if (key == "otel.blrp.max.queue.size") value else "N/A"
108+
val batchSize =
109+
if (key == "otel.blrp.max.export.batch.size") value else "N/A"
110+
val timeout = if (key == "otel.blrp.export.timeout") value else "N/A"
111+
112+
BatchLogRecordProcessorAutoConfigure[IO](exporter)
113+
.configure(config)
114+
.evalMap(IO.println)
115+
.use_
116+
.attempt
117+
.map(_.leftMap(_.getMessage))
118+
.assertEquals(
119+
Left(
120+
s"""Cannot autoconfigure [BatchLogRecordProcessor].
121+
|Cause: $error.
122+
|Config:
123+
|1) `otel.blrp.export.timeout` - $timeout
124+
|2) `otel.blrp.max.export.batch.size` - $batchSize
125+
|3) `otel.blrp.max.queue.size` - $queueSize
126+
|4) `otel.blrp.schedule.delay` - $delay""".stripMargin
127+
)
128+
)
129+
}
130+
131+
}
132+
}

0 commit comments

Comments
 (0)