Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions .github/workflows/pr-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 #v3.4.0
with:
go-version: 1.18.x
go-version: 1.19.x
- name: Restore Go cache
uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7 #v3.0.11
with:
Expand All @@ -32,18 +32,26 @@ jobs:
with:
version: v0.11.1
image: kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
- name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main
- name: Setup envtest
uses: fluxcd/pkg/actions/envtest@main
with:
version: "1.21.2"
- name: Setup Helm
uses: fluxcd/pkg/actions/helm@main
- name: Setup kustomize
shell: bash
run: |
curl --silent --location --remote-name "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.5.7/kustomize_v4.5.7_linux_amd64.tar.gz"
tar xvzf kustomize_v4.5.7_linux_amd64.tar.gz
sudo mv kustomize /usr/local/bin/kustomize
rm -rfv *.tar.gz
kustomize version
- name: Install Helm
uses: azure/setup-helm@f382f75448129b3be48f8121b9857be18d815a82 #v3.4
- name: fmt
run: make fmt
- name: vet
run: make vet
- name: lint
run: make lint
- name: Run tests
run: make test
- name: Send go coverage report
uses: shogo82148/actions-goveralls@v1
uses: shogo82148/actions-goveralls@31ee804b8576ae49f6dc3caa22591bc5080e7920 #v1.6.0
with:
path-to-profile: coverage.out
- name: Check if working tree is dirty
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b #v3
- uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 #v3.4.0
with:
go-version: '1.18'
go-version: '1.19'
- name: Docker Login
uses: docker/login-action@v2
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a #v2.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -35,5 +35,4 @@ jobs:
version: latest
args: release --rm-dist --skip-validate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 changes: 29 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ integrations := $(shell $(GO) list ./... | grep cmd)
PREFIX ?= $(shell pwd)
BIN_DIR ?= $(shell pwd)

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

all: deps vet fmt test build
all: deps vet fmt lint test build

style:
@echo ">> checking code style"
Expand All @@ -39,6 +45,15 @@ integrationtest:
@echo ">> running integration tests"
@$(GO) test -short -race -v $(integrations)

GOLANGCI_LINT = $(GOBIN)/golangci-lint
.PHONY: golangci-lint
golangci-lint: ## Download golint locally if necessary
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/[email protected])

.PHONY: lint
lint: golangci-lint ## Run golangci-lint against code
$(GOLANGCI_LINT) run ./...

deps:
@echo ">> install dependencies"
@$(GO) mod download
Expand Down Expand Up @@ -86,3 +101,16 @@ undeploy-test: ## Undeploy exporter from the K8s cluster specified in ~/.kube/co
$(KUSTOMIZE) build config/test | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: all style fmt build test vet

