Counting active accounts with Metrics

Based on a request parameter in a servlet context

Recently I had the task to report active accounts based on http requests. Here I’m going to show you my solution with Dropwizard Metrics.

Basically I am using a servlet filter togehter with an counter.

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;
  try {
    chain.doFilter(request, response);
  } catch (IOException | ServletException e) {
  LOG.error("unexpected exception occurred", e);
  response.sendError(HttpServletResponse.SC_BAD_REQUEST, "unexpected exception occurred");
  } finally {
  String accountNumber = request.getParameter("account");
  countRequestForAccount(accountNumber);
  }
}

private void countRequestForAccount(int account) {
  if(activeAccounts.containsKey(account))
  {
    activeAccounts.get(account).inc();
  } else if(activeAccounts.size() <= MAX_SIZE) {
    metricsRegistry.counter(Integer.toString(account)).inc();
  }
}

Each account has its own counter. So I have a ConcurrentHashMap activeAccounts with account and counter. If there is a parameter „account“ in the request, I increase the counter for that account.

The second requirement was to save the active accounts with counter in a csv file.

@Override
public void report(SortedMap<String, Gauge> gauges, SortedMap<String, Counter> counters,
SortedMap<String, Histogram> histograms, SortedMap<String, Meter> meters, SortedMap<String, Timer> timers) {
  try (BufferedWriter writer = Files.newBufferedWriter(path)) {
    for (Entry<String, Counter> entry : counters.entrySet()) {
      Counter value = entry.getValue();
      writer.write(String.format("%s;%d%n", entry.getKey(), value.getCount()));
    }
  } catch (IOException e) {
  LOG.error("couldn't write report file " + path, e);
  }
}

I extended a ScheduledReporter as shown above. The csv file has the format

account;counter

And at last, I putted together all the pieces in my servlet class.

...
public void init() throws ServletException {
  ...
  MetricRegistry metricsRegistry = (MetricRegistry) getServletContext().getAttribute(MetricsServlet.METRICS_REGISTRY);
  Path path = Paths.get("/tmp/activeAccounts.cvs"));

  ...

  reporter = new ActiveAccountsReporter(metricsRegistry, path);
  reporter.start(ACTIVE_ACCOUNTS_REPORT_PERIOD_SEC, TimeUnit.SECONDS);
  }
}

That’s it. I hope you like my article.
On GistGitHub you can read the whole example.