com.graphaware.reco.generic.stats.DefaultStatistics.java Source code

Java tutorial

Introduction

Here is the source code for com.graphaware.reco.generic.stats.DefaultStatistics.java

Source

/*
 * Copyright (c) 2015 GraphAware
 *
 * This file is part of GraphAware.
 *
 * GraphAware is free software: you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of
 * the GNU General Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

package com.graphaware.reco.generic.stats;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import static org.springframework.util.StringUtils.hasLength;

/**
 * Default production implementation of {@link com.graphaware.reco.generic.stats.Statistics}.
 * <p/>
 * This class is thread-safe.
 *
 * @param <IN> type of the input into the recommendation-computing process.
 */
public class DefaultStatistics<IN> implements Statistics {

    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private static final Logger LOG = LoggerFactory.getLogger(DefaultStatistics.class);

    private final ConcurrentMap<String, ConcurrentMap<String, Object>> stats = new ConcurrentHashMap<>();
    private final TaskTimer timer = new DefaultTaskTimer();

    private final IN input;

    /**
     * Create a new object encapsulating statistics.
     *
     * @param input into the recommendation-computing process, for which statistics are being collected.
     */
    public DefaultStatistics(IN input) {
        this.input = input;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void startTiming(String task) {
        hasLength(task);

        timer.startTiming(task);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stopTiming(String task) {
        hasLength(task);

        addStatistic(task, ELAPSED_TIME, timer.getTime(task));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addStatistic(String task, String name, Object value) {
        if (getStatistics(task).putIfAbsent(name, value) != null) {
            LOG.warn("Could not add statistic " + name + " for task " + task + ". There's already another value.");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void incrementStatistic(String task, String name) {
        ConcurrentMap<String, Object> taskStats = getStatistics(task);

        AtomicInteger count = (AtomicInteger) taskStats.get(name);
        if (count == null) {
            taskStats.putIfAbsent(name, new AtomicInteger());
            count = (AtomicInteger) taskStats.get(name);
        }

        count.incrementAndGet();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<String, ? extends Map<String, Object>> get() {
        return stats;
    }

    private ConcurrentMap<String, Object> getStatistics(String task) {
        ConcurrentMap<String, Object> taskStats = stats.get(task);

        if (taskStats == null) {
            stats.putIfAbsent(task, new ConcurrentHashMap<String, Object>());
            taskStats = stats.get(task);
        }
        return taskStats;
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder("=== Statistics for ").append(input).append(" ===")
                .append(LINE_SEPARATOR);
        for (String task : stats.keySet()) {
            stringBuilder.append("=== ").append(task).append(" ===").append(LINE_SEPARATOR);
            for (Map.Entry<String, Object> entry : stats.get(task).entrySet()) {
                stringBuilder.append(entry.getKey()).append(": ").append(entry.getValue()).append(LINE_SEPARATOR);
            }
        }
        return stringBuilder.toString();
    }
}