Skip to content

Commit 18907db

Browse files
authored
Implement prometheus-collector-bridge (#477)
* Implement prometheus-collector-bridge Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * lint Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Add license headers to otelcollector files Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Made-with: Cursor * fix imports Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Deduplicate utility functions Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Update collector-bridge dependency Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com>
1 parent 4bf1d8e commit 18907db

14 files changed

Lines changed: 1113 additions & 65 deletions

collectors/monitoring_collector.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ type MetricFilter struct {
3636
FilterQuery string
3737
}
3838

39+
func ParseMetricExtraFilters(raw []string) []MetricFilter {
40+
out := make([]MetricFilter, 0, len(raw))
41+
for _, entry := range raw {
42+
prefix, filter := utils.SplitExtraFilter(entry, ":")
43+
if prefix == "" {
44+
continue
45+
}
46+
out = append(out, MetricFilter{
47+
TargetedMetricPrefix: strings.ToLower(prefix),
48+
FilterQuery: filter,
49+
})
50+
}
51+
return out
52+
}
53+
3954
type MonitoringCollector struct {
4055
projectID string
4156
metricsTypePrefixes []string

collectors/monitoring_collector_test.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313

1414
package collectors
1515

16-
import "testing"
16+
import (
17+
"reflect"
18+
"testing"
19+
)
1720

1821
func TestIsGoogleMetric(t *testing.T) {
1922
good := []string{
@@ -37,3 +40,27 @@ func TestIsGoogleMetric(t *testing.T) {
3740
}
3841
}
3942
}
43+
44+
func TestParseMetricExtraFilters(t *testing.T) {
45+
input := []string{
46+
"pubsub.googleapis.com/subscription:resource.labels.subscription_id=monitoring.regex.full_match(\"my-subs-prefix.*\")",
47+
"missing-separator",
48+
"compute.googleapis.com/instance:metric.labels.instance_name=\"example:vm\"",
49+
}
50+
51+
got := ParseMetricExtraFilters(input)
52+
want := []MetricFilter{
53+
{
54+
TargetedMetricPrefix: "pubsub.googleapis.com/subscription",
55+
FilterQuery: "resource.labels.subscription_id=monitoring.regex.full_match(\"my-subs-prefix.*\")",
56+
},
57+
{
58+
TargetedMetricPrefix: "compute.googleapis.com/instance",
59+
FilterQuery: "metric.labels.instance_name=\"example:vm\"",
60+
},
61+
}
62+
63+
if !reflect.DeepEqual(got, want) {
64+
t.Fatalf("ParseMetricExtraFilters() = %#v, want %#v", got, want)
65+
}
66+
}

otelcollector/config.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2020 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package otelcollector
15+
16+
import (
17+
"fmt"
18+
"net/http"
19+
"time"
20+
21+
prombridge "github.com/ArthurSens/prometheus-collector-bridge"
22+
)
23+
24+
// Config maps stackdriver_exporter runtime settings into exporter_config.
25+
type Config struct {
26+
ProjectIDs []string `mapstructure:"project_ids"`
27+
ProjectsFilter string `mapstructure:"projects_filter"`
28+
UniverseDomain string `mapstructure:"universe_domain"`
29+
MaxRetries int `mapstructure:"max_retries"`
30+
HTTPTimeout string `mapstructure:"http_timeout"`
31+
MaxBackoff string `mapstructure:"max_backoff"`
32+
BackoffJitter string `mapstructure:"backoff_jitter"`
33+
RetryStatuses []int `mapstructure:"retry_statuses"`
34+
MetricsPrefixes []string `mapstructure:"metrics_prefixes"`
35+
MetricsInterval string `mapstructure:"metrics_interval"`
36+
MetricsOffset string `mapstructure:"metrics_offset"`
37+
MetricsIngest bool `mapstructure:"metrics_ingest_delay"`
38+
FillMissing bool `mapstructure:"fill_missing_labels"`
39+
DropDelegated bool `mapstructure:"drop_delegated_projects"`
40+
Filters []string `mapstructure:"filters"`
41+
AggregateDeltas bool `mapstructure:"aggregate_deltas"`
42+
DeltasTTL string `mapstructure:"aggregate_deltas_ttl"`
43+
DescriptorTTL string `mapstructure:"descriptor_cache_ttl"`
44+
DescriptorGoogleOnly bool `mapstructure:"descriptor_cache_only_google"`
45+
}
46+
47+
var _ prombridge.Config = (*Config)(nil)
48+
49+
func defaultConfig() *Config {
50+
return &Config{
51+
UniverseDomain: "googleapis.com",
52+
MaxRetries: 0,
53+
HTTPTimeout: "10s",
54+
MaxBackoff: "5s",
55+
BackoffJitter: "1s",
56+
RetryStatuses: []int{503},
57+
MetricsInterval: "5m",
58+
MetricsOffset: "0s",
59+
MetricsIngest: false,
60+
FillMissing: true,
61+
DropDelegated: false,
62+
AggregateDeltas: false,
63+
DeltasTTL: "30m",
64+
DescriptorTTL: "0s",
65+
DescriptorGoogleOnly: true,
66+
}
67+
}
68+
69+
func defaultComponentDefaults() map[string]interface{} {
70+
cfg := defaultConfig()
71+
return map[string]interface{}{
72+
"max_retries": cfg.MaxRetries,
73+
"http_timeout": cfg.HTTPTimeout,
74+
"max_backoff": cfg.MaxBackoff,
75+
"backoff_jitter": cfg.BackoffJitter,
76+
"retry_statuses": cfg.RetryStatuses,
77+
"universe_domain": cfg.UniverseDomain,
78+
"metrics_interval": cfg.MetricsInterval,
79+
"metrics_offset": cfg.MetricsOffset,
80+
"metrics_ingest_delay": cfg.MetricsIngest,
81+
"fill_missing_labels": cfg.FillMissing,
82+
"drop_delegated_projects": cfg.DropDelegated,
83+
"aggregate_deltas": cfg.AggregateDeltas,
84+
"aggregate_deltas_ttl": cfg.DeltasTTL,
85+
"descriptor_cache_ttl": cfg.DescriptorTTL,
86+
"descriptor_cache_only_google": cfg.DescriptorGoogleOnly,
87+
}
88+
}
89+
90+
func (c *Config) Validate() error {
91+
if len(c.MetricsPrefixes) == 0 {
92+
return fmt.Errorf("metrics_prefixes must have at least one entry")
93+
}
94+
95+
_, err := c.parsedDurations()
96+
if err != nil {
97+
return err
98+
}
99+
100+
for _, code := range c.RetryStatuses {
101+
if code < http.StatusContinue || code > 599 {
102+
return fmt.Errorf("retry status %d is not a valid HTTP status code", code)
103+
}
104+
}
105+
106+
return nil
107+
}
108+
109+
type parsedConfig struct {
110+
HTTPTimeout time.Duration
111+
MaxBackoff time.Duration
112+
BackoffJitter time.Duration
113+
MetricsInterval time.Duration
114+
MetricsOffset time.Duration
115+
DeltasTTL time.Duration
116+
DescriptorTTL time.Duration
117+
}
118+
119+
func (c *Config) parsedDurations() (parsedConfig, error) {
120+
parse := func(name, raw string) (time.Duration, error) {
121+
d, err := time.ParseDuration(raw)
122+
if err != nil {
123+
return 0, fmt.Errorf("%s: invalid duration %q: %w", name, raw, err)
124+
}
125+
return d, nil
126+
}
127+
128+
httpTimeout, err := parse("http_timeout", c.HTTPTimeout)
129+
if err != nil {
130+
return parsedConfig{}, err
131+
}
132+
maxBackoff, err := parse("max_backoff", c.MaxBackoff)
133+
if err != nil {
134+
return parsedConfig{}, err
135+
}
136+
backoffJitter, err := parse("backoff_jitter", c.BackoffJitter)
137+
if err != nil {
138+
return parsedConfig{}, err
139+
}
140+
metricsInterval, err := parse("metrics_interval", c.MetricsInterval)
141+
if err != nil {
142+
return parsedConfig{}, err
143+
}
144+
metricsOffset, err := parse("metrics_offset", c.MetricsOffset)
145+
if err != nil {
146+
return parsedConfig{}, err
147+
}
148+
deltasTTL, err := parse("aggregate_deltas_ttl", c.DeltasTTL)
149+
if err != nil {
150+
return parsedConfig{}, err
151+
}
152+
descriptorTTL, err := parse("descriptor_cache_ttl", c.DescriptorTTL)
153+
if err != nil {
154+
return parsedConfig{}, err
155+
}
156+
157+
return parsedConfig{
158+
HTTPTimeout: httpTimeout,
159+
MaxBackoff: maxBackoff,
160+
BackoffJitter: backoffJitter,
161+
MetricsInterval: metricsInterval,
162+
MetricsOffset: metricsOffset,
163+
DeltasTTL: deltasTTL,
164+
DescriptorTTL: descriptorTTL,
165+
}, nil
166+
}
167+
168+
type configUnmarshaler struct{}
169+
170+
func (configUnmarshaler) GetConfigStruct() prombridge.Config {
171+
return defaultConfig()
172+
}

0 commit comments

Comments
 (0)