Skip to content

Commit c0e674d

Browse files
author
Jairon Terrero
committed
feat: Support tags/fields in Influx exporter
1 parent d10454b commit c0e674d

File tree

3 files changed

+76
-8
lines changed

3 files changed

+76
-8
lines changed

Plugins/BenchmarkTool/BenchmarkTool+Export+InfluxCSVFormatter.swift

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,16 @@ struct ExportableBenchmark: Codable {
1919

2020
struct TestData: Codable {
2121
var test: String
22+
var tags: [String: String]
23+
var fields: [String: Field]
2224
var iterations: Int
2325
var warmupIterations: Int
2426
var data: [TestMetricData]
27+
28+
struct Field: Codable {
29+
let type: String
30+
let value: String
31+
}
2532
}
2633

2734
struct TestMetricData: Codable {
@@ -53,18 +60,30 @@ class InfluxCSVFormatter {
5360
let processors = machine.processors
5461
let memory = machine.memory
5562

56-
if header {
57-
let dataTypeHeader = "#datatype tag,tag,tag,tag,tag,tag,tag,tag,tag,double,double,long,long,dateTime\n"
58-
finalFileFormat.append(dataTypeHeader)
59-
let headers = "measurement,hostName,processoryType,processors,memory,kernelVersion,metric,unit,test,value,test_average,iterations,warmup_iterations,time\n"
60-
finalFileFormat.append(headers)
61-
}
62-
6363
for testData in exportableBenchmark.benchmarks {
64+
let orderedTags = testData.tags.map({ (key: $0, value: $1) })
65+
let orderedFields = testData.fields.map({ (key: $0, value: $1) })
66+
67+
let customHeaderDataTypes = String(repeating: "tag,", count: orderedTags.count)
68+
+ orderedFields.map({ "\($0.value.type)," }).joined()
69+
70+
let customHeaders = (orderedTags.map({ "\($0.key)," })
71+
+ orderedFields.map({ "\($0.key)," })).joined()
72+
73+
if header {
74+
let dataTypeHeader = "#datatype tag,tag,tag,tag,tag,tag,tag,tag,tag,\(customHeaderDataTypes)double,double,long,long,dateTime\n"
75+
finalFileFormat.append(dataTypeHeader)
76+
let headers = "measurement,hostName,processoryType,processors,memory,kernelVersion,metric,unit,test,\(customHeaders)value,test_average,iterations,warmup_iterations,time\n"
77+
finalFileFormat.append(headers)
78+
}
79+
6480
let testName = testData.test
6581
let iterations = testData.iterations
6682
let warmup_iterations = testData.warmupIterations
6783

84+
let customTagValues = orderedTags.map({ "\($0.value)," }).joined()
85+
let customFieldValues = orderedFields.map({ "\($0.value.value)," }).joined()
86+
6887
for granularData in testData.data {
6988
let metric = granularData.metric
7089
.replacingOccurrences(of: " ", with: "")
@@ -73,10 +92,11 @@ class InfluxCSVFormatter {
7392

7493
for dataTableValue in granularData.metricsdata {
7594
let time = ISO8601DateFormatter().string(from: Date())
76-
let dataLine = "\(exportableBenchmark.target),\(hostName),\(processorType),\(processors),\(memory),\(kernelVersion),\(metric),\(units),\(testName),\(dataTableValue),\(average),\(iterations),\(warmup_iterations),\(time)\n"
95+
let dataLine = "\(exportableBenchmark.target),\(hostName),\(processorType),\(processors),\(memory),\(kernelVersion),\(metric),\(units),\(testName),\(customTagValues)\(customFieldValues)\(dataTableValue),\(average),\(iterations),\(warmup_iterations),\(time)\n"
7796
finalFileFormat.append(dataLine)
7897
}
7998
}
99+
finalFileFormat.append("\n")
80100
}
81101

82102
return finalFileFormat
@@ -161,9 +181,23 @@ extension BenchmarkTool {
161181
iterations = results.statistics.measurementCount
162182
warmupIterations = results.warmupIterations
163183
}
184+
185+
let exportConfig = profile.benchmark.configuration.exportConfigurations?[.influx] as? InfluxExportConfiguration
186+
187+
var tags: [String: String] = [:]
188+
var fields: [String: TestData.Field] = [:]
189+
for (tag, value) in profile.benchmark.configuration.tags {
190+
if let field = exportConfig?.fields[tag] {
191+
fields[tag] = TestData.Field(type: field.rawValue, value: value)
192+
} else {
193+
tags[tag] = value
194+
}
195+
}
164196

165197
testList.append(
166198
TestData(test: cleanedTestName,
199+
tags: tags,
200+
fields: fields,
167201
iterations: iterations,
168202
warmupIterations: warmupIterations,
169203
data: benchmarkResultData)

Sources/Benchmark/BenchmarkExportConfigurations/BenchmarkExportConfiguration.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ public struct BenchmarkExportConfigurationKey: Hashable, Codable {
55
private let value: String
66
}
77

8+
public extension BenchmarkExportConfigurationKey {
9+
static var influx: Self { .init(value: #function) }
10+
}
11+
812
/// The set of export configurations for a particular benchmark
913
public struct BenchmarkExportConfigurations: Codable {
1014
let configs: [BenchmarkExportConfigurationKey: any BenchmarkExportConfiguration]
@@ -38,6 +42,7 @@ extension BenchmarkExportConfigurationKey {
3842
static func resolveConfigType(from key: Self) -> BenchmarkExportConfiguration.Type? {
3943
switch key {
4044
// Add a case here when adding a new exporter config
45+
case .influx: InfluxExportConfiguration.self
4146
default: nil
4247
}
4348
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
public struct InfluxExportConfiguration: BenchmarkExportConfiguration {
2+
/// The set of benchmark tags to interpret as Influx fields.
3+
/// The default is to treat benchmark tags as Influx tags.
4+
public let fields: [String: InfluxDataType]
5+
6+
public enum InfluxDataType: String, Codable {
7+
// References: https://docs.influxdata.com/influxdb/cloud/reference/syntax/annotated-csv/#data-types
8+
9+
case boolean
10+
/// Unsigned 64-bit integer
11+
case unsignedLong
12+
/// Signed 64-bit integer
13+
case long
14+
/// IEEE-754 64-bit floating-point number
15+
case double
16+
/// UTF-8 encoded string
17+
case string
18+
/// Base64 encoded sequence of bytes as defined in RFC 4648
19+
case base64Binary
20+
/// Instant in time, may be followed with a colon : and a description of the format (number, RFC3339, RFC3339Nano)
21+
case dateTime
22+
/// Length of time represented as an unsigned 64-bit integer number of nanoseconds
23+
case duration
24+
}
25+
26+
public init(fields: [String: InfluxDataType]) {
27+
self.fields = fields
28+
}
29+
}

0 commit comments

Comments
 (0)