package org.kairosdb.core.aggregator;
import com.google.common.collect.ImmutableSortedMap;
import com.google.inject.Inject;
import org.kairosdb.core.DataPoint;
import org.kairosdb.core.aggregator.annotation.AggregatorName;
import org.kairosdb.core.aggregator.annotation.AggregatorProperty;
import org.kairosdb.core.datastore.DataPointGroup;
import org.kairosdb.core.datastore.Datastore;
import org.kairosdb.core.exception.DatastoreException;
import org.kairosdb.core.groupby.GroupBy;
import org.kairosdb.core.groupby.GroupByResult;
import org.kairosdb.core.groupby.TagGroupBy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
Created by bhawkins on 8/28/15.
*/
@AggregatorName(
name = "save_as",
description = "Saves the results to a new metric.",
properties = {
@AggregatorProperty(name = "metric_name", type = "string")
}
)
public class SaveAsAggregator implements Aggregator, GroupByAware
{
private Datastore m_datastore;
private String m_metricName;
private Map<String, String> m_tags;
private int m_ttl = 0;
private Set<String> m_tagsToKeep = new HashSet<>();
private boolean m_addSavedFrom = true;
@Inject
public SaveAsAggregator(Datastore datastore)
{
m_datastore = datastore;
m_tags = new HashMap<String, String>();
}
public SaveAsAggregator(Datastore datastore, String metricName)
{
this(datastore);
m_metricName = metricName;
m_tags = new HashMap<String, String>();
}
public void setAddSavedFrom(boolean addSavedFrom)
{
m_addSavedFrom = addSavedFrom;
}
public void setMetricName(String metricName)
{
m_metricName = metricName;
}
public void setTags(Map<String, String> tags)
{
m_tags = tags;
}
public void setTtl(int ttl)
{
m_ttl = ttl;
}
public String getMetricName()
{
return m_metricName;
}
public Map<String, String> getTags()
{
return m_tags;
}
@Override
public DataPointGroup aggregate(DataPointGroup dataPointGroup)
{
return new SaveAsDataPointAggregator(dataPointGroup);
}
@Override
public boolean canAggregate(String groupType)
{
return true;
}
@Override
public String getAggregatedGroupType(String groupType)
{
return groupType;
}
@Override
public void setGroupBys(List<GroupBy> groupBys)
{
for (GroupBy groupBy : groupBys)
{
if (groupBy instanceof TagGroupBy)
{
TagGroupBy tagGroupBy = (TagGroupBy) groupBy;
m_tagsToKeep.addAll(tagGroupBy.getTagNames());
}
}
}
private class SaveAsDataPointAggregator implements DataPointGroup
{
private DataPointGroup m_innerDataPointGroup;
private ImmutableSortedMap<String, String> m_groupTags;
public SaveAsDataPointAggregator(DataPointGroup innerDataPointGroup)
{
m_innerDataPointGroup = innerDataPointGroup;
ImmutableSortedMap.Builder<String, String> mapBuilder = ImmutableSortedMap.<String, String>naturalOrder();
mapBuilder.putAll(m_tags);
if (m_addSavedFrom)
mapBuilder.put("saved_from", innerDataPointGroup.getName());
for (String innerTag : innerDataPointGroup.getTagNames())
{
Set<String> tagValues = innerDataPointGroup.getTagValues(innerTag);
if (m_tagsToKeep.contains(innerTag) && (tagValues.size() == 1))
mapBuilder.put(innerTag, tagValues.iterator().next());
}
m_groupTags = mapBuilder.build();
}
@Override
public boolean hasNext()
{
return m_innerDataPointGroup.hasNext();
}
@Override
public DataPoint next()
{
DataPoint next = m_innerDataPointGroup.next();
try
{
m_datastore.putDataPoint(m_metricName, m_groupTags, next, m_ttl);
}
catch (DatastoreException e)
{
throw new RuntimeException("Failure to save data to "+m_metricName, e);
}
return next;
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
@Override
public String getName()
{
return m_innerDataPointGroup.getName();
}
@Override
public List<GroupByResult> getGroupByResult()
{
return m_innerDataPointGroup.getGroupByResult();
}
@Override
public void close()
{
m_innerDataPointGroup.close();
}
@Override
public Set<String> getTagNames()
{
return m_innerDataPointGroup.getTagNames();
}
@Override
public Set<String> getTagValues(String tag)
{
return m_innerDataPointGroup.getTagValues(tag);
}
}
}