Skip to content

Commit

Permalink
feat: Support tags/fields in Influx exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
Jairon Terrero authored and CrownedPhoenix committed Dec 5, 2024
1 parent 0d5da64 commit b354858
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ struct ExportableBenchmark: Codable {

struct TestData: Codable {
var test: String
var tags: [String: String]
var fields: [String: Field]
var iterations: Int
var warmupIterations: Int
var data: [TestMetricData]

struct Field: Codable {
let type: String
let value: String
}
}

struct TestMetricData: Codable {
Expand Down Expand Up @@ -53,18 +60,30 @@ class InfluxCSVFormatter {
let processors = machine.processors
let memory = machine.memory

if header {
let dataTypeHeader = "#datatype tag,tag,tag,tag,tag,tag,tag,tag,tag,double,double,long,long,dateTime\n"
finalFileFormat.append(dataTypeHeader)
let headers = "measurement,hostName,processoryType,processors,memory,kernelVersion,metric,unit,test,value,test_average,iterations,warmup_iterations,time\n"
finalFileFormat.append(headers)
}

for testData in exportableBenchmark.benchmarks {
let orderedTags = testData.tags.map({ (key: $0, value: $1) })
let orderedFields = testData.fields.map({ (key: $0, field: $1) })

let customHeaderDataTypes = String(repeating: "tag,", count: orderedTags.count)
+ orderedFields.map({ "\($0.field.type)," }).joined()

let customHeaders = (orderedTags.map({ "\($0.key)," })
+ orderedFields.map({ "\($0.key)," })).joined()

if header {
let dataTypeHeader = "#datatype tag,tag,tag,tag,tag,tag,tag,tag,tag,\(customHeaderDataTypes)double,double,long,long,dateTime\n"
finalFileFormat.append(dataTypeHeader)
let headers = "measurement,hostName,processoryType,processors,memory,kernelVersion,metric,unit,test,\(customHeaders)value,test_average,iterations,warmup_iterations,time\n"
finalFileFormat.append(headers)
}

let testName = testData.test
let iterations = testData.iterations
let warmup_iterations = testData.warmupIterations

let customTagValues = orderedTags.map({ "\($0.value)," }).joined()
let customFieldValues = orderedFields.map({ "\($0.field.value)," }).joined()

for granularData in testData.data {
let metric = granularData.metric
.replacingOccurrences(of: " ", with: "")
Expand All @@ -73,10 +92,11 @@ class InfluxCSVFormatter {

for dataTableValue in granularData.metricsdata {
let time = ISO8601DateFormatter().string(from: Date())
let dataLine = "\(exportableBenchmark.target),\(hostName),\(processorType),\(processors),\(memory),\(kernelVersion),\(metric),\(units),\(testName),\(dataTableValue),\(average),\(iterations),\(warmup_iterations),\(time)\n"
let dataLine = "\(exportableBenchmark.target),\(hostName),\(processorType),\(processors),\(memory),\(kernelVersion),\(metric),\(units),\(testName),\(customTagValues)\(customFieldValues)\(dataTableValue),\(average),\(iterations),\(warmup_iterations),\(time)\n"
finalFileFormat.append(dataLine)
}
}
finalFileFormat.append("\n")
}

return finalFileFormat
Expand Down Expand Up @@ -161,9 +181,23 @@ extension BenchmarkTool {
iterations = results.statistics.measurementCount
warmupIterations = results.warmupIterations
}

let exportConfig = profile.benchmark.configuration.exportConfigurations?[.influx] as? InfluxExportConfiguration

var tags: [String: String] = [:]
var fields: [String: TestData.Field] = [:]
for (tag, value) in profile.benchmark.configuration.tags {
if let field = exportConfig?.fields[tag] {
fields[tag] = TestData.Field(type: field.rawValue, value: value)
} else {
tags[tag] = value
}
}

testList.append(
TestData(test: cleanedTestName,
tags: tags,
fields: fields,
iterations: iterations,
warmupIterations: warmupIterations,
data: benchmarkResultData)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ public struct BenchmarkExportConfigurationKey: Hashable, Codable {
private let value: String
}

public extension BenchmarkExportConfigurationKey {
static var influx: Self { .init(value: #function) }

Check warning on line 9 in Sources/Benchmark/BenchmarkExportConfigurations/BenchmarkExportConfiguration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Benchmark/BenchmarkExportConfigurations/BenchmarkExportConfiguration.swift#L9

Added line #L9 was not covered by tests
}

/// The set of export configurations for a particular benchmark
public struct BenchmarkExportConfigurations: Codable {
let configs: [BenchmarkExportConfigurationKey: any BenchmarkExportConfiguration]
Expand Down Expand Up @@ -38,6 +42,7 @@ extension BenchmarkExportConfigurationKey {
static func resolveConfigType(from key: Self) -> BenchmarkExportConfiguration.Type? {
switch key {
// Add a case here when adding a new exporter config
case .influx: InfluxExportConfiguration.self
default: nil
}
}

Check warning on line 48 in Sources/Benchmark/BenchmarkExportConfigurations/BenchmarkExportConfiguration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Benchmark/BenchmarkExportConfigurations/BenchmarkExportConfiguration.swift#L42-L48

Added lines #L42 - L48 were not covered by tests
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
public struct InfluxExportConfiguration: BenchmarkExportConfiguration {
/// The set of benchmark tags to interpret as Influx fields.
/// The default is to treat benchmark tags as Influx tags.
public let fields: [String: InfluxDataType]

public enum InfluxDataType: String, Codable {
// References: https://docs.influxdata.com/influxdb/cloud/reference/syntax/annotated-csv/#data-types

case boolean
/// Unsigned 64-bit integer
case unsignedLong
/// Signed 64-bit integer
case long
/// IEEE-754 64-bit floating-point number
case double
/// UTF-8 encoded string
case string
/// Base64 encoded sequence of bytes as defined in RFC 4648
case base64Binary
/// Instant in time, may be followed with a colon : and a description of the format (number, RFC3339, RFC3339Nano)
case dateTime
/// Length of time represented as an unsigned 64-bit integer number of nanoseconds
case duration
}

public init(fields: [String: InfluxDataType]) {
self.fields = fields
}

Check warning on line 28 in Sources/Benchmark/BenchmarkExportConfigurations/InfluxExportConfiguration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Benchmark/BenchmarkExportConfigurations/InfluxExportConfiguration.swift#L26-L28

Added lines #L26 - L28 were not covered by tests
}

0 comments on commit b354858

Please sign in to comment.