io.apiman.gateway.engine.jdbc.JdbcMetrics.java Source code

Java tutorial

Introduction

Here is the source code for io.apiman.gateway.engine.jdbc.JdbcMetrics.java

Source

/*
 * Copyright 2016 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.apiman.gateway.engine.jdbc;

import io.apiman.gateway.engine.IComponentRegistry;
import io.apiman.gateway.engine.IMetrics;
import io.apiman.gateway.engine.metrics.RequestMetric;

import java.util.Calendar;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

import org.apache.commons.dbutils.QueryRunner;

/**
 * A JDBC implementation of the gateway registry.  Only suitable for a 
 * synchronous environment - should not be used when running an async 
 * Gateway (e.g. vert.x).
 * 
 * Must be configured with the JNDI location of the datasource to use.
 * Example:
 * 
 *     apiman-gateway.registry=io.apiman.gateway.engine.jdbc.JdbcRegistry
 *     apiman-gateway.registry.datasource.jndi-location=java:jboss/datasources/apiman-gateway
 * 
 * @author ewittman
 */
public class JdbcMetrics extends AbstractJdbcComponent implements IMetrics {

    private static final int DEFAULT_QUEUE_SIZE = 10000;

    protected IComponentRegistry componentRegistry;
    protected final BlockingQueue<RequestMetric> queue;

    private boolean stopped;
    private Thread thread;

    /**
     * Constructor.
     * @param config map of configuration options
     */
    public JdbcMetrics(Map<String, String> config) {
        super(config);

        int queueSize = DEFAULT_QUEUE_SIZE;
        String queueSizeConfig = config.get("queue.size"); //$NON-NLS-1$
        if (queueSizeConfig != null) {
            queueSize = new Integer(queueSizeConfig);
        }
        queue = new LinkedBlockingDeque<>(queueSize);
        startConsumerThread();
    }

    /**
     * Starts a thread which will serially pull information off the blocking
     * queue and submit that information to hawkular metrics.
     */
    private void startConsumerThread() {
        stopped = false;
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!stopped) {
                    processQueue();
                }
            }
        }, "JdbcMetricsConsumer"); //$NON-NLS-1$
        thread.setDaemon(true);
        thread.start();
    }

    /**
     * Process the next item in the queue.
     */
    @SuppressWarnings("nls")
    protected void processQueue() {
        try {
            RequestMetric metric = queue.take();
            QueryRunner run = new QueryRunner(ds);

            Calendar cal = Calendar.getInstance();
            cal.setTimeZone(TimeZone.getTimeZone("UTC"));
            cal.setTime(metric.getRequestStart());

            long rstart = cal.getTimeInMillis();
            long rend = metric.getRequestEnd().getTime();
            long duration = metric.getRequestDuration();
            cal.set(Calendar.MILLISECOND, 0);
            cal.set(Calendar.SECOND, 0);
            long minute = cal.getTimeInMillis();
            cal.set(Calendar.MINUTE, 0);
            long hour = cal.getTimeInMillis();
            cal.set(Calendar.HOUR_OF_DAY, 0);
            long day = cal.getTimeInMillis();
            cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
            long week = cal.getTimeInMillis();
            cal.set(Calendar.DAY_OF_MONTH, 1);
            long month = cal.getTimeInMillis();
            String api_org_id = metric.getApiOrgId();
            String api_id = metric.getApiId();
            String api_version = metric.getApiVersion();
            String client_org_id = metric.getClientOrgId();
            String client_id = metric.getClientId();
            String client_version = metric.getClientVersion();
            String plan = metric.getPlanId();
            String user_id = metric.getUser();
            String rtype = null;
            if (metric.isFailure()) {
                rtype = "failure";
            } else if (metric.isError()) {
                rtype = "error";
            }
            long bytes_up = metric.getBytesUploaded();
            long bytes_down = metric.getBytesDownloaded();

            // Now insert a row for the metric.
            run.update("INSERT INTO gw_requests (" + "rstart, rend, duration, month, week, day, hour, minute, "
                    + "api_org_id, api_id, api_version, " + "client_org_id, client_id, client_version, plan, "
                    + "user_id, resp_type, bytes_up, bytes_down) VALUES (" + "?, ?, ?, ?, ?, ?, ?, ?," + "?, ?, ?,"
                    + "?, ?, ?, ?," + "?, ?, ?, ?)", rstart, rend, duration, month, week, day, hour, minute,
                    api_org_id, api_id, api_version, client_org_id, client_id, client_version, plan, user_id, rtype,
                    bytes_up, bytes_down);
        } catch (InterruptedException ie) {
            // This means that the thread was stopped.
        } catch (Exception e) {
            // TODO better logging of this unlikely error
            System.err.println("Error adding metric to database:"); //$NON-NLS-1$
            e.printStackTrace();
            return;
        }
    }

    /**
     * @see io.apiman.gateway.engine.IMetrics#record(io.apiman.gateway.engine.metrics.RequestMetric)
     */
    @Override
    public void record(RequestMetric metric) {
        try {
            queue.put(metric);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @see io.apiman.gateway.engine.IMetrics#setComponentRegistry(io.apiman.gateway.engine.IComponentRegistry)
     */
    @Override
    public void setComponentRegistry(IComponentRegistry registry) {
        this.componentRegistry = registry;
    }

    /**
     * Called to stop the consumer thread (used for testing only).
     */
    protected void stop() {
        stopped = true;
        thread.interrupt();
    }

}