Skip to content
This repository was archived by the owner on Dec 3, 2024. It is now read-only.

Commit 7267663

Browse files
authored
Merge pull request #8 from daisy1754/feature/prefix
Add config to specify custom prefix of metrics
2 parents 202ca3d + ae13761 commit 7267663

File tree

2 files changed

+109
-3
lines changed

2 files changed

+109
-3
lines changed

stackdriver.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type Sink struct {
5252

5353
bucketer BucketFn
5454
extractor ExtractLabelsFn
55+
prefix string
5556
taskInfo *taskInfo
5657

5758
mu sync.Mutex
@@ -69,6 +70,9 @@ type Config struct {
6970
// variable parameters within a metric name.
7071
// Optional. Defaults to DefaultLabelExtractor.
7172
LabelExtractor ExtractLabelsFn
73+
// Prefix of the metrics recorded. Defaults to "go-metrics/" so your metric "foo" will be recorded as
74+
// "custom.googleapis.com/go-metrics/foo".
75+
Prefix *string
7276
// The bucketer is used to determine histogram bucket boundaries
7377
// for the sampled metrics. This will execute before the LabelExtractor.
7478
// Optional. Defaults to DefaultBucketer.
@@ -147,6 +151,7 @@ func NewSink(client *monitoring.MetricClient, config *Config) *Sink {
147151
s := &Sink{
148152
client: client,
149153
extractor: config.LabelExtractor,
154+
prefix: "go-metrics/",
150155
bucketer: config.Bucketer,
151156
interval: config.ReportingInterval,
152157
taskInfo: &taskInfo{
@@ -159,6 +164,13 @@ func NewSink(client *monitoring.MetricClient, config *Config) *Sink {
159164
debugLogs: config.DebugLogs,
160165
}
161166

167+
if config.Prefix != nil {
168+
if isValidMetricsPrefix(*config.Prefix) {
169+
s.prefix = *config.Prefix
170+
} else {
171+
log.Printf("%s is not valid string to be used as metrics name, using default value 'go-metrics/'", *config.Prefix)
172+
}
173+
}
162174
// apply defaults if not configured explicitly
163175
if s.extractor == nil {
164176
s.extractor = DefaultLabelExtractor
@@ -207,6 +219,12 @@ func NewSink(client *monitoring.MetricClient, config *Config) *Sink {
207219
return s
208220
}
209221

222+
func isValidMetricsPrefix(s string) bool {
223+
// start with alphanumeric, can contain underscore in path (expect first char), slash is used to separate path.
224+
match, err := regexp.MatchString("^(?:[a-z0-9](?:[a-z0-9_]*)/?)*$", s)
225+
return err == nil && match
226+
}
227+
210228
func (s *Sink) flushMetrics(ctx context.Context) {
211229
if s.interval == 0*time.Second {
212230
return
@@ -297,7 +315,7 @@ func (s *Sink) report(ctx context.Context) {
297315
}
298316
ts = append(ts, &monitoringpb.TimeSeries{
299317
Metric: &metricpb.Metric{
300-
Type: path.Join("custom.googleapis.com", "go-metrics", name),
318+
Type: fmt.Sprintf("custom.googleapis.com/%s%s", s.prefix, name),
301319
Labels: labels,
302320
},
303321
MetricKind: metric.MetricDescriptor_GAUGE,
@@ -330,7 +348,7 @@ func (s *Sink) report(ctx context.Context) {
330348
}
331349
ts = append(ts, &monitoringpb.TimeSeries{
332350
Metric: &metricpb.Metric{
333-
Type: path.Join("custom.googleapis.com", "go-metrics", name),
351+
Type: fmt.Sprintf("custom.googleapis.com/%s%s", s.prefix, name),
334352
Labels: labels,
335353
},
336354
MetricKind: metric.MetricDescriptor_GAUGE,
@@ -370,7 +388,7 @@ func (s *Sink) report(ctx context.Context) {
370388

371389
ts = append(ts, &monitoringpb.TimeSeries{
372390
Metric: &metricpb.Metric{
373-
Type: path.Join("custom.googleapis.com", "go-metrics", name),
391+
Type: fmt.Sprintf("custom.googleapis.com/%s%s", s.prefix, name),
374392
Labels: labels,
375393
},
376394
MetricKind: metric.MetricDescriptor_CUMULATIVE,

stackdriver_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,93 @@ func BenchmarkReport10(b *testing.B) { benchmarkCopy(10, 10, 10, b) }
9191
func BenchmarkReport50(b *testing.B) { benchmarkCopy(50, 50, 50, b) }
9292
func BenchmarkReport100(b *testing.B) { benchmarkCopy(100, 100, 100, b) }
9393

94+
func sPtr(s string) *string {
95+
return &s
96+
}
97+
98+
func TestNewSinkSetCustomPrefix(t *testing.T) {
99+
tests := []struct {
100+
name string
101+
configPrefix *string
102+
expectedPrefix string
103+
}{
104+
{
105+
name: "default to go-metrics/",
106+
expectedPrefix: "go-metrics/",
107+
},
108+
{
109+
name: "set custom",
110+
configPrefix: sPtr("cuSt0m_metrics"),
111+
expectedPrefix: "cuSt0m_metrics",
112+
},
113+
{
114+
name: "default to go-metrics/ when given prefix is invalid",
115+
configPrefix: sPtr("___"),
116+
expectedPrefix: "go-metrics/",
117+
},
118+
}
119+
for _, tc := range tests {
120+
t.Run(tc.name, func(t *testing.T) {
121+
ss := NewSink(nil, &Config{Prefix: tc.configPrefix})
122+
123+
if ss.prefix != tc.expectedPrefix {
124+
t.Errorf("prefix should be initalized as '" + tc.expectedPrefix + "' but got " + ss.prefix)
125+
}
126+
})
127+
}
128+
}
129+
130+
func TestIsValidMetricsPrefix(t *testing.T) {
131+
tests := []struct {
132+
prefix string
133+
expectedValid bool
134+
}{
135+
{
136+
prefix: "",
137+
expectedValid: true,
138+
},
139+
{
140+
prefix: "a",
141+
expectedValid: true,
142+
},
143+
{
144+
prefix: "abc/bef/",
145+
expectedValid: true,
146+
},
147+
{
148+
prefix: "aa_",
149+
expectedValid: true,
150+
},
151+
{
152+
prefix: "///",
153+
expectedValid: false,
154+
},
155+
{
156+
prefix: "!",
157+
expectedValid: false,
158+
},
159+
{
160+
prefix: "_aa",
161+
expectedValid: false,
162+
},
163+
{
164+
prefix: "日本語",
165+
expectedValid: false,
166+
},
167+
}
168+
for _, tc := range tests {
169+
t.Run(tc.prefix, func(t *testing.T) {
170+
if isValidMetricsPrefix(tc.prefix) != tc.expectedValid {
171+
if tc.expectedValid {
172+
t.Errorf("expected %s to be valid", tc.prefix)
173+
} else {
174+
t.Errorf("expected %s to be invalid", tc.prefix)
175+
}
176+
}
177+
})
178+
}
179+
}
180+
94181
func TestSample(t *testing.T) {
95182
ss := newTestSink(0*time.Second, nil)
96183

@@ -943,6 +1030,7 @@ func newTestSink(interval time.Duration, client *monitoring.MetricClient) *Sink
9431030
s.taskInfo = &taskInfo{
9441031
ProjectID: "foo",
9451032
}
1033+
s.prefix = "go-metrics/"
9461034
s.interval = interval
9471035
s.bucketer = DefaultBucketer
9481036
s.extractor = DefaultLabelExtractor

0 commit comments

Comments
 (0)