Vimalraj Selvam
Vimalraj Selvam

Reputation: 2245

Dynamic tag values for the Counter metric in Micrometer

Newbie here, trying to learn more about the micrometer. I'm currently exploring ways on how to accomplish this:

I'm using Spring boot 2 with actuator and micrometer enabled. Consider the following class:

@Component
class MyService {
  @Autowired
  AuthorizeTransaction callbackTransaction;

  @Autowired
  AuthorizeTransaction immediateTransaction;

  private MeterRegistry meterRegistry;
  private Counter requestCounter;
  private Counter responseCounter;

  public MyService(MeterRegistry meterRegistry) {
    this.meterRegistry = meterRegistry;
    initCounters();
  }

  private initCounters() {
    requestCounter = Counter.builder("iso_request")
                      .tags("mti", "0100")  // how do I change the value of this tag for other request types like 0200, 0120, etc.,
                      .register(meterRegistry);
    responseCounter = Counter.builder("iso_response")
                      .tags("mti", "0101")
                      .tags("response_code", "00") // how do I change the value of this tag for other response codes like 01, 09, etc.,
                      .register(meterRegistry);
  }

  public ISOMsg process(ISOMsg request) {
    ISOMsg response = null;

    try {
      switch(request.getMTI()) {  // org.jboss.iso.ISOMsg
        case "0100":
        case "0200":
          if ("0100".equals(request.getMTI())) {
            requestCounter.increment();
          } else {
            requestCounter.increment(); // I want to increment the counter of the same metric with tag mti=0200
          }
          response = immediateTransaction.process(request);
          // here I want to increment the response counter but with different MTIs and response codes
          break;
        case "0120":
        case "0121"
          response = callbackTransaction.process(request);
          break;
        default:
          log.error("error here")
      }
    } catch (Exception e) {
      log.error("error here")
    }

    return response;
  }
}

I'm stuck here and have to create different counter variables for each combination of tag values and the readability of the code gets affected really bad. I've many switch case statements than the above example. There should be definitely an easy way to do this, however I'm unable to find.

Upvotes: 28

Views: 32428

Answers (3)

wumbrath
wumbrath

Reputation: 59

With a global registry as used in a Spring service, the simplest way for me was doing:

io.micrometer.core.instrument.Metrics.counter("counter_name", "tag_1_key", "tag_1_value", "tag_2_key", "tag_2_value").increment();

So, for your case it would be

io.micrometer.core.instrument.Metrics.counter("iso_response", "mti", "0101", "response_code", "00").increment();

From JavaDoc the parameters following the counter name

MUST be an even number of arguments representing key/value pairs of tags

Upvotes: 0

Markus Pscheidt
Markus Pscheidt

Reputation: 7331

To have "dynamic" tag values, simply skip the instantiation of the counters in the initCounters() method. Everytime the counter shall be increased, instantiate a counter by using its builder method and increment, for example:

Counter.builder("iso_response")
    .tags("mti", request.getMTI())
    .tags("response_code", myReponseCode)
    .register(meterRegistry)
    .increment();

In fact, as the io.micrometer.core.instrument.Counter.Builder.register method states in its JavaDoc, a new counter is returned only if a counter with the same tag values does not yet exist. This is because each registry is guaranteed to only create one counter for the same combination of name and tags.

Upvotes: 20

RUARO Thibault
RUARO Thibault

Reputation: 2850

You have to use a Builder if you want to count with a specific Tag. Here is how :

@Component
class MyService {
  @Autowired
  AuthorizeTransaction callbackTransaction;

  @Autowired
  AuthorizeTransaction immediateTransaction;

  private MeterRegistry meterRegistry;
  private Counter.Builder requestCounter;
  private Counter.Builder responseCounter;

  public MyService(MeterRegistry meterRegistry) {
    this.meterRegistry = meterRegistry;
    initCounters();
  }

  private initCounters() {
    requestCounter = Counter.builder("iso_request");
    responseCounter = Counter.builder("iso_response");
  }

  public ISOMsg process(ISOMsg request) {
    ISOMsg response = null;

    try {
      switch(request.getMTI()) {  // org.jboss.iso.ISOMsg
        case "0100":
        case "0200":
          requestCounter.tag("mti", request.getMTI()).registry(meterRegistry);
          response = immediateTransaction.process(request);
          responseCounter.tags("mti", request.getMTI(), "response_code", "0101").registry(meterRegistry);
          // here I want to increment the response counter but with different MTIs and response codes
          break;
        case "0120":
        case "0121"
          response = callbackTransaction.process(request);
          break;
        default:
          log.error("error here")
      }
    } catch (Exception e) {
      log.error("error here")
    }

    return response;
  }
}

Think about:

  • Creating a class to encapsulate your Counter logic
  • Using constant for your tags

Let me know if it worked !

Upvotes: 11

Related Questions