Add loading configuration from file.

This commit is contained in:
Julius Volz 2013-07-26 03:04:53 +02:00 committed by Julius Volz
parent 3f9cc9e3e3
commit 24ac73af5d
11 changed files with 357 additions and 15 deletions

17
config/Makefile Normal file
View File

@ -0,0 +1,17 @@
# Copyright 2013 Prometheus Team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
all: generated/config.pb.go
generated/config.pb.go: config.proto
protoc --go_out=generated/ config.proto

58
config/config.go Normal file
View File

@ -0,0 +1,58 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"time"
"code.google.com/p/goprotobuf/proto"
pb "github.com/prometheus/alert_manager/config/generated"
"github.com/prometheus/alert_manager/manager"
)
// Config encapsulates the configuration of an Alert Manager instance. It wraps
// the raw configuration protocol buffer to be able to add custom methods to
// it.
type Config struct {
// The protobuf containing the actual configuration values.
pb.AlertManagerConfig
}
// String returns an ASCII serialization of the loaded configuration protobuf.
func (c Config) String() string {
return proto.MarshalTextString(&c.AlertManagerConfig)
}
// Validate checks an entire parsed Config for the validity of its fields.
func (c Config) Validate() error {
// BUG: Nothing to do here for now.
return nil
}
// Rules returns all the AggregationRules in a Config object.
func (c Config) AggregationRules() manager.AggregationRules {
rules := make(manager.AggregationRules, 0, len(c.AggregationRule))
for _, r := range c.AggregationRule {
filters := make(manager.Filters, 0, len(r.Filter))
for _, filter := range r.Filter {
filters = append(filters, manager.NewFilter(filter.GetNameRe(), filter.GetValueRe()))
}
rules = append(rules, &manager.AggregationRule{
Filters: filters,
RepeatRate: time.Duration(r.GetRepeatRate()) * time.Second,
})
}
return rules
}

31
config/config.proto Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.prometheus.alert_manager;
// A regex-based label filter used in aggregations.
message Filter {
// The regex matching the label name.
required string name_re = 1;
// The regex matching the label value.
required string value_re = 2;
}
message AggregationRule {
repeated Filter filter = 1;
optional int32 repeat_rate = 2 [default = 7200];
}
message AlertManagerConfig {
repeated AggregationRule aggregation_rule = 1;
}

54
config/config_test.go Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"path"
"strings"
"testing"
)
var fixturesPath = "fixtures"
var configTests = []struct {
inputFile string
shouldFail bool
errContains string
}{
{
inputFile: "empty.conf.input",
}, {
inputFile: "sample.conf.input",
}, {
inputFile: "invalid_proto_format.conf.input",
shouldFail: true,
errContains: "unknown field name",
},
}
func TestConfigs(t *testing.T) {
for i, configTest := range configTests {
_, err := LoadFromFile(path.Join(fixturesPath, configTest.inputFile))
if err != nil {
if !configTest.shouldFail {
t.Fatalf("%d. Error parsing config %v: %v", i, configTest.inputFile, err)
} else {
if !strings.Contains(err.Error(), configTest.errContains) {
t.Fatalf("%d. Expected error containing '%v', got: %v", i, configTest.errContains, err)
}
}
}
}
}

View File

View File

@ -0,0 +1,18 @@
aggregation_rule {
filter {
label_re: "service" // Unknown protobuf field name.
value_re: "discovery"
}
filter {
name_re: "zone"
value_re: "aa"
}
repeat_rate: 3600
}
aggregation_rule {
filter {
name_re: "service"
value_re: "test"
}
}

View File

@ -0,0 +1,18 @@
aggregation_rule {
filter {
name_re: "service"
value_re: "discovery"
}
filter {
name_re: "zone"
value_re: "aa"
}
repeat_rate: 3600
}
aggregation_rule {
filter {
name_re: "service"
value_re: "test"
}
}

View File

