├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── beater ├── boot_actuator.go ├── boot_actuator_test.go ├── springbeat.go └── springbeat_test.go ├── config ├── config.go └── config_test.go ├── docs └── index.asciidoc ├── etc ├── beat.yml ├── fields.yml └── springbeat.template.json ├── examples ├── health.json ├── metrics.json └── metrics_raw.json ├── glide.yaml ├── main.go ├── main_test.go ├── springbeat.template-es2x.json ├── springbeat.template.json ├── springbeat.yml └── tests └── system ├── config └── springbeat.yml.j2 ├── requirements.txt ├── springbeat.py └── test_base.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /build 3 | 4 | .DS_Store 5 | /springbeat 6 | /springbeat.test 7 | *.pyc 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | services: 4 | - docker 5 | 6 | language: go 7 | 8 | go: 9 | - 1.6 10 | 11 | os: 12 | - linux 13 | - osx 14 | 15 | env: 16 | matrix: 17 | - TARGETS="check" 18 | - TARGETS="-C springbeat testsuite" 19 | 20 | global: 21 | # Cross-compile for amd64 only to speed up testing. 22 | - GOX_FLAGS="-arch amd64" 23 | 24 | addons: 25 | apt: 26 | packages: 27 | - python-virtualenv 28 | 29 | before_install: 30 | # Redo the travis setup but with the elastic/libbeat path. This is needed so the package path is correct 31 | - mkdir -p $HOME/gopath/src/github.com/elastic/beats/ 32 | - rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/github.com/elastic/beats/ 33 | - export TRAVIS_BUILD_DIR=$HOME/gopath/src/github.com/elastic/beats/ 34 | - cd $HOME/gopath/src/github.com/elastic/beats/ 35 | 36 | install: 37 | - true 38 | 39 | script: 40 | - make $TARGETS 41 | 42 | after_success: 43 | # Copy full.cov to coverage.txt because codecov.io requires this file 44 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/consulthys/springbeat/0d7c9654f1923f549c91b79806fc045a00ff9aa4/CONTRIBUTING.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Val Crettaz 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BEATNAME=springbeat 2 | BEAT_DIR=github.com/consulthys 3 | SYSTEM_TESTS=false 4 | TEST_ENVIRONMENT=false 5 | ES_BEATS=./vendor/github.com/elastic/beats 6 | GOPACKAGES=$(shell glide novendor) 7 | PREFIX?=. 8 | 9 | # Path to the libbeat Makefile 10 | -include $(ES_BEATS)/libbeat/scripts/Makefile 11 | 12 | .PHONY: init 13 | init: 14 | glide update --no-recursive 15 | make update 16 | git init 17 | 18 | .PHONY: commit 19 | commit: 20 | git add README.md CONTRIBUTING.md 21 | git commit -m "Initial commit" 22 | git add LICENSE 23 | git commit -m "Add the LICENSE" 24 | git add .gitignore 25 | git commit -m "Add git settings" 26 | git add . 27 | git reset -- .travis.yml 28 | git commit -m "Add springbeat" 29 | git add .travis.yml 30 | git commit -m "Add Travis CI" 31 | 32 | .PHONY: update-deps 33 | update-deps: 34 | glide update --no-recursive --strip-vcs 35 | 36 | # This is called by the beats packer before building starts 37 | .PHONY: before-build 38 | before-build: 39 | 40 | # Create binary packages for the beat 41 | pack: create-packer 42 | cd dev-tools/packer; make deps images springbeat 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Springbeat 2 | 3 | Welcome to Springbeat. 4 | 5 | **Important Notes:** 6 | 1. For now, only two endpoints are supported, namely `/metrics` and `/health`. We'll add [more endpoints](http://docs.spring.io/spring-boot/docs/1.4.0.RELEASE/reference/htmlsingle/#production-ready-endpoints) as we go 7 | 2. This plugin will only work if your Spring Boot application has the `spring-boot-starter-actuator` dependency 8 | 9 | ``` 10 | 11 | org.springframework.boot 12 | spring-boot-starter-actuator 13 | 14 | ``` 15 | 16 | Ensure that this folder is at the following location: 17 | `${GOPATH}/github.com/consulthys` 18 | 19 | ## Getting Started with Springbeat 20 | 21 | ### Requirements 22 | 23 | * [Golang](https://golang.org/dl/) 1.7.1 24 | 25 | ### Init Project 26 | To get running with Springbeat, run the following command: 27 | 28 | ``` 29 | make init 30 | ``` 31 | 32 | To commit the first version before you modify it, run: 33 | 34 | ``` 35 | make commit 36 | ``` 37 | 38 | It will create a clean git history for each major step. Note that you can always rewrite the history if you wish before pushing your changes. 39 | 40 | To push Springbeat in the git repository, run the following commands: 41 | 42 | ``` 43 | git remote set-url origin https://github.com/consulthys/springbeat 44 | git push origin master 45 | ``` 46 | 47 | For further development, check out the [beat developer guide](https://www.elastic.co/guide/en/beats/libbeat/current/new-beat.html). 48 | 49 | ### Build 50 | 51 | To build the binary for Springbeat run the command below. This will generate a binary 52 | in the same directory with the name springbeat. 53 | 54 | ``` 55 | make 56 | ``` 57 | 58 | 59 | ### Run 60 | 61 | To run Springbeat with debugging output enabled, run: 62 | 63 | ``` 64 | ./springbeat -c springbeat.yml -e -d "*" 65 | ``` 66 | 67 | 68 | ### Test 69 | 70 | To test Springbeat, run the following command: 71 | 72 | ``` 73 | make testsuite 74 | ``` 75 | 76 | alternatively: 77 | ``` 78 | make unit-tests 79 | make system-tests 80 | make integration-tests 81 | make coverage-report 82 | ``` 83 | 84 | The test coverage is reported in the folder `./build/coverage/` 85 | 86 | 87 | ### Package 88 | 89 | To be able to package Springbeat the requirements are as follows: 90 | 91 | * [Docker Environment](https://docs.docker.com/engine/installation/) >= 1.10 92 | * $GOPATH/bin must be part of $PATH: `export PATH=${PATH}:${GOPATH}/bin` 93 | 94 | To cross-compile and package Springbeat for all supported platforms, run the following commands: 95 | 96 | ``` 97 | cd dev-tools/packer 98 | make deps 99 | make images 100 | make 101 | ``` 102 | 103 | ### Update 104 | 105 | Each beat has a template for the mapping in elasticsearch and a documentation for the fields 106 | which is automatically generated based on `etc/fields.yml`. 107 | To generate etc/springbeat.template.json and etc/springbeat.asciidoc 108 | 109 | ``` 110 | make update 111 | ``` 112 | 113 | 114 | ### Cleanup 115 | 116 | To clean Springbeat source code, run the following commands: 117 | 118 | ``` 119 | make fmt 120 | make simplify 121 | ``` 122 | 123 | To clean up the build directory and generated artifacts, run: 124 | 125 | ``` 126 | make clean 127 | ``` 128 | 129 | 130 | ### Clone 131 | 132 | To clone Springbeat from the git repository, run the following commands: 133 | 134 | ``` 135 | mkdir -p ${GOPATH}/github.com/consulthys 136 | cd ${GOPATH}/github.com/consulthys 137 | git clone https://github.com/consulthys/springbeat 138 | ``` 139 | 140 | 141 | For further development, check out the [beat developer guide](https://www.elastic.co/guide/en/beats/libbeat/current/new-beat.html). 142 | -------------------------------------------------------------------------------- /beater/boot_actuator.go: -------------------------------------------------------------------------------- 1 | package beater 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "net/url" 9 | "strings" 10 | ) 11 | 12 | const METRICS_STATS = "/metrics" 13 | const HEALTH_STATS = "/health" 14 | 15 | type HealthStats struct { 16 | Status string `json:"status"` 17 | DiskSpace struct { 18 | Status string `json:"status"` 19 | Total uint64 `json:"total"` 20 | Free uint64 `json:"free"` 21 | Threshold uint64 `json:"threshold"` 22 | } `json:"diskSpace"` 23 | DB struct { 24 | Status string `json:"status"` 25 | Database string `json:"database"` 26 | Hello uint64 `json:"hello"` 27 | } `json:"db"` 28 | } 29 | 30 | type MetricsStats struct { 31 | Mem struct { 32 | Total uint64 `json:"total"` 33 | Free uint64 `json:"free"` 34 | } `json:"mem"` 35 | Processors uint64 `json:"processors"` 36 | LoadAverage float64 `json:"load_average"` 37 | Uptime struct { 38 | Total uint64 `json:"total"` 39 | Instance uint64 `json:"instance"` 40 | } `json:"uptime"` 41 | Heap struct { 42 | Total uint64 `json:"total"` 43 | Committed uint64 `json:"committed"` 44 | Init uint64 `json:"init"` 45 | Used uint64 `json:"used"` 46 | } `json:"heap"` 47 | NonHeap struct { 48 | Total uint64 `json:"total"` 49 | Committed uint64 `json:"committed"` 50 | Init uint64 `json:"init"` 51 | Used uint64 `json:"used"` 52 | } `json:"non_heap"` 53 | Threads struct { 54 | Total uint64 `json:"total"` 55 | TotalStarted uint64 `json:"started"` 56 | Peak uint64 `json:"peak"` 57 | Daemon uint64 `json:"daemon"` 58 | } `json:"non_heap"` 59 | Classes struct { 60 | Total uint64 `json:"total"` 61 | Loaded uint64 `json:"loaded"` 62 | Unloaded uint64 `json:"unloaded"` 63 | } `json:"classes"` 64 | GC struct { 65 | Scavenge struct { 66 | Count uint64 `json:"count"` 67 | Time uint64 `json:"time"` 68 | } `json:"scavenge"` 69 | Marksweep struct { 70 | Count uint64 `json:"count"` 71 | Time uint64 `json:"time"` 72 | } `json:"marksweep"` 73 | } `json:"gc"` 74 | Http struct { 75 | SessionsMax int64 `json:"max_sessions"` 76 | SessionsActive uint64 `json:"active_sessions"` 77 | } `json:"http"` 78 | DataSource struct { 79 | PrimaryActive uint64 `json:"primary_active"` 80 | PrimaryUsage float64 `json:"primary_usage"` 81 | } `json:"data_source"` 82 | GaugeResponse struct { 83 | Actuator float64 `json:"actuator,omitempty"` 84 | Autoconfig float64 `json:"autoconfig,omitempty"` 85 | Beans float64 `json:"beans,omitempty"` 86 | Configprops float64 `json:"configprops,omitempty"` 87 | Dump float64 `json:"dump,omitempty"` 88 | Env float64 `json:"env,omitempty"` 89 | Health float64 `json:"health,omitempty"` 90 | Info float64 `json:"info,omitempty"` 91 | Root float64 `json:"root,omitempty"` 92 | Trace float64 `json:"trace,omitempty"` 93 | Unmapped float64 `json:"unmapped,omitempty"` 94 | } `json:"gauge_response"` 95 | Status struct { 96 | TWO00 struct { 97 | Actuator uint64 `json:"actuator,omitempty"` 98 | Autoconfig uint64 `json:"autoconfig,omitempty"` 99 | Beans uint64 `json:"beans,omitempty"` 100 | Configprops uint64 `json:"configprops,omitempty"` 101 | Dump uint64 `json:"dump,omitempty"` 102 | Env uint64 `json:"env,omitempty"` 103 | Health uint64 `json:"health,omitempty"` 104 | Info uint64 `json:"info,omitempty"` 105 | Root uint64 `json:"root,omitempty"` 106 | Trace uint64 `json:"trace,omitempty"` 107 | } `json:"200"` 108 | } `json:"status"` 109 | } 110 | 111 | type RawMetricsStats struct { 112 | Mem uint64 `json:"mem"` 113 | MemFree uint64 `json:"mem.free"` 114 | Processors uint64 `json:"processors"` 115 | InstanceUptime uint64 `json:"instance.uptime"` 116 | Uptime uint64 `json:"uptime"` 117 | SystemloadAverage float64 `json:"systemload.average"` 118 | HeapCommitted uint64 `json:"heap.committed"` 119 | HeapInit uint64 `json:"heap.init"` 120 | HeapUsed uint64 `json:"heap.used"` 121 | Heap uint64 `json:"heap"` 122 | NonheapCommitted uint64 `json:"nonheap.committed"` 123 | NonheapInit uint64 `json:"nonheap.init"` 124 | NonheapUsed uint64 `json:"nonheap.used"` 125 | Nonheap uint64 `json:"nonheap"` 126 | ThreadsPeak uint64 `json:"threads.peak"` 127 | ThreadsDaemon uint64 `json:"threads.daemon"` 128 | ThreadsTotalStarted uint64 `json:"threads.totalStarted"` 129 | Threads uint64 `json:"threads"` 130 | Classes uint64 `json:"classes"` 131 | ClassesLoaded uint64 `json:"classes.loaded"` 132 | ClassesUnloaded uint64 `json:"classes.unloaded"` 133 | GCPsScavengeCount uint64 `json:"gc.ps_scavenge.count"` 134 | GCPsScavengeTime uint64 `json:"gc.ps_scavenge.time"` 135 | GCPsMarksweepCount uint64 `json:"gc.ps_marksweep.count"` 136 | GCPsMarksweepTime uint64 `json:"gc.ps_marksweep.time"` 137 | HttpSessionsMax int64 `json:"httpsessions.max"` 138 | HttpSessionsActive uint64 `json:"httpsessions.active"` 139 | DateSourcePrimaryActive uint64 `json:"datasource.primary.active"` 140 | DateSourcePrimaryUsage float64 `json:"datasource.primary.usage"` 141 | GaugeResponseActuator float64 `json:"gauge.response.actuator"` 142 | GaugeResponseBeans float64 `json:"gauge.response.beans"` 143 | GaugeResponseTrace float64 `json:"gauge.response.trace"` 144 | GaugeResponseAutoconfig float64 `json:"gauge.response.autoconfig"` 145 | GaugeResponseDump float64 `json:"gauge.response.dump"` 146 | GaugeResponseHealth float64 `json:"gauge.response.health"` 147 | GaugeResponseRoot float64 `json:"gauge.response.root"` 148 | GaugeResponseUnmapped float64 `json:"gauge.response.unmapped"` 149 | GaugeResponseInfo float64 `json:"gauge.response.info"` 150 | GaugeResponseEnv float64 `json:"gauge.response.env"` 151 | GaugeResponseConfigprops float64 `json:"gauge.response.configprops"` 152 | CounterStatus200Actuator uint64 `json:"counter.status.200.actuator"` 153 | CounterStatus200Autoconfig uint64 `json:"counter.status.200.autoconfig"` 154 | CounterStatus200Beans uint64 `json:"counter.status.200.beans"` 155 | CounterStatus200Configprops uint64 `json:"counter.status.200.configprops"` 156 | CounterStatus200Dump uint64 `json:"counter.status.200.dump"` 157 | CounterStatus200Env uint64 `json:"counter.status.200.env"` 158 | CounterStatus200Health uint64 `json:"counter.status.200.health"` 159 | CounterStatus200Info uint64 `json:"counter.status.200.info"` 160 | CounterStatus200Root uint64 `json:"counter.status.200.root"` 161 | CounterStatus200Trace uint64 `json:"counter.status.200.trace"` 162 | } 163 | 164 | func (bt *Springbeat) GetHealthStats(u url.URL) (*HealthStats, error) { 165 | res, err := http.Get(strings.TrimSuffix(u.String(), "/") + HEALTH_STATS) 166 | if err != nil { 167 | return nil, err 168 | } 169 | defer res.Body.Close() 170 | 171 | if res.StatusCode != 200 { 172 | return nil, fmt.Errorf("HTTP%s", res.Status) 173 | } 174 | 175 | body, err := ioutil.ReadAll(res.Body) 176 | if err != nil { 177 | return nil, err 178 | } 179 | 180 | stats := &HealthStats{} 181 | err = json.Unmarshal([]byte(body), &stats) 182 | if err != nil { 183 | return nil, err 184 | } 185 | return stats, nil 186 | } 187 | 188 | func (bt *Springbeat) GetMetricsStats(u url.URL) (*MetricsStats, error) { 189 | res, err := http.Get(strings.TrimSuffix(u.String(), "/") + METRICS_STATS) 190 | if err != nil { 191 | return nil, err 192 | } 193 | defer res.Body.Close() 194 | 195 | if res.StatusCode != 200 { 196 | return nil, fmt.Errorf("HTTP%s", res.Status) 197 | } 198 | 199 | body, err := ioutil.ReadAll(res.Body) 200 | if err != nil { 201 | return nil, err 202 | } 203 | 204 | raw_stats := &RawMetricsStats{} 205 | err = json.Unmarshal([]byte(body), &raw_stats) 206 | if err != nil { 207 | return nil, err 208 | } 209 | 210 | // Transform into usable JSON format 211 | stats := &MetricsStats{} 212 | stats.Mem.Free = raw_stats.MemFree 213 | stats.Mem.Total = raw_stats.Mem 214 | stats.Processors = raw_stats.Processors 215 | stats.LoadAverage = raw_stats.SystemloadAverage 216 | stats.Uptime.Total = raw_stats.Uptime 217 | stats.Uptime.Instance = raw_stats.InstanceUptime 218 | stats.Heap.Total = raw_stats.Heap 219 | stats.Heap.Init = raw_stats.HeapInit 220 | stats.Heap.Committed = raw_stats.HeapCommitted 221 | stats.Heap.Used = raw_stats.HeapUsed 222 | stats.NonHeap.Total = raw_stats.Nonheap 223 | stats.NonHeap.Init = raw_stats.NonheapInit 224 | stats.NonHeap.Committed = raw_stats.NonheapCommitted 225 | stats.NonHeap.Used = raw_stats.NonheapUsed 226 | stats.Threads.Total = raw_stats.Threads 227 | stats.Threads.TotalStarted = raw_stats.ThreadsTotalStarted 228 | stats.Threads.Peak = raw_stats.ThreadsPeak 229 | stats.Threads.Daemon = raw_stats.ThreadsDaemon 230 | stats.Classes.Total = raw_stats.Classes 231 | stats.Classes.Loaded = raw_stats.ClassesLoaded 232 | stats.Classes.Unloaded = raw_stats.ClassesUnloaded 233 | stats.GC.Scavenge.Count = raw_stats.GCPsScavengeCount 234 | stats.GC.Scavenge.Time = raw_stats.GCPsScavengeTime 235 | stats.GC.Marksweep.Count = raw_stats.GCPsMarksweepCount 236 | stats.GC.Marksweep.Time = raw_stats.GCPsMarksweepTime 237 | stats.Http.SessionsActive = raw_stats.HttpSessionsActive 238 | stats.Http.SessionsMax = raw_stats.HttpSessionsMax 239 | stats.DataSource.PrimaryActive = raw_stats.DateSourcePrimaryActive 240 | stats.DataSource.PrimaryUsage = raw_stats.DateSourcePrimaryUsage 241 | stats.GaugeResponse.Actuator = raw_stats.GaugeResponseActuator 242 | stats.GaugeResponse.Autoconfig = raw_stats.GaugeResponseAutoconfig 243 | stats.GaugeResponse.Beans = raw_stats.GaugeResponseBeans 244 | stats.GaugeResponse.Configprops = raw_stats.GaugeResponseConfigprops 245 | stats.GaugeResponse.Dump = raw_stats.GaugeResponseDump 246 | stats.GaugeResponse.Env = raw_stats.GaugeResponseEnv 247 | stats.GaugeResponse.Health = raw_stats.GaugeResponseHealth 248 | stats.GaugeResponse.Info = raw_stats.GaugeResponseInfo 249 | stats.GaugeResponse.Root = raw_stats.GaugeResponseRoot 250 | stats.GaugeResponse.Trace = raw_stats.GaugeResponseTrace 251 | stats.GaugeResponse.Unmapped = raw_stats.GaugeResponseUnmapped 252 | stats.Status.TWO00.Actuator = raw_stats.CounterStatus200Actuator 253 | stats.Status.TWO00.Autoconfig = raw_stats.CounterStatus200Autoconfig 254 | stats.Status.TWO00.Beans = raw_stats.CounterStatus200Beans 255 | stats.Status.TWO00.Configprops = raw_stats.CounterStatus200Configprops 256 | stats.Status.TWO00.Dump = raw_stats.CounterStatus200Dump 257 | stats.Status.TWO00.Env = raw_stats.CounterStatus200Env 258 | stats.Status.TWO00.Health = raw_stats.CounterStatus200Health 259 | stats.Status.TWO00.Info = raw_stats.CounterStatus200Info 260 | stats.Status.TWO00.Root = raw_stats.CounterStatus200Root 261 | stats.Status.TWO00.Trace = raw_stats.CounterStatus200Trace 262 | 263 | return stats, nil 264 | } 265 | -------------------------------------------------------------------------------- /beater/boot_actuator_test.go: -------------------------------------------------------------------------------- 1 | package beater -------------------------------------------------------------------------------- /beater/springbeat.go: -------------------------------------------------------------------------------- 1 | package beater 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/url" 7 | "time" 8 | 9 | "github.com/elastic/beats/libbeat/beat" 10 | "github.com/elastic/beats/libbeat/common" 11 | "github.com/elastic/beats/libbeat/logp" 12 | "github.com/elastic/beats/libbeat/publisher" 13 | 14 | "github.com/consulthys/springbeat/config" 15 | ) 16 | 17 | type Springbeat struct { 18 | done chan struct{} 19 | config config.Config 20 | client publisher.Client 21 | 22 | urls []*url.URL 23 | 24 | metricsStats bool 25 | healthStats bool 26 | } 27 | 28 | // Creates beater 29 | func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) { 30 | config := config.DefaultConfig 31 | if err := cfg.Unpack(&config); err != nil { 32 | return nil, fmt.Errorf("Error reading config file: %v", err) 33 | } 34 | 35 | bt := &Springbeat{ 36 | done: make(chan struct{}), 37 | config: config, 38 | } 39 | 40 | //define default URL if none provided 41 | var urlConfig []string 42 | if config.URLs != nil { 43 | urlConfig = config.URLs 44 | } else { 45 | urlConfig = []string{"http://127.0.0.1"} 46 | } 47 | 48 | bt.urls = make([]*url.URL, len(urlConfig)) 49 | for i := 0; i < len(urlConfig); i++ { 50 | u, err := url.Parse(urlConfig[i]) 51 | if err != nil { 52 | logp.Err("Invalid Spring Boot URL: %v", err) 53 | return nil, err 54 | } 55 | bt.urls[i] = u 56 | } 57 | 58 | if config.Stats.Metrics != nil { 59 | bt.metricsStats = *config.Stats.Metrics 60 | } else { 61 | bt.metricsStats = true 62 | } 63 | 64 | if config.Stats.Health != nil { 65 | bt.healthStats = *config.Stats.Health 66 | } else { 67 | bt.healthStats = true 68 | } 69 | 70 | if !bt.metricsStats && !bt.metricsStats { 71 | return nil, errors.New("Invalid statistics configuration") 72 | } 73 | 74 | logp.Debug("springbeat", "Init springbeat") 75 | logp.Debug("springbeat", "Period %v\n", bt.config.Period) 76 | logp.Debug("springbeat", "Watch %v", bt.urls) 77 | logp.Debug("springbeat", "Metrics statistics %t\n", bt.metricsStats) 78 | logp.Debug("springbeat", "Health statistics %t\n", bt.healthStats) 79 | 80 | return bt, nil 81 | } 82 | 83 | func (bt *Springbeat) Run(b *beat.Beat) error { 84 | logp.Info("springbeat is running! Hit CTRL-C to stop it.") 85 | 86 | bt.client = b.Publisher.Connect() 87 | 88 | for _, u := range bt.urls { 89 | go func(u *url.URL) { 90 | 91 | ticker := time.NewTicker(bt.config.Period) 92 | counter := 1 93 | for { 94 | select { 95 | case <-bt.done: 96 | goto GotoFinish 97 | case <-ticker.C: 98 | } 99 | 100 | timerStart := time.Now() 101 | 102 | if bt.metricsStats { 103 | logp.Debug("springbeat", "Metrics stats for url: %v", u) 104 | metrics_stats, err := bt.GetMetricsStats(*u) 105 | 106 | if err != nil { 107 | logp.Err("Error reading Metrics stats: %v", err) 108 | } else { 109 | logp.Debug("springbeat", "Metrics stats detail: %+v", metrics_stats) 110 | 111 | event := common.MapStr{ 112 | "@timestamp": common.Time(time.Now()), 113 | "type": "metrics", 114 | "counter": counter, 115 | "metrics": metrics_stats, 116 | } 117 | 118 | bt.client.PublishEvent(event) 119 | logp.Info("Spring Boot /metrics stats sent") 120 | counter++ 121 | } 122 | } 123 | 124 | if bt.healthStats { 125 | logp.Debug("springbeat", "Health stats for url: %v", u) 126 | health_stats, err := bt.GetHealthStats(*u) 127 | 128 | if err != nil { 129 | logp.Err("Error reading Health stats: %v", err) 130 | } else { 131 | logp.Debug("springbeat", "Health stats detail: %+v", health_stats) 132 | 133 | event := common.MapStr{ 134 | "@timestamp": common.Time(time.Now()), 135 | "type": "health", 136 | "counter": counter, 137 | "health": health_stats, 138 | } 139 | 140 | bt.client.PublishEvent(event) 141 | logp.Info("Spring Boot /health stats sent") 142 | counter++ 143 | } 144 | } 145 | 146 | timerEnd := time.Now() 147 | duration := timerEnd.Sub(timerStart) 148 | if duration.Nanoseconds() > bt.config.Period.Nanoseconds() { 149 | logp.Warn("Ignoring tick(s) due to processing taking longer than one period") 150 | } 151 | } 152 | 153 | GotoFinish: 154 | }(u) 155 | } 156 | 157 | <-bt.done 158 | return nil 159 | } 160 | 161 | func (bt *Springbeat) Stop() { 162 | logp.Debug("springbeat", "Stop springbeat") 163 | bt.client.Close() 164 | close(bt.done) 165 | } 166 | -------------------------------------------------------------------------------- /beater/springbeat_test.go: -------------------------------------------------------------------------------- 1 | package beater -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | // Config is put into a different package to prevent cyclic imports in case 2 | // it is needed in several locations 3 | 4 | package config 5 | 6 | import "time" 7 | 8 | type Config struct { 9 | Period time.Duration `config:"period"` 10 | URLs []string 11 | 12 | Stats struct { 13 | Metrics *bool 14 | Health *bool 15 | } 16 | } 17 | 18 | var DefaultConfig = Config{ 19 | Period: 1 * time.Second, 20 | } 21 | -------------------------------------------------------------------------------- /config/config_test.go: -------------------------------------------------------------------------------- 1 | // +build !integration 2 | 3 | package config 4 | -------------------------------------------------------------------------------- /docs/index.asciidoc: -------------------------------------------------------------------------------- 1 | = Springbeat Docs 2 | 3 | Welcome to the Springbeat documentation. 4 | 5 | 6 | -------------------------------------------------------------------------------- /etc/beat.yml: -------------------------------------------------------------------------------- 1 | ################### Springbeat Configuration Example ######################### 2 | 3 | ############################# Springbeat ###################################### 4 | 5 | springbeat: 6 | # Defines how often an event is sent to the output 7 | period: 10s 8 | 9 | # List of URLs to the Spring Boot app. 10 | # Defaults to ["http://127.0.0.1"]. 11 | # Note: Do not use trailing slash 12 | urls: 13 | #- http://user:password@127.0.0.1:8080 14 | - http://127.0.0.1:8080 15 | 16 | # Statistics to collect 17 | stats: 18 | metrics: true 19 | health: true 20 | -------------------------------------------------------------------------------- /etc/fields.yml: -------------------------------------------------------------------------------- 1 | defaults: 2 | type: keyword 3 | required: false 4 | index: true 5 | 6 | common: 7 | type: group 8 | description: > 9 | Contains common fields available in all event types. 10 | fields: 11 | - type: group 12 | name: beat 13 | fields: 14 | - name: name 15 | description: > 16 | The name of the Beat sending the log messages. If the shipper name is set 17 | in the configuration file, then that value is used. If it is not set, 18 | the hostname is used. 19 | - name: hostname 20 | description: > 21 | The hostname as returned by the operating system on which the Beat is 22 | running. 23 | - name: "@timestamp" 24 | type: date 25 | required: true 26 | format: YYYY-MM-DDTHH:MM:SS.milliZ 27 | example: 2015-01-24T14:06:05.071Z 28 | description: > 29 | The timestamp when the log line was read. The precision is in 30 | milliseconds. The timezone is UTC. 31 | - name: type 32 | required: true 33 | description: > 34 | The type of the event generated by this beat, one of "jvm", "events", "process" 35 | 36 | health: 37 | fields: 38 | - name: counter 39 | type: integer 40 | required: true 41 | description: > 42 | The sequence number of the sample 43 | - type: group 44 | name: health 45 | fields: 46 | - name: status 47 | description: > 48 | The status of the Spring Boot application 49 | - name: diskSpace.status 50 | description: > 51 | The status of the disk space 52 | - name: diskSpace.total 53 | description: > 54 | The total space on disk 55 | - name: diskSpace.free 56 | description: > 57 | The remaining free space on disk 58 | - name: diskSpace.threshold 59 | description: > 60 | The threshold space on disk 61 | - name: db.status 62 | description: > 63 | The status of the data source 64 | - name: db.database 65 | description: > 66 | The type of the data source 67 | - name: db.hello 68 | description: > 69 | The health of the data source 70 | 71 | metrics: 72 | fields: 73 | - name: counter 74 | type: integer 75 | required: true 76 | description: > 77 | The sequence number of the sample 78 | - type: group 79 | name: metrics 80 | fields: 81 | - name: mem.total 82 | description: > 83 | The total available memory 84 | - name: mem.free 85 | description: > 86 | The free available memory 87 | - name: heap.total 88 | description: > 89 | The total available heap memory 90 | - name: heap.init 91 | description: > 92 | The initial heap memory 93 | - name: heap.committed 94 | description: > 95 | The committed heap memory 96 | - name: heap.used 97 | description: > 98 | The used heap memory 99 | 100 | sections: 101 | - ["common", "Common"] 102 | - ["health", "Health"] 103 | - ["metrics", "Metrics"] 104 | -------------------------------------------------------------------------------- /etc/springbeat.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "springbeat-*", 3 | "settings": { 4 | "index.refresh_interval": "5s" 5 | } 6 | } -------------------------------------------------------------------------------- /examples/health.json: -------------------------------------------------------------------------------- 1 | { 2 | "@timestamp": "2016-08-18T04:46:31.565Z", 3 | "beat": { 4 | "hostname": "iMac.local", 5 | "name": "iMac.local" 6 | }, 7 | "counter": 2, 8 | "health": { 9 | "db": { 10 | "database": "H2", 11 | "hello": 1, 12 | "status": "UP" 13 | }, 14 | "diskSpace": { 15 | "free": 528694333440, 16 | "status": "UP", 17 | "threshold": 10485760, 18 | "total": 999345127424 19 | }, 20 | "status": "UP" 21 | }, 22 | "type": "health" 23 | } 24 | -------------------------------------------------------------------------------- /examples/metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "@timestamp": "2016-08-18T04:34:45.249Z", 3 | "beat": { 4 | "hostname": "iMac.local", 5 | "name": "iMac.local" 6 | }, 7 | "counter": 5, 8 | "metrics": { 9 | "classes": { 10 | "loaded": 7491, 11 | "total": 7491, 12 | "unloaded": 0 13 | }, 14 | "data_source": { 15 | "primary_active": 0, 16 | "primary_usage": 0 17 | }, 18 | "gauge_response": { 19 | "actuator": 5, 20 | "autoconfig": 25, 21 | "configprops": 722, 22 | "env": 26, 23 | "info": 444, 24 | "trace": 11, 25 | "unmapped": 147 26 | }, 27 | "gc": { 28 | "marksweep": { 29 | "count": 2, 30 | "time": 129 31 | }, 32 | "scavenge": { 33 | "count": 9, 34 | "time": 94 35 | } 36 | }, 37 | "heap": { 38 | "committed": 588288, 39 | "init": 262144, 40 | "total": 3728384, 41 | "used": 211220 42 | }, 43 | "http": { 44 | "active_sessions": 0, 45 | "max_sessions": -1 46 | }, 47 | "load_average": 2.30517578125, 48 | "mem": { 49 | "free": 377067, 50 | "total": 650563 51 | }, 52 | "processors": 4, 53 | "status": { 54 | "200": { 55 | "actuator": 48, 56 | "autoconfig": 1, 57 | "configprops": 1, 58 | "env": 1, 59 | "info": 1, 60 | "trace": 1 61 | } 62 | }, 63 | "uptime": { 64 | "instance": 966561, 65 | "total": 972644 66 | } 67 | }, 68 | "type": "metrics" 69 | } -------------------------------------------------------------------------------- /examples/metrics_raw.json: -------------------------------------------------------------------------------- 1 | { 2 | "mem": 638628, 3 | "mem.free": 419361, 4 | "processors": 4, 5 | "instance.uptime": 406667, 6 | "uptime": 413427, 7 | "systemload.average": 1.4521484375, 8 | "heap.committed": 578048, 9 | "heap.init": 262144, 10 | "heap.used": 158686, 11 | "heap": 3728384, 12 | "nonheap.committed": 61952, 13 | "nonheap.init": 2496, 14 | "nonheap.used": 60383, 15 | "nonheap": 0, 16 | "threads.peak": 23, 17 | "threads.daemon": 21, 18 | "threads.totalStarted": 27, 19 | "threads": 23, 20 | "classes": 7410, 21 | "classes.loaded": 7410, 22 | "classes.unloaded": 0, 23 | "gc.ps_scavenge.count": 9, 24 | "gc.ps_scavenge.time": 112, 25 | "gc.ps_marksweep.count": 2, 26 | "gc.ps_marksweep.time": 124, 27 | "httpsessions.max": -1, 28 | "httpsessions.active": 0, 29 | "datasource.primary.active": 0, 30 | "datasource.primary.usage": 0, 31 | "gauge.response.beans": 37, 32 | "gauge.response.trace": 11, 33 | "gauge.response.autoconfig": 15, 34 | "gauge.response.dump": 149, 35 | "gauge.response.health": 794, 36 | "gauge.response.root": 12, 37 | "gauge.response.unmapped": 5, 38 | "gauge.response.star-star": 5, 39 | "gauge.response.info": 19, 40 | "gauge.response.star-star.favicon.ico": 508, 41 | "gauge.response.env": 5, 42 | "gauge.response.configprops": 104, 43 | "counter.status.200.root": 1, 44 | "counter.status.200.configprops": 1, 45 | "counter.status.404.star-star": 3, 46 | "counter.status.200.health": 1, 47 | "counter.status.200.autoconfig": 1, 48 | "counter.status.401.unmapped": 2, 49 | "counter.status.200.trace": 1, 50 | "counter.status.200.env": 1, 51 | "counter.status.200.star-star.favicon.ico": 1, 52 | "counter.status.200.info": 1, 53 | "counter.status.200.beans": 1, 54 | "counter.status.200.dump": 1 55 | } -------------------------------------------------------------------------------- /glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/consulthys/springbeat 2 | import: 3 | - package: github.com/elastic/beats 4 | subpackages: 5 | - libbeat/beat 6 | - libbeat/common 7 | - libbeat/logp 8 | - libbeat/publisher 9 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/elastic/beats/libbeat/beat" 7 | 8 | "github.com/consulthys/springbeat/beater" 9 | ) 10 | 11 | func main() { 12 | err := beat.Run("springbeat", "", beater.New) 13 | if err != nil { 14 | os.Exit(1) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // This file is mandatory as otherwise the springbeat.test binary is not generated correctly. 4 | 5 | import ( 6 | "flag" 7 | "testing" 8 | ) 9 | 10 | var systemTest *bool 11 | 12 | func init() { 13 | systemTest = flag.Bool("systemTest", false, "Set to true when running system tests") 14 | } 15 | 16 | // Test started when the test binary is started. Only calls main. 17 | func TestSystem(t *testing.T) { 18 | 19 | if *systemTest { 20 | main() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /springbeat.template-es2x.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "springbeat-*", 3 | "settings": { 4 | "index.refresh_interval": "5s" 5 | } 6 | } -------------------------------------------------------------------------------- /springbeat.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "springbeat-*", 3 | "settings": { 4 | "index.refresh_interval": "5s" 5 | } 6 | } -------------------------------------------------------------------------------- /springbeat.yml: -------------------------------------------------------------------------------- 1 | ################### Springbeat Configuration Example ######################### 2 | 3 | ############################# Springbeat ###################################### 4 | 5 | springbeat: 6 | # Defines how often an event is sent to the output 7 | period: "10s" 8 | 9 | # List of URLs to the Spring Boot app. 10 | # Defaults to ["http://127.0.0.1"]. 11 | # Note: Do not use trailing slash 12 | urls: 13 | - http://user:be052929-31a5-4bf8-bc98-336fe456567d@127.0.0.1:8080 14 | 15 | # Statistics to collect 16 | stats: 17 | metrics: true 18 | health: true 19 | 20 | ############################################################################### 21 | ############################# Libbeat Config ################################## 22 | # Base config file used by all other beats for using libbeat features 23 | 24 | ############################# Output ########################################## 25 | 26 | # Configure what outputs to use when sending the data collected by the beat. 27 | # Multiple outputs may be used. 28 | output: 29 | 30 | ### Elasticsearch as output 31 | elasticsearch: 32 | # Array of hosts to connect to. 33 | # Scheme and port can be left out and will be set to the default (http and 9200) 34 | # In case you specify and additional path, the scheme is required: http://localhost:9200/path 35 | # IPv6 addresses should always be defined as: https://[2001:db8::1]:9200 36 | hosts: ["localhost:9200"] 37 | 38 | # Optional protocol and basic auth credentials. 39 | #protocol: "https" 40 | #username: "admin" 41 | #password: "s3cr3t" 42 | 43 | # Dictionary of HTTP parameters to pass within the url with index operations. 44 | #parameters: 45 | #param1: value1 46 | #param2: value2 47 | 48 | # Number of workers per Elasticsearch host. 49 | #worker: 1 50 | 51 | # Optional index name. The default is "springbeat" and generates 52 | # [springbeat-]YYYY.MM.DD keys. 53 | #index: "springbeat" 54 | 55 | # A template is used to set the mapping in Elasticsearch 56 | # By default template loading is disabled and no template is loaded. 57 | # These settings can be adjusted to load your own template or overwrite existing ones 58 | template: 59 | 60 | # Template name. By default the template name is springbeat. 61 | name: "springbeat" 62 | 63 | # Path to template file 64 | path: "etc/springbeat.template.json" 65 | 66 | # Overwrite existing template 67 | overwrite: true 68 | 69 | # Optional HTTP Path 70 | #path: "/elasticsearch" 71 | 72 | # Proxy server url 73 | #proxy_url: http://proxy:3128 74 | 75 | # The number of times a particular Elasticsearch index operation is attempted. If 76 | # the indexing operation doesn't succeed after this many retries, the events are 77 | # dropped. The default is 3. 78 | #max_retries: 3 79 | 80 | # The maximum number of events to bulk in a single Elasticsearch bulk API index request. 81 | # The default is 50. 82 | #bulk_max_size: 50 83 | 84 | # Configure http request timeout before failing an request to Elasticsearch. 85 | #timeout: 90 86 | 87 | # The number of seconds to wait for new events between two bulk API index requests. 88 | # If `bulk_max_size` is reached before this interval expires, addition bulk index 89 | # requests are made. 90 | #flush_interval: 1 91 | 92 | # Boolean that sets if the topology is kept in Elasticsearch. The default is 93 | # false. This option makes sense only for Packetbeat. 94 | #save_topology: false 95 | 96 | # The time to live in seconds for the topology information that is stored in 97 | # Elasticsearch. The default is 15 seconds. 98 | #topology_expire: 15 99 | 100 | # tls configuration. By default is off. 101 | #tls: 102 | # List of root certificates for HTTPS server verifications 103 | #certificate_authorities: ["/etc/pki/root/ca.pem"] 104 | 105 | # Certificate for TLS client authentication 106 | #certificate: "/etc/pki/client/cert.pem" 107 | 108 | # Client Certificate Key 109 | #certificate_key: "/etc/pki/client/cert.key" 110 | 111 | # Controls whether the client verifies server certificates and host name. 112 | # If insecure is set to true, all server host names and certificates will be 113 | # accepted. In this mode TLS based connections are susceptible to 114 | # man-in-the-middle attacks. Use only for testing. 115 | #insecure: true 116 | 117 | # Configure cipher suites to be used for TLS connections 118 | #cipher_suites: [] 119 | 120 | # Configure curve types for ECDHE based cipher suites 121 | #curve_types: [] 122 | 123 | # Configure minimum TLS version allowed for connection to logstash 124 | #min_version: 1.0 125 | 126 | # Configure maximum TLS version allowed for connection to logstash 127 | #max_version: 1.2 128 | 129 | 130 | ### Logstash as output 131 | #logstash: 132 | # The Logstash hosts 133 | #hosts: ["localhost:5044"] 134 | 135 | # Number of workers per Logstash host. 136 | #worker: 1 137 | 138 | # Set gzip compression level. 139 | #compression_level: 3 140 | 141 | # Optional load balance the events between the Logstash hosts 142 | #loadbalance: true 143 | 144 | # Optional index name. The default index name is set to name of the beat 145 | # in all lowercase. 146 | #index: springbeat 147 | 148 | # SOCKS5 proxy server URL 149 | #proxy_url: socks5://user:password@socks5-server:2233 150 | 151 | # Resolve names locally when using a proxy server. Defaults to false. 152 | #proxy_use_local_resolver: false 153 | 154 | # Optional TLS. By default is off. 155 | #tls: 156 | # List of root certificates for HTTPS server verifications 157 | #certificate_authorities: ["/etc/pki/root/ca.pem"] 158 | 159 | # Certificate for TLS client authentication 160 | #certificate: "/etc/pki/client/cert.pem" 161 | 162 | # Client Certificate Key 163 | #certificate_key: "/etc/pki/client/cert.key" 164 | 165 | # Controls whether the client verifies server certificates and host name. 166 | # If insecure is set to true, all server host names and certificates will be 167 | # accepted. In this mode TLS based connections are susceptible to 168 | # man-in-the-middle attacks. Use only for testing. 169 | #insecure: true 170 | 171 | # Configure cipher suites to be used for TLS connections 172 | #cipher_suites: [] 173 | 174 | # Configure curve types for ECDHE based cipher suites 175 | #curve_types: [] 176 | 177 | 178 | ### File as output 179 | #file: 180 | # Path to the directory where to save the generated files. The option is mandatory. 181 | #path: "/tmp/springbeat" 182 | 183 | # Name of the generated files. The default is `springbeat` and it generates files: `springbeat`, `springbeat.1`, `springbeat.2`, etc. 184 | #filename: springbeat 185 | 186 | # Maximum size in kilobytes of each file. When this size is reached, the files are 187 | # rotated. The default value is 10240 kB. 188 | #rotate_every_kb: 10000 189 | 190 | # Maximum number of files under path. When this number of files is reached, the 191 | # oldest file is deleted and the rest are shifted from last to first. The default 192 | # is 7 files. 193 | #number_of_files: 7 194 | 195 | 196 | ### Console output 197 | # console: 198 | # Pretty print json event 199 | #pretty: false 200 | 201 | 202 | ############################# Shipper ######################################### 203 | 204 | shipper: 205 | # The name of the shipper that publishes the network data. It can be used to group 206 | # all the transactions sent by a single shipper in the web interface. 207 | # If this options is not defined, the hostname is used. 208 | #name: 209 | 210 | # The tags of the shipper are included in their own field with each 211 | # transaction published. Tags make it easy to group servers by different 212 | # logical properties. 213 | #tags: ["service-X", "web-tier"] 214 | 215 | # Optional fields that you can specify to add additional information to the 216 | # output. Fields can be scalar values, arrays, dictionaries, or any nested 217 | # combination of these. 218 | #fields: 219 | # env: staging 220 | 221 | # If this option is set to true, the custom fields are stored as top-level 222 | # fields in the output document instead of being grouped under a fields 223 | # sub-dictionary. Default is false. 224 | #fields_under_root: false 225 | 226 | # Uncomment the following if you want to ignore transactions created 227 | # by the server on which the shipper is installed. This option is useful 228 | # to remove duplicates if shippers are installed on multiple servers. 229 | #ignore_outgoing: true 230 | 231 | # How often (in seconds) shippers are publishing their IPs to the topology map. 232 | # The default is 10 seconds. 233 | #refresh_topology_freq: 10 234 | 235 | # Expiration time (in seconds) of the IPs published by a shipper to the topology map. 236 | # All the IPs will be deleted afterwards. Note, that the value must be higher than 237 | # refresh_topology_freq. The default is 15 seconds. 238 | #topology_expire: 15 239 | 240 | # Internal queue size for single events in processing pipeline 241 | #queue_size: 1000 242 | 243 | # Sets the maximum number of CPUs that can be executing simultaneously. The 244 | # default is the number of logical CPUs available in the system. 245 | #max_procs: 246 | 247 | # Configure local GeoIP database support. 248 | # If no paths are not configured geoip is disabled. 249 | #geoip: 250 | #paths: 251 | # - "/usr/share/GeoIP/GeoLiteCity.dat" 252 | # - "/usr/local/var/GeoIP/GeoLiteCity.dat" 253 | 254 | 255 | ############################# Logging ######################################### 256 | 257 | # There are three options for the log output: syslog, file, stderr. 258 | # Under Windows systems, the log files are per default sent to the file output, 259 | # under all other system per default to syslog. 260 | logging: 261 | 262 | # Send all logging output to syslog. On Windows default is false, otherwise 263 | # default is true. 264 | #to_syslog: true 265 | 266 | # Write all logging output to files. Beats automatically rotate files if rotateeverybytes 267 | # limit is reached. 268 | #to_files: false 269 | 270 | # To enable logging to files, to_files option has to be set to true 271 | files: 272 | # The directory where the log files will written to. 273 | #path: /var/log/springbeat 274 | 275 | # The name of the files where the logs are written to. 276 | #name: springbeat 277 | 278 | # Configure log file size limit. If limit is reached, log file will be 279 | # automatically rotated 280 | rotateeverybytes: 10485760 # = 10MB 281 | 282 | # Number of rotated log files to keep. Oldest files will be deleted first. 283 | #keepfiles: 7 284 | 285 | # Enable debug output for selected components. To enable all selectors use ["*"] 286 | # Other available selectors are beat, publish, service 287 | # Multiple selectors can be chained. 288 | #selectors: [ ] 289 | 290 | # Sets log level. The default log level is error. 291 | # Available log levels are: critical, error, warning, info, debug 292 | #level: error -------------------------------------------------------------------------------- /tests/system/config/springbeat.yml.j2: -------------------------------------------------------------------------------- 1 | ################### Beat Configuration ######################### 2 | 3 | 4 | 5 | ############################# Output ########################################## 6 | 7 | # Configure what outputs to use when sending the data collected by the beat. 8 | # You can enable one or multiple outputs by setting enabled option to true. 9 | output: 10 | 11 | ### File as output 12 | file: 13 | # Enabling file output 14 | enabled: true 15 | 16 | # Path to the directory where to save the generated files. The option is mandatory. 17 | path: {{ output_file_path|default(beat.working_dir + "/output") }} 18 | 19 | 20 | # Name of the generated files. The default is `springbeat` and it generates 21 | # files: `springbeat`, `springbeat.1`, `springbeat.2`, etc. 22 | filename: "{{ output_file_filename|default("springbeat") }}" 23 | 24 | # Maximum size in kilobytes of each file. When this size is reached, the files are 25 | # rotated. The default value is 10 MB. 26 | #rotate_every_kb: 10000 27 | 28 | # Maximum number of files under path. When this number of files is reached, the 29 | # oldest file is deleted and the rest are shifted from last to first. The default 30 | # is 7 files. 31 | #number_of_files: 7 32 | 33 | 34 | 35 | ############################# Shipper ######################################### 36 | 37 | shipper: 38 | # The name of the shipper that publishes the network data. It can be used to group 39 | # all the transactions sent by a single shipper in the web interface. 40 | # If this options is not defined, the hostname is used. 41 | #name: 42 | 43 | # The tags of the shipper are included in their own field with each 44 | # transaction published. Tags make it easy to group servers by different 45 | # logical properties. 46 | #tags: ["service-X", "web-tier"] 47 | 48 | # Uncomment the following if you want to ignore transactions created 49 | # by the server on which the shipper is installed. This option is useful 50 | # to remove duplicates if shippers are installed on multiple servers. 51 | #ignore_outgoing: true 52 | 53 | 54 | ############################# Logging ######################################### 55 | 56 | #logging: 57 | # Send all logging output to syslog. On Windows default is false, otherwise 58 | # default is true. 59 | #to_syslog: true 60 | 61 | # Write all logging output to files. Beats automatically rotate files if configurable 62 | # limit is reached. 63 | #to_files: false 64 | 65 | # Enable debug output for selected components. 66 | #selectors: [] 67 | 68 | # Set log level 69 | #level: error 70 | 71 | #files: 72 | # The directory where the log files will written to. 73 | #path: /var/log/springbeat 74 | 75 | # The name of the files where the logs are written to. 76 | #name: springbeat 77 | 78 | # Configure log file size limit. If limit is reached, log file will be 79 | # automatically rotated 80 | #rotateeverybytes: 10485760 # = 10MB 81 | 82 | # Number of rotated log files to keep. Oldest files will be deleted first. 83 | #keepfiles: 7 84 | -------------------------------------------------------------------------------- /tests/system/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/consulthys/springbeat/0d7c9654f1923f549c91b79806fc045a00ff9aa4/tests/system/requirements.txt -------------------------------------------------------------------------------- /tests/system/springbeat.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('../../vendor/github.com/elastic/beats/libbeat/tests/system') 3 | from beat.beat import TestCase 4 | 5 | class BaseTest(TestCase): 6 | 7 | @classmethod 8 | def setUpClass(self): 9 | self.beat_name = "springbeat" 10 | self.build_path = "../../build/system-tests/" 11 | self.beat_path = "../../springbeat.test" 12 | -------------------------------------------------------------------------------- /tests/system/test_base.py: -------------------------------------------------------------------------------- 1 | from springbeat import BaseTest 2 | 3 | import os 4 | 5 | 6 | class Test(BaseTest): 7 | 8 | def test_base(self): 9 | """ 10 | Basic test with exiting Springbeat normally 11 | """ 12 | self.render_config_template( 13 | path=os.path.abspath(self.working_dir) + "/log/*" 14 | ) 15 | 16 | springbeat_proc = self.start_beat() 17 | self.wait_until( lambda: self.log_contains("springbeat is running")) 18 | exit_code = springbeat_proc.kill_and_wait() 19 | assert exit_code == 0 20 | --------------------------------------------------------------------------------