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.