/* * Copyright 2016 KairosDB 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.kairosdb.core.groupby; import org.json.JSONException; import org.json.JSONWriter; import org.kairosdb.core.DataPoint; import org.kairosdb.core.aggregator.annotation.GroupByName; import org.kairosdb.core.datastore.Duration; import org.kairosdb.core.datastore.TimeUnit; import org.kairosdb.core.formatter.FormatterException; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import java.io.StringWriter; import java.util.Calendar; import java.util.Map; import java.util.TimeZone; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @GroupByName(name = "time", description = "Groups data points in time ranges.") public class TimeGroupBy implements GroupBy { @NotNull private Duration rangeSize; @Min(1) private int groupCount; private long startDate; private Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); public TimeGroupBy() { } public TimeGroupBy(Duration rangeSize, int groupCount) { checkArgument(groupCount > 0); this.rangeSize = checkNotNull(rangeSize); this.groupCount = groupCount; } @Override public int getGroupId(DataPoint dataPoint, Map<String, String> tags) { if (rangeSize.getUnit() == TimeUnit.MONTHS) { calendar.setTimeInMillis(dataPoint.getTimestamp()); int dataPointYear = calendar.get(Calendar.YEAR); int dataPointMonth = calendar.get(Calendar.MONTH); calendar.setTimeInMillis(startDate); int startDateYear = calendar.get(Calendar.YEAR); int startDateMonth = calendar.get(Calendar.MONTH); return ((dataPointYear - startDateYear) * 12 + (dataPointMonth - startDateMonth)) % groupCount; } else return (int) (((dataPoint.getTimestamp() - startDate) / convertGroupSizeToMillis() ) % groupCount); } @SuppressWarnings("NumericOverflow") private long convertGroupSizeToMillis() { long milliseconds = rangeSize.getValue(); switch(rangeSize.getUnit()) { case MONTHS: throw new AssertionError(); case YEARS: milliseconds *= 52; case WEEKS: milliseconds *= 7; case DAYS: milliseconds *= 24; case HOURS: milliseconds *= 60; case MINUTES: milliseconds *= 60; case SECONDS: milliseconds *= 1000; } return milliseconds; } public void setRangeSize(Duration rangeSize) { this.rangeSize = rangeSize; } public void setGroupCount(int groupCount) { this.groupCount = groupCount; } @Override public GroupByResult getGroupByResult(final int id) { return new GroupByResult() { @Override public String toJson() throws FormatterException { StringWriter stringWriter = new StringWriter(); try { JSONWriter writer = new JSONWriter(stringWriter); writer.object(); writer.key("name").value("time"); writer.key("range_size").object(); writer.key("value").value(rangeSize.getValue()); writer.key("unit").value(rangeSize.getUnit().toString()); writer.endObject(); writer.key("group_count").value(groupCount); writer.key("group").object(); writer.key("group_number").value(id); writer.endObject(); writer.endObject(); } catch (JSONException e) { throw new FormatterException(e); } return stringWriter.toString(); } }; } @Override public void setStartDate(long startDate) { this.startDate = startDate; } }