Skip to content

Commit 3099069

Browse files
authored
Feat/datastax metrics config (#1228)
* feat: add metrics configuration options to datastax * feat: update datastax pureconfig readers
1 parent f918903 commit 3099069

File tree

4 files changed

+205
-21
lines changed

4 files changed

+205
-21
lines changed

cassandra-datastax-driver-pureconfig/src/main/scala-2/com/avast/sst/datastax/pureconfig/ConfigReaders.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,15 @@ trait ConfigReaders {
4848
implicit val cassandraDatastaxDriverProtocolConfigReader: ConfigReader[ProtocolConfig] = deriveReader[ProtocolConfig]
4949
implicit val cassandraDatastaxDriverMetricsConfigReader: ConfigReader[MetricsConfig] = deriveReader[MetricsConfig]
5050
implicit val cassandraDatastaxDriverSessionConfigReader: ConfigReader[SessionConfig] = deriveReader[SessionConfig]
51+
implicit val cassandraDatastaxDriverMetricsFactoryConfigReader: ConfigReader[MetricsFactoryConfig] = deriveReader[MetricsFactoryConfig]
52+
implicit val cassandraDatastaxDriverIdGeneratorConfigReader: ConfigReader[IdGeneratorConfig] = deriveReader[IdGeneratorConfig]
53+
implicit val cassandraDatastaxDriverContinuousRequestsConfigReader: ConfigReader[ContinuousCqlRequests] =
54+
deriveReader[ContinuousCqlRequests]
55+
implicit val cassandraDatastaxDriverGraphRequestsConfigReader: ConfigReader[GraphRequests] = deriveReader[GraphRequests]
5156
implicit val cassandraDatastaxDriverCqlRequestsConfigReader: ConfigReader[CqlRequestsConfig] = deriveReader[CqlRequestsConfig]
5257
implicit val cassandraDatastaxDriverThrottlingConfigReader: ConfigReader[ThrottlingConfig] = deriveReader[ThrottlingConfig]
5358
implicit val cassandraDatastaxDriverDelayConfigReader: ConfigReader[DelayConfig] = deriveReader[DelayConfig]
59+
implicit val cassandraDatastaxDriverGraphMessagesConfigReader: ConfigReader[GraphMessagesConfig] = deriveReader[GraphMessagesConfig]
5460
implicit val cassandraDatastaxDriverNodeConfigReader: ConfigReader[NodeConfig] = deriveReader[NodeConfig]
5561
implicit val cassandraDatastaxDriverCqlMessagesConfigReader: ConfigReader[CqlMessagesConfig] = deriveReader[CqlMessagesConfig]
5662
implicit val cassandraDatastaxDriverSocketConfigReader: ConfigReader[SocketConfig] = deriveReader[SocketConfig]

cassandra-datastax-driver-pureconfig/src/main/scala-3/com/avast/sst/datastax/pureconfig/ConfigReaders.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,14 @@ trait ConfigReaders {
4949
implicit val cassandraDatastaxDriverProtocolConfigReader: ConfigReader[ProtocolConfig] = ConfigReader.derived
5050
implicit val cassandraDatastaxDriverMetricsConfigReader: ConfigReader[MetricsConfig] = ConfigReader.derived
5151
implicit val cassandraDatastaxDriverSessionConfigReader: ConfigReader[SessionConfig] = ConfigReader.derived
52+
implicit val cassandraDatastaxDriverMetricsFactoryConfigReader: ConfigReader[MetricsFactoryConfig] = ConfigReader.derived
53+
implicit val cassandraDatastaxDriverIdGeneratorConfigReader: ConfigReader[IdGeneratorConfig] = ConfigReader.derived
54+
implicit val cassandraDatastaxDriverContinuousRequestsConfigReader: ConfigReader[ContinuousCqlRequests] = ConfigReader.derived
55+
implicit val cassandraDatastaxDriverGraphRequestsConfigReader: ConfigReader[GraphRequests] = ConfigReader.derived
5256
implicit val cassandraDatastaxDriverCqlRequestsConfigReader: ConfigReader[CqlRequestsConfig] = ConfigReader.derived
5357
implicit val cassandraDatastaxDriverThrottlingConfigReader: ConfigReader[ThrottlingConfig] = ConfigReader.derived
5458
implicit val cassandraDatastaxDriverDelayConfigReader: ConfigReader[DelayConfig] = ConfigReader.derived
59+
implicit val cassandraDatastaxDriverGraphMessagesConfigReader: ConfigReader[GraphMessagesConfig] = ConfigReader.derived
5560
implicit val cassandraDatastaxDriverNodeConfigReader: ConfigReader[NodeConfig] = ConfigReader.derived
5661
implicit val cassandraDatastaxDriverCqlMessagesConfigReader: ConfigReader[CqlMessagesConfig] = ConfigReader.derived
5762
implicit val cassandraDatastaxDriverSocketConfigReader: ConfigReader[SocketConfig] = ConfigReader.derived

cassandra-datastax-driver/src/main/scala/com/avast/sst/datastax/CassandraDatastaxDriverModule.scala

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@ package com.avast.sst.datastax
33
import cats.effect.{Resource, Sync}
44
import com.avast.sst.datastax.DatastaxHelper.*
55
import com.avast.sst.datastax.config.CassandraDatastaxDriverConfig
6-
import com.datastax.oss.driver.api.core.CqlSession
6+
import com.datastax.oss.driver.api.core.{CqlSession, CqlSessionBuilder}
77
import com.datastax.oss.driver.api.core.config.DefaultDriverOption.*
8+
import com.datastax.dse.driver.api.core.config.DseDriverOption.*
89
import com.datastax.oss.driver.api.core.config.{DriverConfigLoader, ProgrammaticDriverConfigLoaderBuilder as DriverBuilder}
910

1011
import javax.net.ssl.SSLContext
1112

1213
object CassandraDatastaxDriverModule {
1314

1415
/** Makes [[com.datastax.oss.driver.api.core.CqlSession]] initialized with the given config. */
15-
def make[F[_]: Sync](cfg: CassandraDatastaxDriverConfig, ssl: Option[SSLContext] = None): Resource[F, CqlSession] = {
16+
def make[F[_]: Sync](
17+
cfg: CassandraDatastaxDriverConfig,
18+
ssl: Option[SSLContext] = None,
19+
customSessionBuilderOptions: CqlSessionBuilder => CqlSessionBuilder = identity
20+
): Resource[F, CqlSession] = {
1621

1722
val acquire = Sync[F].delay {
1823

@@ -78,11 +83,27 @@ object CassandraDatastaxDriverModule {
7883
durationProperty(REQUEST_TRACE_INTERVAL)(cfg.advanced.request.trace.interval),
7984
stringProperty(REQUEST_TRACE_CONSISTENCY)(cfg.advanced.request.trace.consistency.toStringRepr),
8085
booleanProperty(REQUEST_LOG_WARNINGS)(cfg.advanced.request.logWarnings),
81-
optional(intListProperty(METRICS_SESSION_ENABLED), cfg.advanced.metrics.session.map(_.enabled)),
86+
optional(stringListProperty(METRICS_SESSION_ENABLED), cfg.advanced.metrics.session.map(_.enabled)),
87+
optional(
88+
stringProperty(METRICS_FACTORY_CLASS),
89+
cfg.advanced.metrics.factory.map(_.`class`)
90+
),
91+
optional(
92+
stringProperty(METRICS_ID_GENERATOR_CLASS),
93+
cfg.advanced.metrics.idGenerator.map(_.`class`)
94+
),
95+
optional(
96+
stringProperty(METRICS_ID_GENERATOR_PREFIX),
97+
cfg.advanced.metrics.idGenerator.flatMap(_.prefix)
98+
),
8299
optional(
83100
durationProperty(METRICS_SESSION_CQL_REQUESTS_HIGHEST),
84101
cfg.advanced.metrics.session.flatMap(_.cqlRequests.map(_.highestLatency))
85102
),
103+
optional(
104+
durationProperty(METRICS_SESSION_CQL_REQUESTS_LOWEST),
105+
cfg.advanced.metrics.session.flatMap(_.cqlRequests.map(_.lowestLatency))
106+
),
86107
optional(
87108
durationProperty(METRICS_SESSION_CQL_REQUESTS_INTERVAL),
88109
cfg.advanced.metrics.session.flatMap(_.cqlRequests.map(_.refreshInterval))
@@ -95,6 +116,10 @@ object CassandraDatastaxDriverModule {
95116
durationProperty(METRICS_SESSION_THROTTLING_HIGHEST),
96117
cfg.advanced.metrics.session.flatMap(_.throttling.flatMap(_.delay.map(_.highestLatency)))
97118
),
119+
optional(
120+
durationProperty(METRICS_SESSION_THROTTLING_LOWEST),
121+
cfg.advanced.metrics.session.flatMap(_.throttling.flatMap(_.delay.map(_.lowestLatency)))
122+
),
98123
optional(
99124
durationProperty(METRICS_SESSION_THROTTLING_INTERVAL),
100125
cfg.advanced.metrics.session.flatMap(_.throttling.flatMap(_.delay.map(_.refreshInterval)))
@@ -103,15 +128,71 @@ object CassandraDatastaxDriverModule {
103128
intProperty(METRICS_SESSION_THROTTLING_DIGITS),
104129
cfg.advanced.metrics.session.flatMap(_.throttling.flatMap(_.delay.map(_.significantDigits)))
105130
),
106-
optional(intListProperty(METRICS_NODE_ENABLED), cfg.advanced.metrics.node.map(_.enabled)),
131+
optional(
132+
durationProperty(CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST),
133+
cfg.advanced.metrics.session.flatMap(_.continuousCqlRequests.map(_.highestLatency))
134+
),
135+
optional(
136+
durationProperty(CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST),
137+
cfg.advanced.metrics.session.flatMap(_.continuousCqlRequests.map(_.lowestLatency))
138+
),
139+
optional(
140+
intProperty(CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS),
141+
cfg.advanced.metrics.session.flatMap(_.continuousCqlRequests.map(_.significantDigits))
142+
),
143+
optional(
144+
durationProperty(CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL),
145+
cfg.advanced.metrics.session.flatMap(_.continuousCqlRequests.map(_.refreshInterval))
146+
),
147+
optional(
148+
durationProperty(METRICS_SESSION_GRAPH_REQUESTS_HIGHEST),
149+
cfg.advanced.metrics.session.flatMap(_.graphRequests.map(_.highestLatency))
150+
),
151+
optional(
152+
durationProperty(METRICS_SESSION_GRAPH_REQUESTS_LOWEST),
153+
cfg.advanced.metrics.session.flatMap(_.graphRequests.map(_.lowestLatency))
154+
),
155+
optional(
156+
intProperty(METRICS_SESSION_GRAPH_REQUESTS_DIGITS),
157+
cfg.advanced.metrics.session.flatMap(_.graphRequests.map(_.significantDigits))
158+
),
159+
optional(
160+
durationProperty(METRICS_SESSION_GRAPH_REQUESTS_INTERVAL),
161+
cfg.advanced.metrics.session.flatMap(_.graphRequests.map(_.refreshInterval))
162+
),
163+
optional(stringListProperty(METRICS_NODE_ENABLED), cfg.advanced.metrics.node.map(_.enabled)),
107164
optional(
108165
durationProperty(METRICS_NODE_CQL_MESSAGES_HIGHEST),
109-
cfg.advanced.metrics.node.flatMap(_.cqlRequests.map(_.highestLatency))
166+
cfg.advanced.metrics.node.flatMap(_.cqlMessages.map(_.highestLatency))
110167
),
111-
optional(intProperty(METRICS_NODE_CQL_MESSAGES_DIGITS), cfg.advanced.metrics.node.flatMap(_.cqlRequests.map(_.significantDigits))),
168+
optional(
169+
durationProperty(METRICS_NODE_CQL_MESSAGES_LOWEST),
170+
cfg.advanced.metrics.node.flatMap(_.cqlMessages.map(_.lowestLatency))
171+
),
172+
optional(intProperty(METRICS_NODE_CQL_MESSAGES_DIGITS), cfg.advanced.metrics.node.flatMap(_.cqlMessages.map(_.significantDigits))),
112173
optional(
113174
durationProperty(METRICS_NODE_CQL_MESSAGES_INTERVAL),
114-
cfg.advanced.metrics.node.flatMap(_.cqlRequests.map(_.refreshInterval))
175+
cfg.advanced.metrics.node.flatMap(_.cqlMessages.map(_.refreshInterval))
176+
),
177+
optional(
178+
durationProperty(METRICS_NODE_GRAPH_MESSAGES_HIGHEST),
179+
cfg.advanced.metrics.node.flatMap(_.graphMessages.map(_.highestLatency))
180+
),
181+
optional(
182+
durationProperty(METRICS_NODE_GRAPH_MESSAGES_LOWEST),
183+
cfg.advanced.metrics.node.flatMap(_.graphMessages.map(_.lowestLatency))
184+
),
185+
optional(
186+
intProperty(METRICS_NODE_GRAPH_MESSAGES_DIGITS),
187+
cfg.advanced.metrics.node.flatMap(_.graphMessages.map(_.significantDigits))
188+
),
189+
optional(
190+
durationProperty(METRICS_NODE_GRAPH_MESSAGES_INTERVAL),
191+
cfg.advanced.metrics.node.flatMap(_.graphMessages.map(_.refreshInterval))
192+
),
193+
optional(
194+
durationProperty(METRICS_NODE_EXPIRE_AFTER),
195+
cfg.advanced.metrics.node.map(_.expireAfter)
115196
),
116197
durationProperty(HEARTBEAT_INTERVAL)(cfg.advanced.heartbeat.interval),
117198
durationProperty(HEARTBEAT_TIMEOUT)(cfg.advanced.heartbeat.timeout),
@@ -172,8 +253,8 @@ object CassandraDatastaxDriverModule {
172253
.build()
173254

174255
ssl match {
175-
case Some(ssl) => CqlSession.builder().withConfigLoader(loader).withSslContext(ssl).build()
176-
case None => CqlSession.builder().withConfigLoader(loader).build()
256+
case Some(ssl) => customSessionBuilderOptions(CqlSession.builder().withConfigLoader(loader).withSslContext(ssl)).build()
257+
case None => customSessionBuilderOptions(CqlSession.builder().withConfigLoader(loader)).build()
177258
}
178259
}
179260

cassandra-datastax-driver/src/main/scala/com/avast/sst/datastax/config/advanced.scala

Lines changed: 104 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -490,44 +490,95 @@ object TraceConfig {
490490

491491
/** Metrics configuration
492492
*
493+
* @param factory
494+
* Metrics Factory configuration.
495+
* @param idGenerator
496+
* This section configures how metric ids are generated. A metric id is a unique combination of a metric name and metric tags.
493497
* @param session
494498
* The session-level metrics (all disabled by default).
495499
* @param node
496500
* The node-level metrics (all disabled by default).
497501
*/
498-
final case class MetricsConfig(session: Option[SessionConfig], node: Option[NodeConfig])
502+
final case class MetricsConfig(
503+
factory: Option[MetricsFactoryConfig],
504+
idGenerator: Option[IdGeneratorConfig],
505+
session: Option[SessionConfig],
506+
node: Option[NodeConfig]
507+
)
499508

500509
object MetricsConfig {
501-
val Default: MetricsConfig = MetricsConfig(None, None)
510+
val Default: MetricsConfig = MetricsConfig(None, None, None, None)
502511
}
503512

513+
/** Metrics Factory configuration.
514+
*
515+
* @param `class`
516+
* The class for the metrics factory.
517+
*
518+
* Note: specifying a metrics factory is not enough to enable metrics; for the driver to actually start collecting metrics, you also need
519+
* to specify which metrics to collect. See the following options for more information:
520+
* - advanced.metrics.session.enabled
521+
* - advanced.metrics.node.enabled
522+
*/
523+
final case class MetricsFactoryConfig(`class`: String = "DefaultMetricsFactory")
524+
525+
/** Metric ID generator configuration.
526+
*
527+
* The driver ships with two built-in implementations:
528+
* - DefaultMetricIdGenerator: generates identifiers composed solely of (unique) metric names; It is mostly suitable for use with metrics
529+
* libraries that do not support tags, like Dropwizard.
530+
* - TaggingMetricIdGenerator: generates identifiers composed of name and tags. It is mostly suitable for use with metrics libraries that
531+
* support tags, like Micrometer or MicroProfile Metrics.
532+
*
533+
* @param `class`
534+
* The class name of a component implementing `MetricIdGenerator`. If it is not qualified, the driver assumes that it resides in the
535+
* `package com.datastax.oss.driver.internal.core.metrics`.
536+
* @param prefix
537+
* An optional prefix to prepend to each generated metric name. The prefix should not start nor end with a dot or any other path
538+
* separator; the following are two valid examples: "cassandra" or "myapp.prod.cassandra".
539+
*/
540+
final case class IdGeneratorConfig(`class`: String = "DefaultMetricIdGenerator", prefix: Option[String] = None)
541+
504542
/** The session-level metrics (all disabled by default).
505543
*
506544
* @param enabled
507545
* The session-level metrics (all disabled by default).
508546
* @param cqlRequests
509547
* Extra configuration (for the metrics that need it). Required if the 'cql-requests' metric is enabled
510548
* @param throttling
511-
* Configures request throttling metrics..
549+
* Configures request throttling metrics.
550+
* @param continuousCqlRequests
551+
* Required: if the 'continuous-cql-requests' metric is enabled, and Dropwizard or Micrometer is used.
552+
* @param graphRequests
553+
* Required: if the 'graph-requests' metric is enabled, and Dropwizard or Micrometer is used.
512554
*/
513555
final case class SessionConfig(
514-
enabled: List[Int] = List.empty,
556+
enabled: List[String] = List.empty,
515557
cqlRequests: Option[CqlRequestsConfig],
516-
throttling: Option[ThrottlingConfig]
558+
throttling: Option[ThrottlingConfig],
559+
continuousCqlRequests: Option[ContinuousCqlRequests],
560+
graphRequests: Option[GraphRequests]
517561
)
518562

519563
/** Extra metrics configuration
520564
*
521565
* @param highestLatency
522-
* The largest latency that we expect to record.
566+
* The largest latency that we expect to record.\
567+
* @param lowestLatency
568+
* The lowest latency that we expect to record.
523569
* @param significantDigits
524570
* The number of significant decimal digits to which internal structures will maintain value resolution and separation (for example, 3
525571
* means that recordings up to 1 second will be recorded with a resolution of 1 millisecond or better). This must be between 0 and 5. If
526572
* the value is out of range, it defaults to 3 and a warning is logged.
527573
* @param refreshInterval
528574
* The interval at which percentile data is refreshed.
529575
*/
530-
final case class CqlRequestsConfig(highestLatency: Duration = 3.seconds, significantDigits: Int = 3, refreshInterval: Duration = 5.minutes)
576+
final case class CqlRequestsConfig(
577+
highestLatency: Duration = 3.seconds,
578+
lowestLatency: Duration = 1.millisecond,
579+
significantDigits: Int = 3,
580+
refreshInterval: Duration = 5.minutes
581+
)
531582

532583
/** How long requests are being throttled
533584
*
@@ -538,18 +589,59 @@ final case class CqlRequestsConfig(highestLatency: Duration = 3.seconds, signifi
538589
final case class ThrottlingConfig(delay: Option[DelayConfig])
539590

540591
/** Throttling delay metric. */
541-
final case class DelayConfig(highestLatency: Duration = 3.seconds, significantDigits: Int = 3, refreshInterval: Duration = 5.minutes)
592+
final case class DelayConfig(
593+
highestLatency: Duration = 3.seconds,
594+
lowestLatency: Duration = 1.millisecond,
595+
significantDigits: Int = 3,
596+
refreshInterval: Duration = 5.minutes
597+
)
598+
599+
final case class ContinuousCqlRequests(
600+
highestLatency: Duration = 120.seconds,
601+
lowestLatency: Duration = 10.millisecond,
602+
significantDigits: Int = 3,
603+
refreshInterval: Duration = 5.minutes
604+
)
605+
606+
final case class GraphRequests(
607+
highestLatency: Duration = 12.seconds,
608+
lowestLatency: Duration = 1.millisecond,
609+
significantDigits: Int = 3,
610+
refreshInterval: Duration = 5.minutes
611+
)
542612

543613
/** Node-level metric.
544614
*
545615
* @param enabled
546616
* node-level metrics
547-
* @param cqlRequests
617+
* @param cqlMessages
548618
* Required: if the 'cql-messages' metric is enabled
549-
*/
550-
final case class NodeConfig(enabled: List[Int], cqlRequests: Option[CqlMessagesConfig])
619+
* @param graphMessages
620+
* Required: if the 'graph-messages' metric is enabled, and Dropwizard or Micrometer is used.
621+
* @param expireAfter
622+
* The time after which the node level metrics will be evicted. The lowest allowed value is 5 minutes. If you try to set it lower, the
623+
* driver will log a warning and use 5 minutes.
624+
*/
625+
final case class NodeConfig(
626+
enabled: List[String],
627+
cqlMessages: Option[CqlMessagesConfig],
628+
graphMessages: Option[GraphMessagesConfig],
629+
expireAfter: Duration = 1.hour
630+
)
551631

552-
final case class CqlMessagesConfig(highestLatency: Duration = 3.seconds, significantDigits: Int = 3, refreshInterval: Duration = 5.minutes)
632+
final case class CqlMessagesConfig(
633+
highestLatency: Duration = 3.seconds,
634+
lowestLatency: Duration = 1.millisecond,
635+
significantDigits: Int = 3,
636+
refreshInterval: Duration = 5.minutes
637+
)
638+
639+
final case class GraphMessagesConfig(
640+
highestLatency: Duration = 3.seconds,
641+
lowestLatency: Duration = 1.millisecond,
642+
significantDigits: Int = 3,
643+
refreshInterval: Duration = 5.minutes
644+
)
553645

554646
/** Socket configuration.
555647
*

0 commit comments

Comments
 (0)