-
-
Notifications
You must be signed in to change notification settings - Fork 114
/
file.go
101 lines (86 loc) · 2.86 KB
/
file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package ffexporter
import (
"context"
"fmt"
"log"
"os"
"strings"
"sync"
"text/template"
"github.com/thomaspoignant/go-feature-flag/internal/exporter"
)
type File struct {
// Format is the output format you want in your exported file.
// Available format are JSON and CSV.
// Default: JSON
Format string
// OutputDir is the location of the directory where to store the exported files
// It should finish with a /
// Default: the current directory
OutputDir string
// Filename is the name of your output file
// You can use a templated config to define the name of your export files.
// Available replacement are {{ .Hostname}}, {{ .Timestamp}} and {{ .Format}}
// Default: "flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}"
Filename string
// CsvTemplate is used if your output format is CSV.
// This field will be ignored if you are using another format than CSV.
// You can decide which fields you want in your CSV line with a go-template syntax,
// please check internal/exporter/feature_event.go to see what are the fields available.
// Default:
// {{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}}\n
CsvTemplate string
csvTemplate *template.Template
filenameTemplate *template.Template
initTemplates sync.Once
}
// Export is saving a collection of events in a file.
func (f *File) Export(ctx context.Context, logger *log.Logger, featureEvents []exporter.FeatureEvent) error {
// Parse the template only once
f.initTemplates.Do(func() {
f.csvTemplate = parseTemplate("csvFormat", f.CsvTemplate, DefaultCsvTemplate)
f.filenameTemplate = parseTemplate("filenameFormat", f.Filename, DefaultFilenameTemplate)
})
// Default format for the output
if f.Format == "" {
f.Format = "json"
}
// Get the filename
filename, err := computeFilename(f.filenameTemplate, f.Format)
if err != nil {
return err
}
filePath := f.OutputDir + "/" + filename
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
for _, event := range featureEvents {
var line []byte
var err error
// Convert the line in the right format
switch strings.ToLower(f.Format) {
case "csv":
line, err = formatEventInCSV(f.csvTemplate, event)
case "json":
line, err = formatEventInJSON(event)
default:
line, err = formatEventInJSON(event)
}
// Handle error and write line into the file
if err != nil {
return fmt.Errorf("impossible to format the event in %s: %v", f.Format, err)
}
_, errWrite := file.Write(line)
if errWrite != nil {
return fmt.Errorf("error while writing the export file: %v", err)
}
}
return nil
}
// IsBulk return false if we should directly send the data as soon as it is produce
// and true if we collect the data to send them in bulk.
func (f *File) IsBulk() bool {
return true
}