logstash-input-cloudwatch_logs 1.0.0.pre.3 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/DEVELOPER.md +86 -0
- data/README.md +17 -4
- data/lib/logstash/inputs/cloudwatch_logs.rb +41 -3
- data/logstash-input-cloudwatch_logs.gemspec +1 -1
- data/spec/inputs/cloudwatch_logs_spec.rb +84 -13
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3c086f123d992aed90c4ca3f3f9e32561d8d14b
|
4
|
+
data.tar.gz: f8a299987d5ea86dac1aeccadb1061de883b21e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2efff01f11400ad57da03596b97335c8b7c095e29d0b05b0b5d5abb5b50e277514962d6970bd2eced47f76493fd8dd7e2bb5d850da6e0e6b5d7049dce6c7b00b
|
7
|
+
data.tar.gz: 591d042bfdcbe403d64d1335f2911db0224797f5a70474ec4f748f68cd468de07080f556a9a14b0450b8f3aad97adb50c0046f91f47f2cb5a37d42221edaecd9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Release Notes for `logstash-input-cloudwatch_logs`
|
2
2
|
|
3
|
+
## v1.0.0.rc1 Release Candidate 1 (2017-07-02)
|
4
|
+
* Ensure the plugin stops properly
|
5
|
+
* Implement `start_position` setting ([#28](https://github.com/lukewaite/logstash-input-cloudwatch-logs/issues/28))
|
6
|
+
|
3
7
|
## v1.0.0.pre3 Pre-Release 3 (2017-06-28)
|
4
8
|
* Fix call to `filter_log_events` which had been limited to 10 events per call for debugging
|
5
9
|
|
data/DEVELOPER.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Logstash Plugin
|
2
|
+
|
3
|
+
This is a plugin for [Logstash](https://github.com/elasticsearch/logstash).
|
4
|
+
|
5
|
+
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
|
6
|
+
|
7
|
+
## Documentation
|
8
|
+
|
9
|
+
Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elasticsearch.org/guide/en/logstash/current/).
|
10
|
+
|
11
|
+
- For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
|
12
|
+
- For more asciidoc formatting tips, see the excellent reference here https://github.com/elasticsearch/docs#asciidoc-guide
|
13
|
+
|
14
|
+
## Need Help?
|
15
|
+
|
16
|
+
Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
|
17
|
+
|
18
|
+
## Developing
|
19
|
+
|
20
|
+
### 1. Plugin Developement and Testing
|
21
|
+
|
22
|
+
#### Code
|
23
|
+
- To get started, you'll need JRuby with the Bundler gem installed.
|
24
|
+
|
25
|
+
- Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
|
26
|
+
|
27
|
+
- Install dependencies
|
28
|
+
```sh
|
29
|
+
bundle install
|
30
|
+
```
|
31
|
+
|
32
|
+
#### Test
|
33
|
+
|
34
|
+
- Update your dependencies
|
35
|
+
|
36
|
+
```sh
|
37
|
+
bundle install
|
38
|
+
```
|
39
|
+
|
40
|
+
- Run tests
|
41
|
+
|
42
|
+
```sh
|
43
|
+
bundle exec rspec
|
44
|
+
```
|
45
|
+
|
46
|
+
### 2. Running your unpublished Plugin in Logstash
|
47
|
+
|
48
|
+
#### 2.1 Run in a local Logstash clone
|
49
|
+
|
50
|
+
- Edit Logstash `Gemfile` and add the local plugin path, for example:
|
51
|
+
```ruby
|
52
|
+
gem "logstash-filter-awesome", :path => "/your/local/logstash-filter-awesome"
|
53
|
+
```
|
54
|
+
- Install plugin
|
55
|
+
```sh
|
56
|
+
bin/plugin install --no-verify
|
57
|
+
```
|
58
|
+
- Run Logstash with your plugin
|
59
|
+
```sh
|
60
|
+
bin/logstash -e 'filter {awesome {}}'
|
61
|
+
```
|
62
|
+
At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
|
63
|
+
|
64
|
+
#### 2.2 Run in an installed Logstash
|
65
|
+
|
66
|
+
You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
|
67
|
+
|
68
|
+
- Build your plugin gem
|
69
|
+
```sh
|
70
|
+
gem build logstash-filter-awesome.gemspec
|
71
|
+
```
|
72
|
+
- Install the plugin from the Logstash home
|
73
|
+
```sh
|
74
|
+
bin/plugin install /your/local/plugin/logstash-filter-awesome.gem
|
75
|
+
```
|
76
|
+
- Start Logstash and proceed to test the plugin
|
77
|
+
|
78
|
+
## Contributing
|
79
|
+
|
80
|
+
All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
|
81
|
+
|
82
|
+
Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
|
83
|
+
|
84
|
+
It is more important to the community that you are able to contribute.
|
85
|
+
|
86
|
+
For more information about contributing, see the [CONTRIBUTING](https://github.com/elasticsearch/logstash/blob/master/CONTRIBUTING.md) file.
|
data/README.md
CHANGED
@@ -5,14 +5,14 @@
|
|
5
5
|
[![Software License][ico-license]](LICENSE.md)
|
6
6
|
[![Build Status][ico-travis]][link-travis]
|
7
7
|
|
8
|
-
> Stream events from CloudWatch Logs
|
8
|
+
> Stream events from CloudWatch Logs.
|
9
9
|
|
10
10
|
### Purpose
|
11
|
-
Specify an individual log group, and this plugin will scan
|
11
|
+
Specify an individual log group or array of groups, and this plugin will scan
|
12
12
|
all log streams in that group, and pull in any new log events.
|
13
13
|
|
14
14
|
Optionally, you may set the `log_group_prefix` parameter to true
|
15
|
-
which will scan for all log groups matching the specified prefix
|
15
|
+
which will scan for all log groups matching the specified prefix(s)
|
16
16
|
and ingest all logs available in all of the matching groups.
|
17
17
|
|
18
18
|
## Usage
|
@@ -20,8 +20,9 @@ and ingest all logs available in all of the matching groups.
|
|
20
20
|
### Parameters
|
21
21
|
| Parameter | Input Type | Required | Default |
|
22
22
|
|-----------|------------|----------|---------|
|
23
|
-
| log_group |
|
23
|
+
| log_group | string or Array of strings | Yes | |
|
24
24
|
| log_group_prefix | boolean | No | `false` |
|
25
|
+
| start_position | `beginning`, `end`, or an Integer | No | `beginning` |
|
25
26
|
| sincedb_path | string | No | `$HOME/.sincedb*` |
|
26
27
|
| interval | number | No | 60 |
|
27
28
|
| aws_credentials_file | string | No | |
|
@@ -31,6 +32,18 @@ and ingest all logs available in all of the matching groups.
|
|
31
32
|
| region | string | No | `us-east-1` |
|
32
33
|
| codec | string | No | `plain` |
|
33
34
|
|
35
|
+
#### `start_position`
|
36
|
+
The `start_position` setting allows you to specify where to begin processing
|
37
|
+
a newly encountered log group on plugin boot. Whether the group is 'new' is
|
38
|
+
determined by whether or not the log group has a previously existing entry in
|
39
|
+
the sincedb file.
|
40
|
+
|
41
|
+
Valid options for `start_position` are:
|
42
|
+
* `beginning` - Reads from the beginning of the group (default)
|
43
|
+
* `end` - Sets the sincedb to now, and reads any new messages going forward
|
44
|
+
* Integer - Number of seconds in the past to begin reading at
|
45
|
+
|
46
|
+
#### Logstash Default config params
|
34
47
|
Other standard logstash parameters are available such as:
|
35
48
|
* `add_field`
|
36
49
|
* `type`
|
@@ -29,7 +29,7 @@ class LogStash::Inputs::CloudWatch_Logs < LogStash::Inputs::Base
|
|
29
29
|
|
30
30
|
# Log group(s) to use as an input. If `log_group_prefix` is set
|
31
31
|
# to `true`, then each member of the array is treated as a prefix
|
32
|
-
config :log_group, :validate => :string, :list => true
|
32
|
+
config :log_group, :validate => :string, :list => true
|
33
33
|
|
34
34
|
# Where to write the since database (keeps track of the date
|
35
35
|
# the last handled log stream was updated). The default will write
|
@@ -44,6 +44,12 @@ class LogStash::Inputs::CloudWatch_Logs < LogStash::Inputs::Base
|
|
44
44
|
# Decide if log_group is a prefix or an absolute name
|
45
45
|
config :log_group_prefix, :validate => :boolean, :default => false
|
46
46
|
|
47
|
+
# When a new log group is encountered at initial plugin start (not already in
|
48
|
+
# sincedb), allow configuration to specify where to begin ingestion on this group.
|
49
|
+
# Valid options are: `beginning`, `end`, or an integer, representing number of
|
50
|
+
# seconds before now to read back from.
|
51
|
+
config :start_position, :default => 'beginning'
|
52
|
+
|
47
53
|
|
48
54
|
# def register
|
49
55
|
public
|
@@ -53,6 +59,8 @@ class LogStash::Inputs::CloudWatch_Logs < LogStash::Inputs::Base
|
|
53
59
|
settings = defined?(LogStash::SETTINGS) ? LogStash::SETTINGS : nil
|
54
60
|
@sincedb = {}
|
55
61
|
|
62
|
+
check_start_position_validity
|
63
|
+
|
56
64
|
Aws::ConfigService::Client.new(aws_options_hash)
|
57
65
|
@cloudwatch = Aws::CloudWatchLogs::Client.new(aws_options_hash)
|
58
66
|
|
@@ -88,21 +96,33 @@ class LogStash::Inputs::CloudWatch_Logs < LogStash::Inputs::Base
|
|
88
96
|
|
89
97
|
end #def register
|
90
98
|
|
99
|
+
public
|
100
|
+
def check_start_position_validity
|
101
|
+
raise LogStash::ConfigurationError, "No start_position specified!" unless @start_position
|
102
|
+
|
103
|
+
return if @start_position =~ /^(beginning|end)$/
|
104
|
+
return if @start_position.is_a? Integer
|
105
|
+
|
106
|
+
raise LogStash::ConfigurationError, "start_position '#{@start_position}' is invalid! Must be `beginning`, `end`, or an integer."
|
107
|
+
end # def check_start_position_validity
|
108
|
+
|
91
109
|
# def run
|
92
110
|
public
|
93
111
|
def run(queue)
|
94
112
|
@queue = queue
|
95
113
|
_sincedb_open
|
114
|
+
determine_start_position(find_log_groups)
|
96
115
|
|
97
|
-
|
116
|
+
while !stop?
|
98
117
|
groups = find_log_groups
|
99
118
|
|
100
119
|
groups.each do |group|
|
101
120
|
@logger.debug("calling process_group on #{group}")
|
102
121
|
process_group(group)
|
103
122
|
end # groups.each
|
104
|
-
end
|
105
123
|
|
124
|
+
Stud.stoppable_sleep(@interval) { stop? }
|
125
|
+
end
|
106
126
|
end # def run
|
107
127
|
|
108
128
|
public
|
@@ -127,6 +147,24 @@ class LogStash::Inputs::CloudWatch_Logs < LogStash::Inputs::Base
|
|
127
147
|
groups
|
128
148
|
end # def find_log_groups
|
129
149
|
|
150
|
+
public
|
151
|
+
def determine_start_position(groups)
|
152
|
+
groups.each do |group|
|
153
|
+
if !@sincedb.member?(group)
|
154
|
+
case @start_position
|
155
|
+
when 'beginning'
|
156
|
+
@sincedb[group] = 0
|
157
|
+
|
158
|
+
when 'end'
|
159
|
+
@sincedb[group] = DateTime.now.strftime('%Q')
|
160
|
+
|
161
|
+
else
|
162
|
+
@sincedb[group] = DateTime.now.strftime('%Q') - (@start_position * 1000)
|
163
|
+
end # case @start_position
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end # def determine_start_position
|
167
|
+
|
130
168
|
private
|
131
169
|
def process_group(group)
|
132
170
|
next_token = nil
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-input-cloudwatch_logs'
|
4
|
-
s.version = '1.0.0.
|
4
|
+
s.version = '1.0.0.rc1'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = 'Stream events from CloudWatch Logs.'
|
7
7
|
s.description = 'This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program'
|
@@ -1,26 +1,97 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require
|
3
|
-
require
|
2
|
+
require 'logstash/devutils/rspec/spec_helper'
|
3
|
+
require 'logstash/inputs/cloudwatch_logs'
|
4
|
+
require 'aws-sdk-resources'
|
5
|
+
require 'aws-sdk'
|
4
6
|
|
5
7
|
describe LogStash::Inputs::CloudWatch_Logs do
|
8
|
+
let(:config) {
|
9
|
+
{
|
10
|
+
'access_key_id' => '1234',
|
11
|
+
'secret_access_key' => 'secret',
|
12
|
+
'log_group' => ['sample-log-group'],
|
13
|
+
'region' => 'us-east-1'
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
6
17
|
before do
|
7
18
|
Aws.config[:stub_responses] = true
|
8
19
|
Thread.abort_on_exception = true
|
9
20
|
end
|
10
21
|
|
22
|
+
|
23
|
+
context 'when interrupting the plugin' do
|
24
|
+
let(:config) {super.merge({'interval' => 5})}
|
25
|
+
|
26
|
+
before do
|
27
|
+
expect_any_instance_of(LogStash::Inputs::CloudWatch_Logs).to receive(:process_group).and_return(nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
it_behaves_like 'an interruptible input plugin'
|
31
|
+
end
|
32
|
+
|
11
33
|
describe '#register' do
|
12
|
-
|
13
|
-
{
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
34
|
+
context 'default config' do
|
35
|
+
subject {LogStash::Inputs::CloudWatch_Logs.new(config)}
|
36
|
+
|
37
|
+
it 'registers succesfully' do
|
38
|
+
expect {subject.register}.to_not raise_error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'start_position set to end' do
|
43
|
+
subject {LogStash::Inputs::CloudWatch_Logs.new(config.merge({'start_position' => 'end'}))}
|
44
|
+
|
45
|
+
it 'registers succesfully' do
|
46
|
+
expect {subject.register}.to_not raise_error
|
47
|
+
end
|
48
|
+
end
|
21
49
|
|
22
|
-
|
23
|
-
|
50
|
+
context 'start_position set to an integer' do
|
51
|
+
subject {LogStash::Inputs::CloudWatch_Logs.new(config.merge({'start_position' => 100}))}
|
52
|
+
|
53
|
+
it 'registers succesfully' do
|
54
|
+
expect {subject.register}.to_not raise_error
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'start_position invalid' do
|
59
|
+
subject {LogStash::Inputs::CloudWatch_Logs.new(config.merge({'start_position' => 'invalid start position'}))}
|
60
|
+
|
61
|
+
it 'raises a configuration error' do
|
62
|
+
expect {subject.register}.to raise_error(LogStash::ConfigurationError)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
describe '#find_log_groups without prefix true' do
|
69
|
+
context 'with an array in the config' do
|
70
|
+
subject {LogStash::Inputs::CloudWatch_Logs.new(config)}
|
71
|
+
|
72
|
+
it 'passes through configuration' do
|
73
|
+
expect(subject.find_log_groups).to eq(['sample-log-group'])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with a single string in the log_group' do
|
78
|
+
subject {LogStash::Inputs::CloudWatch_Logs.new(config.merge({'log_group' => 'sample-log-group-string'}))}
|
79
|
+
|
80
|
+
it 'array-ifies the single string' do
|
81
|
+
expect(subject.find_log_groups).to eq(['sample-log-group-string'])
|
82
|
+
end
|
24
83
|
end
|
25
84
|
end
|
85
|
+
|
86
|
+
# describe '#find_log_groups with prefix true' do
|
87
|
+
# subject {LogStash::Inputs::CloudWatch_Logs.new(config.merge({'log_group_prefix' => true}))}
|
88
|
+
#
|
89
|
+
# before(:each) {subject.register}
|
90
|
+
#
|
91
|
+
# it 'should create list of prefixes' do
|
92
|
+
# expect_any_instance_of(Aws::CloudWatchLogs::Resource).to receive(:describe_log_groups).and_return({'log_groups' => [{'log_group_name' => '1'},{'log_group_name' => '2'}]})
|
93
|
+
# expect(subject.find_log_groups).to eq(['sample-log-group-1', 'sample-log-group-2'])
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
|
26
97
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-cloudwatch_logs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Waite
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,7 @@ extra_rdoc_files: []
|
|
80
80
|
files:
|
81
81
|
- CHANGELOG.md
|
82
82
|
- CONTRIBUTORS
|
83
|
+
- DEVELOPER.md
|
83
84
|
- Gemfile
|
84
85
|
- LICENSE
|
85
86
|
- NOTICE.TXT
|