fluent-plugin-azurestorage 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 173125873d3f72fb76b104b180df63b23472c02d
4
+ data.tar.gz: 4895ded3228acfb7c5e3e6458f9cc081c0ce69da
5
+ SHA512:
6
+ metadata.gz: 87d07b8903865caccf0e90833cbbc5edf9fb4ac81bcf453e526d9b3555a0c92af0aff6abee645abdab4789ecdd98ede4cfcaddc0c53e1b0eadb6c905f71585e8
7
+ data.tar.gz: 12b97072aa1633a683b7061212f6ac7a7c3c30c5374f9068edac973ab4972cbb086f4397c58e35a95d2dbf26ff20febd883f8ec0d91d8e181505c1a296fb17c7
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-azurestorage.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Hidemasa Togashi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # Azure Storage output plugin for Fluentd
2
+
3
+ ## Overview
4
+
5
+ Azure Storate output plugin buffers logs in local file and upload them to Azure Storage periodically.
6
+ This plugin is porting from [fluent-plugin-s3](https://github.com/fluent/fluent-plugin-s3) for AzureStorage.
7
+
8
+ ## Installation
9
+
10
+ Install from RubyGems:
11
+ ```
12
+ $ gem install fluent-plugin-azurestorage
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ ```
18
+ <match pattern>
19
+ type azurestorage
20
+
21
+ azure_storage_account <your azure storage account>
22
+ azure_storage_access_key <your azure storage access key>
23
+ azure_container <your azure storage container>
24
+ azure_storage_type blob
25
+ store_as gzip
26
+ auto_create_container true
27
+ path logs/
28
+ azure_object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
29
+ buffer_path /var/log/fluent/azurestorage
30
+
31
+ time_slice_format %Y%m%d-%H
32
+ time_slice_wait 10m
33
+ utc
34
+ </match>
35
+ ```
36
+
37
+ ### azure_storage_account
38
+
39
+ Your Azure Storage Account Name. This can be got from Azure Management potal.
40
+ This parameter is required when environment variable 'AZURE_STORAGE_ACCOUNT' is not set.
41
+
42
+ ### azure_storage_access_key
43
+
44
+ Your Azure Storage Access Key(Primary or Secondary). This also can be got from Azure Management potal.
45
+ This parameter is required when environment variable 'AZURE_STORAGE_ACCESS_KEY' is not set.
46
+
47
+ ### azure_container (Required)
48
+
49
+ Azure Storage Container name
50
+
51
+ ### auto_create_container
52
+
53
+ This plugin create container if not exist when you set 'auto_create_container' to true.
54
+
55
+ ### azure_storage_type
56
+
57
+ Azure Storage type. Now supports only 'blob'(default). 'tables' and 'queues' are not implemented.
58
+
59
+ ### azure_object_key_format
60
+
61
+ The format of Azure Storage object keys. You can use several built-in variables:
62
+
63
+ - %{path}
64
+ - %{time_slice}
65
+ - %{index}
66
+ - %{file_extension}
67
+
68
+ to decide keys dynamically.
69
+
70
+ %{path} is exactly the value of *path* configured in the configuration file. E.g., "logs/" in the example configuration above.
71
+ %{time_slice} is the time-slice in text that are formatted with *time_slice_format*.
72
+ %{index} is the sequential number starts from 0, increments when multiple files are uploaded to Azure Storage in the same time slice.
73
+ %{file_extention} is always "gz" for now.
74
+
75
+ The default format is "%{path}%{time_slice}_%{index}.%{file_extension}".
76
+
77
+ For instance, using the example configuration above, actual object keys on Azure Storage will be something like:
78
+
79
+ ```
80
+ "logs/20130111-22_0.gz"
81
+ "logs/20130111-23_0.gz"
82
+ "logs/20130111-23_1.gz"
83
+ "logs/20130112-00_0.gz"
84
+ ```
85
+
86
+ With the configuration:
87
+
88
+ ```
89
+ azure_object_key_format %{path}/events/ts=%{time_slice}/events_%{index}.%{file_extension}
90
+ path log
91
+ time_slice_format %Y%m%d-%H
92
+ ```
93
+
94
+ You get:
95
+
96
+ ```
97
+ "log/events/ts=20130111-22/events_0.gz"
98
+ "log/events/ts=20130111-23/events_0.gz"
99
+ "log/events/ts=20130111-23/events_1.gz"
100
+ "log/events/ts=20130112-00/events_0.gz"
101
+ ```
102
+
103
+ The [fluent-mixin-config-placeholders](https://github.com/tagomoris/fluent-mixin-config-placeholders) mixin is also incorporated, so additional variables such as %{hostname}, %{uuid}, etc. can be used in the azure_object_key_format. This could prove useful in preventing filename conflicts when writing from multiple servers.
104
+
105
+ ```
106
+ azure_object_key_format %{path}/events/ts=%{time_slice}/events_%{index}-%{hostname}.%{file_extension}
107
+ ```
108
+
109
+ ### store_as
110
+
111
+ Archive format on Azure Storage. You can use following types:
112
+
113
+ - gzip (default)
114
+ - json
115
+ - text
116
+ - lzo (Need lzop command)
117
+ - lzma2 (Need xz command)
118
+
119
+ ### format
120
+
121
+ Change one line format in the Azure Storage object. Supported formats are 'out_file', 'json', 'ltsv' and 'single_value'.
122
+
123
+ - out_file (default)
124
+
125
+ ```
126
+ time\ttag\t{..json1..}
127
+ time\ttag\t{..json2..}
128
+ ...
129
+ ```
130
+
131
+ - json
132
+
133
+ ```
134
+ {..json1..}
135
+ {..json2..}
136
+ ...
137
+ ```
138
+
139
+ At this format, "time" and "tag" are omitted.
140
+ But you can set these information to the record by setting "include_tag_key" / "tag_key" and "include_time_key" / "time_key" option.
141
+ If you set following configuration in AzureStorage output:
142
+
143
+ ```
144
+ format json
145
+ include_time_key true
146
+ time_key log_time # default is time
147
+ ```
148
+
149
+ then the record has log_time field.
150
+
151
+ ```
152
+ {"log_time":"time string",...}
153
+ ```
154
+
155
+ - ltsv
156
+
157
+ ```
158
+ key1:value1\tkey2:value2
159
+ key1:value1\tkey2:value2
160
+ ...
161
+ ```
162
+
163
+ "ltsv" format also accepts "include_xxx" related options. See "json" section.
164
+
165
+ - single_value
166
+
167
+ Use specified value instead of entire recode. If you get '{"message":"my log"}', then contents are
168
+
169
+ ```
170
+ my log1
171
+ my log2
172
+ ...
173
+ ```
174
+
175
+ You can change key name by "message_key" option.
176
+
177
+ ### path
178
+
179
+ path prefix of the files on Azure Storage. Default is "" (no prefix).
180
+
181
+ ### buffer_path (required)
182
+
183
+ path prefix of the files to buffer logs.
184
+
185
+ ### time_slice_format
186
+
187
+ Format of the time used as the file name. Default is '%Y%m%d'. Use '%Y%m%d%H' to split files hourly.
188
+
189
+ ### time_slice_wait
190
+
191
+ The time to wait old logs. Default is 10 minutes. Specify larger value if old logs may reache.
192
+
193
+ ### utc
194
+
195
+ Use UTC instead of local time.
196
+
197
+ ## License
198
+ Azure Storage output plugin is licensed according to the terms of the Apache License, Version 2.0.
199
+
200
+ The full version of this lisence can be found at http://www.apache.org/licenses/LICENSE-2.0 [TXT](http://www.apache.org/licenses/LICENSE-2.0.txt) or [HTML](http://www.apache.org/licenses/LICENSE-2.0.html)
201
+
202
+ ## Contributing
203
+
204
+ 1. Fork it
205
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
206
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
207
+ 4. Push to the branch (`git push origin my-new-feature`)
208
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ #lib = File.expand_path('../lib', __FILE__)
3
+ #$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-azurestorage"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Hidemasa Togashi"]
9
+ spec.email = ["togachiro@gmail.com"]
10
+ spec.description = %q{Fluent plugin for store to Azure Storage}
11
+ spec.summary = %q{Fluent plugin for store to Azure Storage}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+
23
+ spec.add_runtime_dependency "fluentd"
24
+ spec.add_runtime_dependency "azure"
25
+ end
@@ -0,0 +1,162 @@
1
+ module Fluent
2
+ require 'fluent/mixin/config_placeholders'
3
+
4
+ class AzureStorageOutput < Fluent::TimeSlicedOutput
5
+ Fluent::Plugin.register_output('azurestorage', self)
6
+
7
+ def initialize
8
+ super
9
+ require 'azure'
10
+ require 'zlib'
11
+ require 'time'
12
+ require 'tempfile'
13
+ require 'open3'
14
+ end
15
+
16
+ config_param :path, :string, :default => ''
17
+ config_param :azure_storage_account, :string, :default => nil
18
+ config_param :azure_storage_access_key, :string, :default => nil
19
+ config_param :azure_container, :string, :default => nil
20
+ config_param :azure_storage_type, :string, :default => 'blob'
21
+ config_param :azure_object_key_format, :string, :default => "%{path}%{time_slice}_%{index}.%{file_extension}"
22
+ config_param :store_as, :string, :default => 'gzip'
23
+ config_param :auto_create_container, :bool, :default => true
24
+ config_param :format, :string, :default => 'out_file'
25
+ config_param :command_parameter, :string, :default => nil
26
+
27
+ include Fluent::Mixin::ConfigPlaceholders
28
+
29
+ def configure(conf)
30
+ super
31
+
32
+ @ext = case @store_as
33
+ when 'gzip'
34
+ 'gz'
35
+ when 'lzo'
36
+ check_command('lzop', 'LZO')
37
+ @command_parameter = '-qf1' if @command_parameter.nil?
38
+ 'lzo'
39
+ when 'lzma2'
40
+ check_command('xz', 'LZMA2')
41
+ @command_paramter = '-qf0' if @command_parameter.nil?
42
+ 'xz'
43
+ when 'json'
44
+ 'json'
45
+ else
46
+ 'txt'
47
+ end
48
+
49
+ @storage_type = case @azure_storage_type
50
+ when 'tables'
51
+ raise NotImplementedError
52
+ when 'queues'
53
+ raise NotImplementedError
54
+ else
55
+ 'blob'
56
+ end
57
+
58
+ conf['format'] = @format
59
+ @formatter = TextFormatter.create(conf)
60
+
61
+ if @localtime
62
+ @path_slicer = Proc.new {|path|
63
+ Time.now.strftime(path)
64
+ }
65
+ else
66
+ @path_slicer = Proc.new {|path|
67
+ Time.now.utc.strftime(path)
68
+ }
69
+ end
70
+
71
+ if @azure_container.nil?
72
+ raise ConfigError, 'azure_container is needed'
73
+ end
74
+ end
75
+
76
+ def start
77
+ super
78
+
79
+ if (!@azure_storage_account.nil? && !@azure_storage_access_key)
80
+ Azure.configure do |config|
81
+ config.storage_account_name = @azure_storage_account
82
+ config.storage_access_key = @azure_storage_access_key
83
+ end
84
+ end
85
+ @bs = Azure::BlobService.new
86
+
87
+ ensure_container
88
+ end
89
+
90
+ def format(tag, time, record)
91
+ @formatter.format(tag, time, record)
92
+ end
93
+
94
+ def write(chunk)
95
+ blob_list = @bs.list_blobs(@azure_container)
96
+ i = 0
97
+ begin
98
+ path = @path_slicer.call(@path)
99
+ values_for_object_key = {
100
+ 'path' => path,
101
+ 'time_slice' => chunk.key,
102
+ 'file_extension' => @ext,
103
+ 'index' => i
104
+ }
105
+ storage_path = @azure_object_key_format.gsub(%r(%{[^}]+})) { |expr|
106
+ values_for_object_key[expr[2...expr.size-1]]
107
+ }
108
+ i += 1
109
+ end while blob_list.find { |elem| elem.name == storage_path }
110
+
111
+ tmp = Tempfile.new("azure-")
112
+ begin
113
+ case @store_as
114
+ when 'gzip'
115
+ w = Zlib::GzipWriter.new(tmp)
116
+ chunk.write_to(w)
117
+ w.close
118
+ when 'lzo'
119
+ w = Tempfile.new('chunk-tmp')
120
+ chunk.write_to(w)
121
+ w.close
122
+ tmp.close
123
+ system "lzop #{@command_parameter} -o #{tmp.path} #{w.path}"
124
+ when 'lzma2'
125
+ w = Tempfile.new('chunk-xz-tmp')
126
+ chunk.write_to(w)
127
+ w.close
128
+ tmp.close
129
+ system "xz #{@command_parameter} -c #{w.path} > #{tmp.path}"
130
+ else
131
+ chunk.write_to(tmp)
132
+ tmp.close
133
+ end
134
+ content = File.open(tmp.path, 'rb') { |file| file.read }
135
+ @bs.create_block_blob(@azure_container, storage_path, content)
136
+ ensure
137
+ tmp.close(true) rescue nil
138
+ w.close rescue nil
139
+ w.unlink rescue nil
140
+ end
141
+ end
142
+
143
+ private
144
+ def ensure_container
145
+ if ! @bs.list_containers.find { |c| c.name == @azure_container }
146
+ if @auto_create_container
147
+ @bs.create_container(@azure_container)
148
+ else
149
+ raise "The specified container does not exist: container = #{@azure_container}"
150
+ end
151
+ end
152
+ end
153
+
154
+ def check_command(command, algo)
155
+ begin
156
+ Open3.capture3("#{command} -V")
157
+ rescue Errno::ENOENT
158
+ raise ConfigError, "'#{command}' utility must be in PATH for #{algo} compression"
159
+ end
160
+ end
161
+ end
162
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-azurestorage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Hidemasa Togashi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fluentd
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: azure
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Fluent plugin for store to Azure Storage
70
+ email:
71
+ - togachiro@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - fluent-plugin-azurestorage.gemspec
82
+ - lib/fluent/plugin/out_azurestorage.rb
83
+ homepage: ''
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.0.14
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Fluent plugin for store to Azure Storage
107
+ test_files: []