org.apache.usergrid.tools.Metrics.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.usergrid.tools.Metrics.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.usergrid.tools;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.codehaus.jackson.JsonGenerator;
import org.apache.usergrid.management.ApplicationInfo;
import org.apache.usergrid.management.OrganizationInfo;
import org.apache.usergrid.management.UserInfo;
import org.apache.usergrid.persistence.AggregateCounter;
import org.apache.usergrid.persistence.CounterResolution;
import org.apache.usergrid.tools.bean.MetricLine;
import org.apache.usergrid.tools.bean.MetricQuery;
import org.apache.usergrid.tools.bean.MetricSort;
import org.apache.usergrid.utils.TimeUtils;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.lang.time.DateUtils;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Ordering;

/**
 * Tools class which dumps metrics for tracking Usergrid developer adoption and high-level application usage.
 * <p/>
 * Can be called thusly: mvn exec:java -Dexec.mainClass="org.apache.usergrid.tools.Command" -Dexec.args="Metrics -host
 * localhost -outputDir ./output"
 *
 * @author zznate
 */
public class Metrics extends ExportingToolBase {

    private List<OrganizationInfo> organizations;
    private ListMultimap<UUID, ApplicationInfo> orgApps = ArrayListMultimap.create();
    private ListMultimap<Long, UUID> totalScore = ArrayListMultimap.create();
    private Map<UUID, MetricLine> collector = new HashMap<UUID, MetricLine>();
    private int reportThreshold = 100;
    private long startDate;
    private long endDate;

    @Override
    public void runTool(CommandLine line) throws Exception {
        startSpring();

        setVerbose(line);

        prepareBaseOutputFileName(line);

        parseDuration(line);

        applyOrgId(line);

        parseDateRange(line);

        outputDir = createOutputParentDir();

        logger.info("Export directory: {}", outputDir.getAbsolutePath());

        if (orgId == null) {
            organizations = managementService.getOrganizations(null, 20000);
            for (OrganizationInfo organization : organizations) {
                logger.info("Org Name: {} key: {}", organization.getName(), organization.getUuid());
                //List<UserInfo> adminUsers = managementService.getAdminUsersForOrganization(orgId);
                applicationsFor(organization.getUuid());
            }
        } else {
            OrganizationInfo orgInfo = managementService.getOrganizationByUuid(orgId);
            applicationsFor(orgInfo.getUuid());
            organizations = new ArrayList<OrganizationInfo>();
            organizations.add(orgInfo);
        }

        Iterable<OrganizationInfo> workingOrgs = applyThreshold();

        printReport(MetricSort.APP_REQ_COUNT, workingOrgs);
    }

    @Override
    public Options createOptions() {
        Options options = super.createOptions();
        Option duration = OptionBuilder.hasArg()
                .withDescription("A duration signifying the previous time until now. "
                        + "Supported forms: h,m,d eg. '30d' would be 30 days")
                .create("duration");
        Option startDate = OptionBuilder.hasArg().withDescription("The start date of the report")
                .create("startDate");
        Option endDate = OptionBuilder.hasArg().withDescription("The end date of the report").create("endDate");

        options.addOption(duration).addOption(endDate).addOption(startDate);

        return options;
    }

    /** 30 days in milliseconds by default */
    private void parseDuration(CommandLine line) {
        String duration = line.getOptionValue("duration");
        if (duration != null) {
            startDate = TimeUtils.millisFromDuration(duration);
            endDate = System.currentTimeMillis();
        }
    }

    private void parseDateRange(CommandLine line) throws Exception {
        if (line.hasOption("startDate")) {
            startDate = DateUtils.parseDate(line.getOptionValue("startDate"), new String[] { "yyyyMMdd-HHmm" })
                    .getTime();
        }
        if (line.hasOption("endDate")) {
            endDate = DateUtils.parseDate(line.getOptionValue("endDate"), new String[] { "yyyyMMdd-HHmm" })
                    .getTime();
        }
    }

    private Iterable<OrganizationInfo> applyThreshold() throws Exception {
        Set<OrganizationInfo> orgs = new HashSet<OrganizationInfo>(reportThreshold);
        for (Long l : Ordering.natural().greatestOf(totalScore.keys(), reportThreshold)) {
            List<UUID> apps = totalScore.get(l);
            for (UUID appId : apps) {
                orgs.add(managementService.getOrganizationForApplication(appId));
            }
        }
        return orgs;
    }

    private void printReport(MetricSort metricSort, Iterable<OrganizationInfo> workingOrgs) throws Exception {
        JsonGenerator jg = getJsonGenerator(createOutputFile("metrics", metricSort.name().toLowerCase()));
        jg.writeStartObject();
        jg.writeStringField("report", metricSort.name());
        jg.writeStringField("date", new Date().toString());
        jg.writeArrayFieldStart("orgs");
        for (OrganizationInfo org : workingOrgs) {
            jg.writeStartObject();
            jg.writeStringField("org_id", org.getUuid().toString());
            jg.writeStringField("org_name", org.getName());
            jg.writeArrayFieldStart("admins");
            for (UserInfo userInfo : managementService.getAdminUsersForOrganization(org.getUuid())) {
                jg.writeString(userInfo.getEmail());
            }
            jg.writeEndArray();
            writeAppLines(jg, org.getUuid());
            jg.writeEndObject();
        }
        jg.writeEndArray();
        jg.writeEndObject();
        jg.close();
    }

    private void writeAppLines(JsonGenerator jg, UUID orgId) throws Exception {
        jg.writeArrayFieldStart("apps");
        for (ApplicationInfo appInfo : orgApps.get(orgId)) {

            jg.writeStartObject();
            jg.writeStringField("app_id", appInfo.getId().toString());
            jg.writeStringField("app_name", appInfo.getName());
            jg.writeArrayFieldStart("counts");
            MetricLine line = collector.get(appInfo.getId());
            if (line != null) {
                jg.writeStartObject();
                for (AggregateCounter ag : line.getAggregateCounters()) {
                    jg.writeStringField(new Date(ag.getTimestamp()).toString(), Long.toString(ag.getValue()));
                }
                jg.writeEndObject();
            }
            jg.writeEndArray();
            jg.writeEndObject();
        }
        jg.writeEndArray();
    }

    private void applicationsFor(UUID orgId) throws Exception {
        BiMap<UUID, String> applications = managementService.getApplicationsForOrganization(orgId);

        for (UUID uuid : applications.keySet()) {
            logger.info("Checking app: {}", applications.get(uuid));

            orgApps.put(orgId, new ApplicationInfo(uuid, applications.get(uuid)));

            collect(MetricQuery.getInstance(uuid, MetricSort.APP_REQ_COUNT).resolution(CounterResolution.DAY)
                    .startDate(startDate).endDate(endDate).execute(emf.getEntityManager(uuid)));
        }
    }

    private void collect(MetricLine metricLine) {
        for (AggregateCounter a : metricLine.getAggregateCounters()) {
            logger.info("col: {} val: {}", new Date(a.getTimestamp()), a.getValue());
        }
        totalScore.put(metricLine.getCount(), metricLine.getAppId());
        collector.put(metricLine.getAppId(), metricLine);
    }
    // line format: {reportQuery: application.requests, date: date, startDate : startDate, endDate: endDate, orgs : [
    // {orgId: guid, orgName: name, apps [{appId: guid, appName: name, dates: [{"[human date from ts]" : "[value]"},{...
}