question

wederbrand avatar image
wederbrand asked wederbrand commented

Is it possible to have multiple RequestTrackers with the Java driver?

Hi!

I can configure the default RequestLogger like this

   datastax-java-driver {
     advanced.request-tracker {
       class = RequestLogger

It works great but I'm also using another RequestTracker in my application and I can't find a way to have both.

I know that internally there is a MultiplexingRequestTracker to which serveral RequestTrackers can be .registered(). It seems to be created really late though, after Springs CqlSessionBuilderCustomizer for instance. If I add a RequestTracker there the configured one will not be created.

Is there any customizer I can use that would give me the MultiplexingRequestTracker to append RequestTrackers to?

If not, can I create my own MultiplexingRequestTracker and add both the RequestLogger and my own RequestTracker to it? How would I get ahold of the DriverContext needed?

It feels like I'm getting to close to the core for comfort ;)


EDIT, added example:

The BoundStatementProfile inherits from RequestTracker

@Bean
@ConditionalOnClass(MeterRegistry.class)
public CqlSessionBuilderCustomizer requstTrackerCustomizer(MeterRegistry meterRegistry) {
   return cqlSessionBuilder -> {
      // Create a MultiplexingRequestTracker to be able to add both logging and the BoundStatementProfiler
      // This, and how the RequestLogger is created, mimics
      // com.datastax.oss.driver.internal.core.context.DefaultDriverContext.buildRequestTracker
      MultiplexingRequestTracker multiplexingRequestTracker = new MultiplexingRequestTracker();

      // TODO: Get the DriverContext
      // RequestLogger requestLogger = new RequestLogger(driverContext);
      // multiplexingRequestTracker.register(requestLogger);

      BoundStatementProfiler boundStatementProfiler = new BoundStatementProfiler(meterRegistry);
      multiplexingRequestTracker.register(boundStatementProfiler);

      cqlSessionBuilder.withRequestTracker(multiplexingRequestTracker);
   };
}


java driverspring-bootspring
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

alexandre.dutra avatar image
alexandre.dutra answered wederbrand commented

I suggest creating separate beans for each request tracker:

@Bean
public CqlSessionBuilderCustomizer cqlSessionBuilderCustomizer(MultiplexingRequestTracker multiplexingRequestTracker) {
    return cqlSessionBuilder -> {
        cqlSessionBuilder.withRequestTracker(multiplexingRequestTracker);
    };
}

@Bean
public MultiplexingRequestTracker multiplexingRequestTracker() {
    return new MultiplexingRequestTracker();
}

@Bean
@ConditionalOnClass(MeterRegistry.class)
public BoundStatementProfiler boundStatementProfiler(MeterRegistry meterRegistry, MultiplexingRequestTracker multiplexingRequestTracker) {
    BoundStatementProfiler boundStatementProfiler = new BoundStatementProfiler(meterRegistry);
    multiplexingRequestTracker.register(boundStatementProfiler);
    return boundStatementProfiler;
}

@Bean
public RequestLogger requestLogger(CqlSession cqlSession, MultiplexingRequestTracker multiplexingRequestTracker) {
    RequestLogger requestLogger = new RequestLogger(cqlSession.getContext());
    multiplexingRequestTracker.register(requestLogger);
    return requestLogger;
}

Please note: I didn't fully validate this solution, but I think you got the general ideal. One possible drawback is that the boundStatementProfiler and requestLogger beans won't be automatically created, unless you inject them somewhere, or request them manually with something like:

ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
context.getBean(BoundStatementProfiler.class);
context.getBean(RequestLogger.class);
1 comment Share
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

wederbrand avatar image wederbrand commented ·

This works great. I wasn't aware that CqlSession contained the context. That was the missing piece.

And infact the beans are created, at least in my class annotated with

@Configuration

Thanks!

0 Likes 0 ·
Erick Ramirez avatar image
Erick Ramirez answered Erick Ramirez commented

[UPDATED] Olivier Michallat advised that you can use an instance of MultiplexingRequestTracker directly in the session. Something like this:

MultiplexingRequestTracker multiTracker = ...;
...
CqlSession session = CqlSession.builder().withRequestTracker(multiTracker).build();

You should then be able to add child trackers to the multi-tracker instance with register() . Cheers!

6 comments Share
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

wederbrand avatar image wederbrand commented ·

The RequestLogger is normally created from within DefaultDriverContext. Can I get that context somehow?

0 Likes 0 ·
Erick Ramirez avatar image Erick Ramirez ♦♦ wederbrand commented ·

You should still be able to get the context in the same manner. Or did I misunderstand your question?

Perhaps if you provide an example of what you're trying to achieve, I'd be able to pass it on to the team. Cheers!

0 Likes 0 ·
wederbrand avatar image wederbrand Erick Ramirez ♦♦ commented ·

Sure think, I've added it to the question

0 Likes 0 ·
Erick Ramirez avatar image Erick Ramirez ♦♦ wederbrand commented ·

Thanks. I'm looking at your update now and I don't think you can register a logger here:

      // RequestLogger requestLogger = new RequestLogger(driverContext);
      // multiplexingRequestTracker.register(requestLogger);

The register() takes a RequestTracker:

  public void register(RequestTracker tracker) {
    trackers.add(tracker);
  }

See the 4.6.0 MultiplexingRequestTracker.register() here. Cheers!

0 Likes 0 ·
wederbrand avatar image wederbrand Erick Ramirez ♦♦ commented ·

The RequestLogger is a RequestTracker

public class RequestLogger implements RequestTracker {
  


0 Likes 0 ·
Show more comments