feat(csv): change to csv from jsonl

This commit is contained in:
2025-09-27 21:59:53 +01:00
parent 2240d18f0b
commit 65bca470eb
3 changed files with 55 additions and 14 deletions

View File

@@ -75,7 +75,7 @@ func (r *MeasurementRunner) runMeasurement(upstream string, domains []string, qT
defer dnsClient.Close()
// Setup output files
jsonPath, pcapPath := GenerateOutputPaths(r.config.OutputDir, upstream, r.config.DNSSEC, r.config.KeepAlive)
csvPath, pcapPath := GenerateOutputPaths(r.config.OutputDir, upstream, r.config.DNSSEC, r.config.KeepAlive)
keepAliveStr := ""
if r.config.KeepAlive {
@@ -83,7 +83,7 @@ func (r *MeasurementRunner) runMeasurement(upstream string, domains []string, qT
}
fmt.Printf(">>> Measuring %s (dnssec=%v%s) → %s\n", upstream, r.config.DNSSEC, keepAliveStr,
strings.TrimSuffix(strings.TrimSuffix(jsonPath, ".jsonl"), r.config.OutputDir+"/"))
strings.TrimSuffix(strings.TrimSuffix(csvPath, ".csv"), r.config.OutputDir+"/"))
// Setup packet capture
packetCapture, err := capture.NewPacketCapture(r.config.Interface, pcapPath)
@@ -93,7 +93,7 @@ func (r *MeasurementRunner) runMeasurement(upstream string, domains []string, qT
defer packetCapture.Close()
// Setup results writer
writer, err := results.NewMetricsWriter(jsonPath)
writer, err := results.NewMetricsWriter(csvPath)
if err != nil {
return err
}

View File

@@ -1,9 +1,10 @@
package results
import (
"encoding/json"
"encoding/csv"
"fmt"
"os"
"strconv"
"time"
)
@@ -23,29 +24,69 @@ type DNSMetric struct {
Error string `json:"error,omitempty"`
}
// Rest stays exactly the same
type MetricsWriter struct {
encoder *json.Encoder
writer *csv.Writer
file *os.File
}
func NewMetricsWriter(path string) (*MetricsWriter, error) {
file, err := os.Create(path)
if err != nil {
return nil, fmt.Errorf("create json output: %w", err)
return nil, fmt.Errorf("create csv output: %w", err)
}
writer := csv.NewWriter(file)
// Write CSV header
header := []string{
"domain", "query_type", "protocol", "dnssec", "keep_alive",
"dns_server", "timestamp", "duration_ns", "duration_ms",
"request_size_bytes", "response_size_bytes", "response_code", "error",
}
if err := writer.Write(header); err != nil {
file.Close()
return nil, fmt.Errorf("write csv header: %w", err)
}
writer.Flush()
return &MetricsWriter{
encoder: json.NewEncoder(file),
writer: writer,
file: file,
}, nil
}
func (mw *MetricsWriter) WriteMetric(metric DNSMetric) error {
return mw.encoder.Encode(metric)
record := []string{
metric.Domain,
metric.QueryType,
metric.Protocol,
strconv.FormatBool(metric.DNSSEC),
strconv.FormatBool(metric.KeepAlive),
metric.DNSServer,
metric.Timestamp.Format(time.RFC3339),
strconv.FormatInt(metric.Duration, 10),
strconv.FormatFloat(metric.DurationMs, 'f', 3, 64),
strconv.Itoa(metric.RequestSize),
strconv.Itoa(metric.ResponseSize),
metric.ResponseCode,
metric.Error,
}
err := mw.writer.Write(record)
if err != nil {
return err
}
mw.writer.Flush()
return mw.writer.Error()
}
func (mw *MetricsWriter) Close() error {
if mw.writer != nil {
mw.writer.Flush()
}
if mw.file != nil {
return mw.file.Close()
}

View File

@@ -8,7 +8,7 @@ import (
"time"
)
func GenerateOutputPaths(outputDir, upstream string, dnssec, keepAlive bool) (jsonPath, pcapPath string) {
func GenerateOutputPaths(outputDir, upstream string, dnssec, keepAlive bool) (csvPath, pcapPath string) {
proto := DetectProtocol(upstream)
serverName := ExtractServerName(upstream)
ts := time.Now().Format("20060102_1504")
@@ -18,7 +18,7 @@ func GenerateOutputPaths(outputDir, upstream string, dnssec, keepAlive bool) (js
base := fmt.Sprintf("%s_%s_dnssec_%s_keepalive_%s_%s",
proto, sanitize(serverName), dnssecStr, keepAliveStr, ts)
return filepath.Join(outputDir, base+".jsonl"),
return filepath.Join(outputDir, base+".csv"),
filepath.Join(outputDir, base+".pcap")
}