/*
* Copyright 2002-2013 the original author or authors.
*
* 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 org.springframework.xd.shell.command;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;
import org.joda.time.DateTimeConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.PagedResources;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.stereotype.Component;
import org.springframework.xd.rest.client.AggregateCounterOperations;
import org.springframework.xd.rest.client.AggregateCounterOperations.Resolution;
import org.springframework.xd.rest.domain.metrics.AggregateCountsResource;
import org.springframework.xd.rest.domain.metrics.MetricResource;
import org.springframework.xd.shell.XDShell;
import org.springframework.xd.shell.converter.NumberFormatConverter;
import org.springframework.xd.shell.util.Assertions;
import org.springframework.xd.shell.util.Table;
import org.springframework.xd.shell.util.TableHeader;
/**
* Commands for interacting with aggregate counter analytics.
*
* @author Ilayaperumal Gopinathan
*/
@Component
public class AggregateCounterCommands extends AbstractMetricsCommands implements CommandMarker {
protected AggregateCounterCommands() {
super("AggregateCounter");
}
private static final String DISPLAY_AGGR_COUNTER = "aggregate-counter display";
private static final String LIST_AGGR_COUNTERS = "aggregate-counter list";
private static final String DELETE_AGGR_COUNTER = "aggregate-counter delete";
@Autowired
private XDShell xdShell;
@CliAvailabilityIndicator({ DISPLAY_AGGR_COUNTER, LIST_AGGR_COUNTERS, DELETE_AGGR_COUNTER })
public boolean available() {
return xdShell.getSpringXDOperations() != null;
}
@CliCommand(value = DISPLAY_AGGR_COUNTER, help = "Display aggregate counter values by chosen interval and resolution(minute, hour)")
public Table display(
@CliOption(key = { "", "name" }, help = "the name of the aggregate counter to display", mandatory = true, optionContext = "existing-aggregate-counter disable-string-converter") String name,
@CliOption(key = "from", help = "start-time for the interval. format: 'yyyy-MM-dd HH:mm:ss'", mandatory = false) String from,
@CliOption(key = "to", help = "end-time for the interval. format: 'yyyy-MM-dd HH:mm:ss'. defaults to now", mandatory = false) String to,
@CliOption(key = "lastHours", help = "set the interval to last 'n' hours", mandatory = false) Integer lastHours,
@CliOption(key = "lastDays", help = "set the interval to last 'n' days", mandatory = false) Integer lastDays,
@CliOption(key = "resolution", help = "the size of the bucket to aggregate (minute, hour, day, month)", mandatory = false, unspecifiedDefaultValue = "hour") Resolution resolution,
@CliOption(key = "pattern", help = "the pattern used to format the count values (see DecimalFormat)", mandatory = false, unspecifiedDefaultValue = NumberFormatConverter.DEFAULT) NumberFormat pattern) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date fromDate;
switch (Assertions.atMostOneOf("from", from, "lastHours", lastHours, "lastDays", lastDays)) {
case 0:
fromDate = dateFormat.parse(from);
break;
case 1:
fromDate = new Date(System.currentTimeMillis() - ((long) lastHours)
* DateTimeConstants.MILLIS_PER_HOUR);
break;
case 2:
fromDate = new Date(System.currentTimeMillis() - ((long) lastDays)
* DateTimeConstants.MILLIS_PER_DAY);
break;
default:
fromDate = null;
break;
}
Date toDate = (to == null) ? null : dateFormat.parse(to);
AggregateCountsResource aggResource = aggrCounterOperations().retrieve(name, fromDate, toDate, resolution);
return displayAggrCounter(aggResource, pattern);
}
catch (ParseException pe) {
throw new IllegalArgumentException(
"Parse exception ocurred while parsing the 'from/to' options. The accepted date format is "
+ dateFormat.toPattern());
}
}
@CliCommand(value = LIST_AGGR_COUNTERS, help = "List all available aggregate counter names")
public Table list(/* TODO */) {
PagedResources<MetricResource> list = aggrCounterOperations().list(/* TODO */);
return displayMetrics(list);
}
@CliCommand(value = DELETE_AGGR_COUNTER, help = "Delete an aggregate counter")
public String delete(
@CliOption(key = { "", "name" }, help = "the name of the aggregate counter to delete", mandatory = true, optionContext = "existing-aggregate-counter disable-string-converter") String name) {
aggrCounterOperations().delete(name);
return String.format("Deleted aggregatecounter '%s'", name);
}
private AggregateCounterOperations aggrCounterOperations() {
return xdShell.getSpringXDOperations().aggrCounterOperations();
}
private Table displayAggrCounter(AggregateCountsResource aggResource, NumberFormat pattern) {
final SortedMap<Date, Long> values = aggResource.getValues();
Table t = new Table();
t.addHeader(1, new TableHeader("AggregateCounter=" + aggResource.getName())).addHeader(2, new TableHeader(""))
.addHeader(3, new TableHeader(""));
t.newRow().addValue(1, "TIME").addValue(2, "-").addValue(3, "COUNT");
for (Map.Entry<Date, Long> entry : values.entrySet()) {
t.newRow().addValue(1, entry.getKey().toString()).addValue(2, "|")
.addValue(3, pattern.format(entry.getValue()));
}
return t;
}
}