forked from influxdata/influxdb-csharp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement Aggregation of Increment and Time measurements
Fixes influxdata#9
- Loading branch information
1 parent
7dc6860
commit c1289d4
Showing
10 changed files
with
492 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
src/InfluxDB.Collector/Configuration/CollectorAggregateConfiguration.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace InfluxDB.Collector.Configuration | ||
{ | ||
public abstract class CollectorAggregateConfiguration | ||
{ | ||
public abstract CollectorConfiguration AtInterval(TimeSpan interval); | ||
|
||
public abstract CollectorConfiguration SumIncrements(); | ||
|
||
public abstract CollectorConfiguration AggregateTimes(Func<IEnumerable<long>, double> func); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
src/InfluxDB.Collector/Configuration/PipelinedCollectorAggregateConfiguration.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using InfluxDB.Collector.Pipeline; | ||
using InfluxDB.Collector.Pipeline.Aggregate; | ||
|
||
namespace InfluxDB.Collector.Configuration | ||
{ | ||
class PipelinedCollectorAggregateConfiguration : CollectorAggregateConfiguration | ||
{ | ||
private readonly CollectorConfiguration _configuration; | ||
|
||
bool _sumIncrements; | ||
Func<IEnumerable<long>, double> _timeAggregation; | ||
TimeSpan? _interval; | ||
|
||
public PipelinedCollectorAggregateConfiguration(CollectorConfiguration configuration) | ||
{ | ||
if (configuration == null) throw new ArgumentNullException(nameof(configuration)); | ||
_configuration = configuration; | ||
} | ||
|
||
public override CollectorConfiguration AtInterval(TimeSpan interval) | ||
{ | ||
_interval = interval; | ||
return _configuration; | ||
} | ||
|
||
public override CollectorConfiguration SumIncrements() | ||
{ | ||
_sumIncrements = true; | ||
return _configuration; | ||
} | ||
|
||
public override CollectorConfiguration AggregateTimes(Func<IEnumerable<long>, double> func) | ||
{ | ||
_timeAggregation = func; | ||
return _configuration; | ||
} | ||
|
||
public IPointEmitter CreateEmitter(IPointEmitter parent, out Action dispose) | ||
{ | ||
if (_interval == null) | ||
{ | ||
dispose = null; | ||
return parent; | ||
} | ||
|
||
var aggregator = new AggregatePointEmitter(_interval.Value, _sumIncrements, _timeAggregation, parent); | ||
dispose = aggregator.Dispose; | ||
return aggregator; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
src/InfluxDB.Collector/Pipeline/Aggregate/AggregateGroupingKey.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace InfluxDB.Collector.Pipeline.Aggregate | ||
{ | ||
struct GroupingKey : IEquatable<GroupingKey> | ||
{ | ||
private static readonly Dictionary<string, string> EmptyDict = new Dictionary<string, string>(); | ||
|
||
public long Bucket { get; } | ||
|
||
public MeasurementKind Kind { get; } | ||
|
||
public string Measurement { get; } | ||
|
||
public Dictionary<string, string> Tags { get; } | ||
|
||
public GroupingKey(long bucket, MeasurementKind kind, string measurement, Dictionary<string, string> tags) | ||
{ | ||
Bucket = bucket; | ||
Kind = kind; | ||
Measurement = measurement; | ||
Tags = tags ?? EmptyDict; | ||
} | ||
|
||
public bool Equals(GroupingKey other) | ||
{ | ||
return Bucket == other.Bucket && Kind == other.Kind && Measurement == other.Measurement && DictionaryEquals(Tags, other.Tags); | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
if (ReferenceEquals(null, obj)) | ||
{ | ||
return false; | ||
} | ||
|
||
return obj is GroupingKey key && Equals(key); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
unchecked | ||
{ | ||
int hashCode = Bucket.GetHashCode(); | ||
hashCode = (hashCode * 397) ^ (int) Kind; | ||
hashCode = (hashCode * 397) ^ Measurement.GetHashCode(); | ||
hashCode = (hashCode * 397) ^ TagsHashCode(); | ||
return hashCode; | ||
} | ||
} | ||
|
||
int TagsHashCode() | ||
{ | ||
unchecked | ||
{ | ||
int hashCode = 1; | ||
foreach (var kvp in Tags) | ||
{ | ||
hashCode *= (kvp.Key.GetHashCode() * 397) ^ kvp.Key.GetHashCode(); | ||
} | ||
|
||
return hashCode; | ||
} | ||
} | ||
|
||
static bool DictionaryEquals(Dictionary<string, string> dict, Dictionary<string, string> dict2) | ||
{ | ||
if (dict.Count != dict2.Count) | ||
{ | ||
return false; | ||
} | ||
|
||
foreach (var kvp in dict) | ||
{ | ||
if (dict2.TryGetValue(kvp.Key, out string value)) | ||
{ | ||
if (value != kvp.Value) | ||
{ | ||
return false; | ||
} | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
} |
103 changes: 103 additions & 0 deletions
103
src/InfluxDB.Collector/Pipeline/Aggregate/AggregatePointEmitter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// ========================================================================== | ||
// AggregatePointEmitter.cs | ||
// Bus Portal (busliniensuche.de) | ||
// ========================================================================== | ||
// All rights reserved. | ||
// ========================================================================== | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace InfluxDB.Collector.Pipeline.Aggregate | ||
{ | ||
class AggregatePointEmitter : IPointEmitter, IDisposable | ||
{ | ||
readonly TimeSpan _timeSpan; | ||
readonly bool _sumIncrements; | ||
readonly Func<IEnumerable<long>, double> _timesAggregation; | ||
readonly IPointEmitter _parent; | ||
|
||
public AggregatePointEmitter(TimeSpan timeSpan, bool sumIncrements, Func<IEnumerable<long>, double> timesAggregation, IPointEmitter parent) | ||
{ | ||
_timeSpan = timeSpan; | ||
_sumIncrements = sumIncrements; | ||
_timesAggregation = timesAggregation; | ||
_parent = parent; | ||
} | ||
|
||
public void Emit(PointData[] points) | ||
{ | ||
var grouped = points.GroupBy(x => new GroupingKey( | ||
x.UtcTimestamp.HasValue ? x.UtcTimestamp.Value.Ticks / _timeSpan.Ticks : 0, | ||
DetermineKind(x), | ||
x.Measurement, | ||
x.Tags | ||
)); | ||
|
||
var aggregated = grouped.SelectMany(Aggregate).ToArray(); | ||
|
||
_parent.Emit(aggregated); | ||
} | ||
|
||
IEnumerable<PointData> Aggregate(IGrouping<GroupingKey, PointData> group) | ||
{ | ||
GroupingKey key = group.Key; | ||
MeasurementKind kind = key.Kind; | ||
|
||
if (kind == MeasurementKind.Increment && _sumIncrements) | ||
{ | ||
long sum = group.Sum(x => (long) x.Fields["count"]); | ||
return new[] | ||
{ | ||
new PointData( | ||
key.Measurement, | ||
new Dictionary<string, object> { { "count", sum } }, | ||
key.Tags, | ||
AverageTime(key), | ||
key.Kind) | ||
}; | ||
} | ||
|
||
if (kind == MeasurementKind.Time && _timesAggregation != null) | ||
{ | ||
long ticks = (long) _timesAggregation(group.Select(x => ((TimeSpan) x.Fields["value"]).Ticks)); | ||
return new[] | ||
{ | ||
new PointData( | ||
key.Measurement, | ||
new Dictionary<string, object> { { "value", new TimeSpan(ticks) } }, | ||
key.Tags, | ||
AverageTime(key), | ||
key.Kind) | ||
}; | ||
} | ||
|
||
return group; | ||
} | ||
|
||
private DateTime AverageTime(GroupingKey key) | ||
{ | ||
return new DateTime(key.Bucket + _timeSpan.Ticks / 2, DateTimeKind.Utc); | ||
} | ||
|
||
static MeasurementKind DetermineKind(PointData x) | ||
{ | ||
if (x.Fields.Count != 1) return MeasurementKind.Other; | ||
|
||
switch (x.Kind) | ||
{ | ||
case MeasurementKind.Increment when x.Fields.TryGetValue("count", out var count) && count is long: | ||
return MeasurementKind.Increment; | ||
case MeasurementKind.Time when x.Fields.TryGetValue("value", out var value) && value is TimeSpan: | ||
return MeasurementKind.Time; | ||
default: | ||
return MeasurementKind.Other; | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace InfluxDB.Collector.Pipeline | ||
{ | ||
public enum MeasurementKind | ||
{ | ||
Other = 0, Increment, Time | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.