@ -0,0 +1,83 @@
// Code generated by protoc-gen-go.
// source: config.proto
// DO NOT EDIT!
package io_prometheus_alert_manager
import proto "code.google.com/p/goprotobuf/proto"
import json "encoding/json"
import math "math"
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
var _ = proto.Marshal
var _ = &json.SyntaxError{}
var _ = math.Inf
type Filter struct {
NameRe *string `protobuf:"bytes,1,req,name=name_re" json:"name_re,omitempty"`
ValueRe *string `protobuf:"bytes,2,req,name=value_re" json:"value_re,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Filter) Reset() { *m = Filter{} }
func (m *Filter) String() string { return proto.CompactTextString(m) }
func (*Filter) ProtoMessage() {}
func (m *Filter) GetNameRe() string {
if m != nil && m.NameRe != nil {
return *m.NameRe
}
return ""
}
func (m *Filter) GetValueRe() string {
if m != nil && m.ValueRe != nil {
return *m.ValueRe
}
return ""
}
type AggregationRule struct {
Filter []*Filter `protobuf:"bytes,1,rep,name=filter" json:"filter,omitempty"`
RepeatRate *int32 `protobuf:"varint,2,opt,name=repeat_rate,def=7200" json:"repeat_rate,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *AggregationRule) Reset() { *m = AggregationRule{} }
func (m *AggregationRule) String() string { return proto.CompactTextString(m) }
func (*AggregationRule) ProtoMessage() {}
const Default_AggregationRule_RepeatRate int32 = 7200
func (m *AggregationRule) GetFilter() []*Filter {
if m != nil {
return m.Filter
}
return nil
}
func (m *AggregationRule) GetRepeatRate() int32 {
if m != nil && m.RepeatRate != nil {
return *m.RepeatRate
}
return Default_AggregationRule_RepeatRate
}
type AlertManagerConfig struct {
AggregationRule []*AggregationRule `protobuf:"bytes,1,rep,name=aggregation_rule" json:"aggregation_rule,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *AlertManagerConfig) Reset() { *m = AlertManagerConfig{} }
func (m *AlertManagerConfig) String() string { return proto.CompactTextString(m) }
func (*AlertManagerConfig) ProtoMessage() {}
func (m *AlertManagerConfig) GetAggregationRule() []*AggregationRule {
if m != nil {
return m.AggregationRule
}
return nil
}
func init() {
}

42
config/load.go Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"code.google.com/p/goprotobuf/proto"
pb "github.com/prometheus/alert_manager/config/generated"
"io/ioutil"
)
func LoadFromString(configStr string) (Config, error) {
configProto := pb.AlertManagerConfig{}
if err := proto.UnmarshalText(configStr, &configProto); err != nil {
return Config{}, err
}
config := Config{configProto}
err := config.Validate()
return config, err
}
func LoadFromFile(fileName string) (Config, error) {
configStr, err := ioutil.ReadFile(fileName)
if err != nil {
return Config{}, err
}
return LoadFromString(string(configStr))
}

25
config/load_test.go Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"testing"
)
func TestLoadFromFile(t *testing.T) {
_, err := LoadFromFile("file-does-not-exist.conf")
if err == nil {
t.Error(err)
}
}

26
main.go
View File

@ -17,14 +17,24 @@ import (
"flag"
"log"
"github.com/prometheus/alert_manager/config"
"github.com/prometheus/alert_manager/manager"
"github.com/prometheus/alert_manager/web"
"github.com/prometheus/alert_manager/web/api"
)
var (
configFile = flag.String("configFile", "alertmanager.conf", "Alert Manager configuration file name.")
)
func main() {
flag.Parse()
conf, err := config.LoadFromFile(*configFile)
if err != nil {
log.Fatalf("Error loading configuration from %s: %v", *configFile, err)
}
suppressor := manager.NewSuppressor()
defer suppressor.Close()
@ -50,21 +60,7 @@ func main() {
}
go webService.ServeForever()
// BEGIN EXAMPLE CODE - replace with config loading later.
done := make(chan bool)
go func() {
rules := manager.AggregationRules{
&manager.AggregationRule{
Filters: manager.Filters{manager.NewFilter("service", "discovery")},
},
}
aggregator.SetRules(rules)
done <- true
}()
<-done
// END EXAMPLE CODE
aggregator.SetRules(conf.AggregationRules())
log.Println("Running summary dispatcher...")
summarizer.Dispatch(suppressor)