Loupe - Log - Monitor - Resolve
Loupe / Developer's Guide / For Java / Metrics / Event Metrics / Developer's Guide - Java - Event Metrics Example
In This Topic
    Developer's Guide - Java - Event Metrics Example
    In This Topic

    Loupe uses Event Metrics to capture details about singular events that occur as your application runs.  They provide high resolution telemetry on key events - like database calls, controller hits, and other actions.  Ideally, you want to record an event every time your application reaches out of process or is invoked from another process at a minimum: These will give you the high level view of how your application is scaling and performing.

    In this example, we will define a custom event metric for capturing JDBC call information.  We want to record the SQL Text, result size, duration, and any error for each database call.

    Defining an Event Metric

    The simplest way to define metrics is to use annotations on a DTO that contains the data we want to record.  In the example below we create a DTO that supports auto-close behavior and have it contain all of the information we want to record:

    @EventMetricClass(namespace = "yourApplicationName", categoryName = "Database",
    counterName = "Query", caption = "Database Query Performance",
    description = "Performance data for every database query")
    public class DatabaseMetric implements Closeable {
        private String query;
        private int rows;
        private Instant startTime;
        private Duration duration;
        private String result;
       
        public DatabaseMetric(String query) {
            super();
            this.query = query;
            this.result = "Success";
            startTime = Instant.now();
        }
        @EventMetricValue(name = "queryName", summaryFunction = SummaryFunction.COUNT,
    caption = "Query Name",
    description = "The name of the stored procedure or query that was executed")
        public String getQuery() {
            return query;
        }
        public void setQuery(String query) {
            this.query = query;
        }
        @EventMetricValues({@EventMetricValue(name = "duration", summaryFunction = SummaryFunction.AVERAGE, unitCaption = "ms",
    caption = "Duration",
    description = "Duration of the query execution", defaultValue = true)})
        public Duration getDuration() {
            return duration;
        }
        public void setDuration(Duration duration) {
            this.duration = duration;
        }
        @EventMetricValue(name = "result", summaryFunction = SummaryFunction.COUNT,
    caption = "Result",
    description = "The result of the query; Success or an error message.")
        public String getResult() {
            return result;
        }
        public void setResult(String result) {
            this.result = result;
        }
       
        @Override
        public void close() throws IOException {
            duration = Duration.between(startTime, Instant.now());
            EventMetric.write(this);
        }
    }
    

    Recording Samples

    To record an instance of this metric every time a database call is made, we route our database calls through an execute method with the metric added in a try block:

    private ResultSet executeQuery(Connection connection, String query) throws Exception {
        try (PreparedStatement ps = connection.prepareStatement(query)) {
            // Execute the provided command wrapped in our metric
            try (DatabaseMetric ourMetric = new DatabaseMetric(query)) {
                try {
                    return ps.executeQuery();
                } catch (Exception e) {
                    // record the error info in our metric and then re-throw the exception.
                    ourMetric.setResult(e.getMessage());
                    throw e;
                }
            }
        }
    }
    private void executeUpdate(Connection connection, String query) throws Exception {
        try (PreparedStatement ps = connection.prepareStatement(query)) {
            // Execute the provided command wrapped in our metric
            try (DatabaseMetric ourMetric = new DatabaseMetric(query)) {
                try {
                    ps.executeUpdate();
                } catch (Exception e) {
                    // record the error info in our metric and then re-throw the exception.
                    ourMetric.setResult(e.getMessage());
                    throw e;
                }
            }
        }
    }
    

    Analyzing Event Metrics

    By capturing this information, the Loupe Desktop can quickly show you a range of charts such as:

    Example Chart:  Average Duration by Query

    Example Average Duration by Query Chart

    Example Average Duration by Query Chart

    Example Chart: Count by Duration

    Example Chart: Count of Duration

    Example Chart: Count of Duration

    In addition to these charts, you can treat any value in an event metric like a sampled metric and create a graph of that value by time, such as:

    In each case, you can then add other sampled metrics to the same graph such as processor or memory utilization.

    Example Graph: Average Duration by Time

    Examle Average Duration by Time Graph

    Examle Average Duration by Time Graph

     

    See Also