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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1609b955d44c5cf6fb13e2ef341dce96fd7d79ec
4
- data.tar.gz: f4ce33514097bc7495097557fd263c384723e948
3
+ metadata.gz: f3c086f123d992aed90c4ca3f3f9e32561d8d14b
4
+ data.tar.gz: f8a299987d5ea86dac1aeccadb1061de883b21e1
5
5
  SHA512:
6
- metadata.gz: 8364a0350d31f9ab5b64bf4e4789eca9028d2c58092659f3129ee92e0132fd1b928693329e1fa379e1d0cc66f7858b2c142ac6842ea69a5f868f42680c69391a
7
- data.tar.gz: 999de5c022c9160bd252826921065463a0165703e9cfc83c32e9df2420980bad0e330ce60c2b23b8fe9934f3265ba2a610acd7173bdcd4287515656ca4dc84bf
6
+ metadata.gz: 2efff01f11400ad57da03596b97335c8b7c095e29d0b05b0b5d5abb5b50e277514962d6970bd2eced47f76493fd8dd7e2bb5d850da6e0e6b5d7049dce6c7b00b
7
+ data.tar.gz: 591d042bfdcbe403d64d1335f2911db0224797f5a70474ec4f748f68cd468de07080f556a9a14b0450b8f3aad97adb50c0046f91f47f2cb5a37d42221edaecd9
@@ -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
 
@@ -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 streams.
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 | array | Yes | |
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, :required => 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
- Stud.interval(@interval) do
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.pre.3'
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 "logstash/devutils/rspec/spec_helper"
3
- require "logstash/inputs/cloudwatch_logs"
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
- let(:config) {
13
- {
14
- 'access_key_id' => '1234',
15
- 'secret_access_key' => 'secret',
16
- 'log_group' => ['sample-log-group'],
17
- 'region' => 'us-east-1'
18
- }
19
- }
20
- subject {LogStash::Inputs::CloudWatch_Logs.new(config)}
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
- it "registers succesfully" do
23
- expect {subject.register}.to_not raise_error
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.pre.3
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-06-28 00:00:00.000000000 Z
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