# go-install-tool will 'go install' any package $2 and install it to $1
define go-install-tool
@[ -f $(1) ] || { \
set -e ;\
TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
env -i bash -c "GOBIN=$(GOBIN) PATH=$(PATH) GOPATH=$(shell go env GOPATH) GOCACHE=$(shell go env GOCACHE) go install $(2)" ;\
rm -rf $$TMP_DIR ;\
}
endef
118 changes: 84 additions & 34 deletions cmd/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ func executeIntegrationTest(t *testing.T, test integrationTest) {
container, err := setupMongoDBContainer(context.TODO(), test.mongodbImage)
assert.NoError(t, err)
opts := options.Client().ApplyURI(container.URI)
defer container.Terminate(context.TODO())

defer func() {
assert.NoError(t, container.Terminate(context.TODO()))
}()

client, err := mongo.Connect(context.TODO(), opts)
assert.NoError(t, err)
Expand All @@ -92,7 +95,10 @@ func executeIntegrationTest(t *testing.T, test integrationTest) {
b := bytes.NewBufferString("")
rootCmd.SetOut(b)
rootCmd.SetArgs(args)
go rootCmd.Execute()

go func() {
assert.NoError(t, rootCmd.Execute())
}()

//binding is blocking, do this async but wait 200ms for tcp port to be open
time.Sleep(200 * time.Millisecond)
Expand All @@ -118,7 +124,7 @@ func executeIntegrationTest(t *testing.T, test integrationTest) {
assert.Len(t, test.expectedMetrics, found)

//tear down http server and unregister collector
srv.Shutdown(context.TODO())
assert.NoError(t, srv.Shutdown(context.TODO()))
prometheus.Unregister(promCollector)
}

Expand Down Expand Up @@ -156,40 +162,84 @@ func setupMongoDBContainer(ctx context.Context, image string) (*mongodbContainer
return &mongodbContainer{Container: container, URI: uri}, nil
}

type testRecord struct {
document bson.M
database string
collection string
}

func setupTestData(t *testing.T, client *mongo.Client) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

_, err := client.Database("mydb").Collection("objects").InsertOne(ctx, bson.M{
"foo": "bar",
})
assert.NoError(t, err)
testData := []testRecord{
{
database: "mydb",
collection: "objects",
document: bson.M{
"foo": "bar",
},
},
{
database: "mydb",
collection: "objects",
document: bson.M{
"foo": "foo",
},
},
{
database: "mydb",
collection: "queue",
document: bson.M{
"class": "foobar",
"status": 1,
},
},
{
database: "mydb",
collection: "queue",
document: bson.M{
"class": "foobar",
"status": 1,
},
},
{
database: "mydb",
collection: "queue",
document: bson.M{
"class": "bar",
"status": 2,
},
},
{
database: "mydb",
collection: "events",
document: bson.M{
"type": "bar",
"created": time.Now(),
},
},
{
database: "mydb",
collection: "events",
document: bson.M{
"type": "bar",
"created": time.Now(),
},
},
{
database: "mydb",
collection: "events",
document: bson.M{
"type": "foo",
"created": time.Now(),
},
},
}

for _, record := range testData {
_, err := client.Database(record.database).Collection(record.collection).InsertOne(ctx, record.document)
assert.NoError(t, err)
}

client.Database("mydb").Collection("objects").InsertOne(ctx, bson.M{
"foo": "foo",
})
client.Database("mydb").Collection("queue").InsertOne(ctx, bson.M{
"class": "foobar",
"status": 1,
})
client.Database("mydb").Collection("queue").InsertOne(ctx, bson.M{
"class": "foobar",
"status": 1,
})
client.Database("mydb").Collection("queue").InsertOne(ctx, bson.M{
"class": "bar",
"status": 2,
})
client.Database("mydb").Collection("events").InsertOne(ctx, bson.M{
"type": "bar",
"created": time.Now(),
})
client.Database("mydb").Collection("events").InsertOne(ctx, bson.M{
"type": "bar",
"created": time.Now(),
})
client.Database("mydb").Collection("events").InsertOne(ctx, bson.M{
"type": "foo",
"created": time.Now(),
})
}
28 changes: 14 additions & 14 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var (
//reg := prometheus.NewRegistry()
prometheus.MustRegister(c)
promCollector = c
c.StartCacheInvalidator()
_ = c.StartCacheInvalidator()
srv = buildHTTPServer(prometheus.DefaultGatherer, conf)
err = srv.ListenAndServe()

Expand Down Expand Up @@ -114,7 +114,7 @@ func buildHTTPServer(reg prometheus.Gatherer, conf config.Config) *http.Server {
}

func main() {
rootCmd.Execute()
_ = rootCmd.Execute()
}

func init() {
Expand All @@ -126,18 +126,18 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&bind, "bind", "b", config.DefaultBindAddr, "Address to bind http server (default is :9412)")
rootCmd.PersistentFlags().StringVarP(&metricsPath, "path", "p", config.DefaultMetricsPath, "Metric path (default is /metrics)")
rootCmd.PersistentFlags().DurationVarP(&queryTimeout, "query-timeout", "t", config.DefaultQueryTimeout, "Timeout for MongoDB queries")
viper.BindPFlag("log.level", rootCmd.PersistentFlags().Lookup("log-level"))
viper.BindPFlag("log.encoding", rootCmd.PersistentFlags().Lookup("log-encoding"))
viper.BindPFlag("bind", rootCmd.PersistentFlags().Lookup("bind"))
viper.BindPFlag("metricsPath", rootCmd.PersistentFlags().Lookup("path"))
viper.BindPFlag("mongodb.uri", rootCmd.PersistentFlags().Lookup("uri"))
viper.BindPFlag("mongodb.queryTimeout", rootCmd.PersistentFlags().Lookup("query-timeout"))
viper.BindEnv("mongodb.uri", "MDBEXPORTER_MONGODB_URI")
viper.BindEnv("global.queryTimeout", "MDBEXPORTER_MONGODB_QUERY_TIMEOUT")
viper.BindEnv("log.level", "MDBEXPORTER_LOG_LEVEL")
viper.BindEnv("log.encoding", "MDBEXPORTER_LOG_ENCODING")
viper.BindEnv("bind", "MDBEXPORTER_BIND")
viper.BindEnv("metricsPath", "MDBEXPORTER_METRICSPATH")
_ = viper.BindPFlag("log.level", rootCmd.PersistentFlags().Lookup("log-level"))
_ = viper.BindPFlag("log.encoding", rootCmd.PersistentFlags().Lookup("log-encoding"))
_ = viper.BindPFlag("bind", rootCmd.PersistentFlags().Lookup("bind"))
_ = viper.BindPFlag("metricsPath", rootCmd.PersistentFlags().Lookup("path"))
_ = viper.BindPFlag("mongodb.uri", rootCmd.PersistentFlags().Lookup("uri"))
_ = viper.BindPFlag("mongodb.queryTimeout", rootCmd.PersistentFlags().Lookup("query-timeout"))
_ = viper.BindEnv("mongodb.uri", "MDBEXPORTER_MONGODB_URI")
_ = viper.BindEnv("global.queryTimeout", "MDBEXPORTER_MONGODB_QUERY_TIMEOUT")
_ = viper.BindEnv("log.level", "MDBEXPORTER_LOG_LEVEL")
_ = viper.BindEnv("log.encoding", "MDBEXPORTER_LOG_ENCODING")
_ = viper.BindEnv("bind", "MDBEXPORTER_BIND")
_ = viper.BindEnv("metricsPath", "MDBEXPORTER_METRICSPATH")
}

func initConfig() {
Expand Down
19 changes: 8 additions & 11 deletions collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ type Collector struct {
servers []*server
logger Logger
config *Config
metrics []*Metric
aggregations []*Aggregation
counter *prometheus.CounterVec
cache map[string]*cacheEntry
Expand Down Expand Up @@ -59,7 +58,6 @@ type Aggregation struct {
Pipeline string
Metrics []*Metric
pipeline bson.A
validUntil time.Time
}

// A metric defines how a certain value is exported from a MongoDB aggregation
Expand Down Expand Up @@ -91,7 +89,7 @@ const (
ModePull = "pull"
//Push mode (Uses changestream which is only supported with MongoDB >= 3.6)
ModePush = "push"
//Metric generated succesfully
//Metric generated successfully
ResultSuccess = "SUCCESS"
//Metric value could not been determined
ResultError = "ERROR"
Expand Down Expand Up @@ -445,18 +443,17 @@ func createMetric(metric *Metric, result AggregationResult) (prometheus.Metric,

func (metric *Metric) getValue(result AggregationResult) (float64, error) {
if val, ok := result[metric.Value]; ok {
switch val.(type) {
switch v := val.(type) {
case float32:
value := float64(val.(float32))
value := float64(v)
return value, nil
case float64:
value := val.(float64)
return value, nil
return v, nil
case int32:
value := float64(val.(int32))
value := float64(v)
return value, nil
case int64:
value := float64(val.(int64))
value := float64(v)
return value, nil
default:
return 0, fmt.Errorf("provided value taken from the aggregation result has to be a number, type %T given", val)
Expand All @@ -471,9 +468,9 @@ func (metric *Metric) getLabels(result AggregationResult) ([]string, error) {

for _, label := range metric.Labels {
if val, ok := result[label]; ok {
switch val.(type) {
switch v := val.(type) {
case string:
labels = append(labels, val.(string))
labels = append(labels, v)
default:
return labels, fmt.Errorf("provided label value taken from the aggregation result has to be a string, type %T given", val)
}
Expand Down
8 changes: 4 additions & 4 deletions collector/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func TestInitializeMetrics(t *testing.T) {
aggregation: &Aggregation{
Metrics: []*Metric{
&Metric{
Name: "simple_gauge_value_not_found_overriden",
Name: "simple_gauge_value_not_found_overridden",
Type: "gauge",
Help: "overridden",
OverrideEmpty: true,
Expand All @@ -167,9 +167,9 @@ func TestInitializeMetrics(t *testing.T) {
Pipeline: "[{\"$match\":{\"foo\":\"bar\"}}]",
},
expected: `
# HELP simple_gauge_value_not_found_overriden overridden
# TYPE simple_gauge_value_not_found_overriden gauge
simple_gauge_value_not_found_overriden 12
# HELP simple_gauge_value_not_found_overridden overridden
# TYPE simple_gauge_value_not_found_overridden gauge
simple_gauge_value_not_found_overridden 12
`,
},
aggregationTest{
Expand Down
Loading