fluent-plugin-azureoms 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 460994a7573dbeb51cd3a9180b252bcb91df6d7f
4
- data.tar.gz: 1053d0974d92d5b07bd9c4a9a5c369bd2d5f1315
3
+ metadata.gz: 680cf704074eb4a3f28c32fcfcac08ff893542c7
4
+ data.tar.gz: eccc175af820a495c5246d9ad786153a8b5ffad5
5
5
  SHA512:
6
- metadata.gz: 16539bf9a26f62ce16e9b4ce2b809dfe2da9ec65637a83c245d6099d985d3aa4055244fe70942b37754074d970105f57b41db7adca5bdecff13521a893f95367
7
- data.tar.gz: '0635551900d0d5fbb003be834ebb78f3f0d8a1b151917c92cf0f40a18afaa4a29aa2658232ed2096aa5c3092ccc88e927737cd14dfcb255fd04c77906385c243'
6
+ metadata.gz: 795a8755ed33d412f8f1d59b88ea0ba4c2b955fe193c7980907665037576c23f184619410ee96ed50f8ef84af5994c26eeffc5e6e96061b7fa4c53c49333aff0
7
+ data.tar.gz: d680350bceff3c4d4060dee39660e3ff65458a805cc9b501999622d519a1ae9b7fd3e8038afcf02982a45fa0ab15079e22fa1a8a8d15d2eedc999d0946b905d3
@@ -0,0 +1 @@
1
+ pkg/
@@ -1,53 +1,51 @@
1
- PATH
2
- remote: .
3
- specs:
4
- fluent-plugin-azureoms (0.1.0)
5
- fluentd (>= 0.14.10, < 2)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- cool.io (1.5.3)
11
- cool.io (1.5.3-x64-mingw32)
12
- dig_rb (1.0.1)
13
- fluentd (1.1.2)
14
- cool.io (>= 1.4.5, < 2.0.0)
15
- dig_rb (~> 1.0.0)
16
- http_parser.rb (>= 0.5.1, < 0.7.0)
17
- msgpack (>= 0.7.0, < 2.0.0)
18
- serverengine (>= 2.0.4, < 3.0.0)
19
- sigdump (~> 0.2.2)
20
- strptime (>= 0.2.2, < 1.0.0)
21
- tzinfo (~> 1.0)
22
- tzinfo-data (~> 1.0)
23
- yajl-ruby (~> 1.0)
24
- http_parser.rb (0.6.0)
25
- msgpack (1.2.4)
26
- msgpack (1.2.4-x64-mingw32)
27
- power_assert (1.1.1)
28
- rake (12.3.1)
29
- serverengine (2.0.6)
30
- sigdump (~> 0.2.2)
31
- sigdump (0.2.4)
32
- strptime (0.2.3)
33
- test-unit (3.2.7)
34
- power_assert
35
- thread_safe (0.3.6)
36
- tzinfo (1.2.5)
37
- thread_safe (~> 0.1)
38
- tzinfo-data (1.2018.4)
39
- tzinfo (>= 1.0.0)
40
- yajl-ruby (1.3.1)
41
-
42
- PLATFORMS
43
- ruby
44
- x64-mingw32
45
-
46
- DEPENDENCIES
47
- bundler (~> 1.14)
48
- fluent-plugin-azureoms!
49
- rake (~> 12.0)
50
- test-unit (~> 3.0)
51
-
52
- BUNDLED WITH
53
- 1.16.1
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fluent-plugin-azureoms (0.2.0)
5
+ fluentd (>= 0.14.10, < 2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ cool.io (1.5.3)
11
+ dig_rb (1.0.1)
12
+ fluentd (1.1.2)
13
+ cool.io (>= 1.4.5, < 2.0.0)
14
+ dig_rb (~> 1.0.0)
15
+ http_parser.rb (>= 0.5.1, < 0.7.0)
16
+ msgpack (>= 0.7.0, < 2.0.0)
17
+ serverengine (>= 2.0.4, < 3.0.0)
18
+ sigdump (~> 0.2.2)
19
+ strptime (>= 0.2.2, < 1.0.0)
20
+ tzinfo (~> 1.0)
21
+ tzinfo-data (~> 1.0)
22
+ yajl-ruby (~> 1.0)
23
+ http_parser.rb (0.6.0)
24
+ msgpack (1.2.4)
25
+ power_assert (1.1.1)
26
+ rake (12.3.1)
27
+ serverengine (2.0.6)
28
+ sigdump (~> 0.2.2)
29
+ sigdump (0.2.4)
30
+ strptime (0.2.3)
31
+ test-unit (3.2.7)
32
+ power_assert
33
+ thread_safe (0.3.6)
34
+ tzinfo (1.2.5)
35
+ thread_safe (~> 0.1)
36
+ tzinfo-data (1.2018.4)
37
+ tzinfo (>= 1.0.0)
38
+ yajl-ruby (1.3.1)
39
+
40
+ PLATFORMS
41
+ ruby
42
+ x64-mingw32
43
+
44
+ DEPENDENCIES
45
+ bundler (~> 1.14)
46
+ fluent-plugin-azureoms!
47
+ rake (~> 12.0)
48
+ test-unit (~> 3.0)
49
+
50
+ BUNDLED WITH
51
+ 1.16.1
@@ -3,9 +3,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-azureoms"
6
- spec.version = "0.1.0"
6
+ spec.version = "0.2.0"
7
7
  spec.authors = ["Mark Simms"]
8
8
  spec.email = ["masimms@microsoft.com"]
9
+ #spec.git = "git://www.github.com/mabsimms/fluent-plugin-azureoms.git"
9
10
 
10
11
  spec.summary = "Fluentd output plugin for Azure Log Analytics"
11
12
  spec.description = "Fluentd output plugin for Azure Log Analytics"
@@ -1,144 +1,157 @@
1
- #
2
- # Copyright 2018- TODO: Write your name
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- require "fluent/plugin/output"
17
- require "time"
18
- require "base64"
19
- require "openssl"
20
- require "uri"
21
- require "net/https"
22
- require "json"
23
-
24
- module Fluent
25
- module Plugin
26
- class AzureomsOutput < Fluent::Plugin::Output
27
-
28
- helpers :event_emitter, :compat_parameters, :record_accessor
29
-
30
- Fluent::Plugin.register_output("azureoms", self)
31
-
32
- config_param :workspace, :string
33
- config_param :key, :string, secret: true
34
- config_param :timestamp_field, :string, default: "timestamp"
35
- config_param :log_name, :string, default: "AzureLog"
36
-
37
- def configure(conf)
38
- # This also calls config_param (don't access configuration parameters before
39
- # calling super)
40
- super
41
- end
42
-
43
- # This output plugin uses the raw HTTP data collector
44
- # API per https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-data-collector-api
45
-
46
- def prefer_buffered_processing
47
- true
48
- end
49
-
50
- def process(tag, es)
51
- print "Writing single record set (synchronous)\n"
52
- es.each do |time, record|
53
- # Convert record into a JSON body payload for OMS
54
- record[:timestamp] = Time.at(time).iso8601
55
-
56
- # Publish event
57
- send_data(workspace, key, record.to_json, log_name)
58
- end
59
- end
60
-
61
- # Synchronous buffered output
62
- def write(chunk)
63
- log.debug "Writing buffered record set (synchronous)"
64
- log.debug "writing data to file", chunk_id: dump_unique_id_hex(chunk.unique_id)
65
-
66
- elements = Array.new
67
-
68
- chunk.each do |time, record|
69
- log.debug "Writing record #{record.inspect}"
70
-
71
- # Fold the timestamp into the record
72
- record[:timestamp] = Time.at(time).iso8601
73
-
74
- # Append the record to the content in the appropriate format
75
- elements.push(record)
76
-
77
- # TODO - check size of content buffer and flush when it approaches
78
- # watermark
79
- if false
80
- log.debug "Elements buffer approaching max send size; flushing TODO"
81
- send_data(workspace, key, elements.to_json, log_name)
82
- elements.clear
83
- end
84
- end
85
-
86
- if elements.length > 0
87
- send_data(workspace, key, elements.to_json, log_name)
88
- end
89
- end
90
-
91
- def send_data(customer_id, shared_key, content, log_type)
92
- current_time = Time.now.utc
93
- signature = build_signature(
94
- shared_key, current_time, content.length,
95
- "POST", "application/json", "/api/logs")
96
- publish_data(log_name, signature, current_time, content)
97
- end
98
-
99
- def publish_data(log_name, signature, time, json)
100
- url = "https://#{workspace}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01"
101
- uri = URI url
102
-
103
- rfc1123date = time.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
104
-
105
- response = Net::HTTP.start(uri.hostname, uri.port,
106
- :use_ssl => uri.scheme == 'https') do |http|
107
-
108
- req = Net::HTTP::Post.new(uri.to_s)
109
- req.body = json.to_s
110
-
111
- # Signature and headers
112
- req['Content-Type'] = 'application/json'
113
- req['Log-Type'] = log_name
114
- req['Authorization'] = signature
115
- req['x-ms-date'] = rfc1123date
116
-
117
- log.debug "Publishing record of length #{req.body.length} to OMS workspace #{workspace}"
118
- http.request(req)
119
- end
120
-
121
- case response
122
- when Net::HTTPSuccess
123
- log.debug "Successfully published record of length #{json.length} to OMS workspace #{workspace}"
124
- else
125
- # TODO - throw error
126
- log.warn "Could not publish record of length #{json.length} to OMS workspace #{workspace} because #{response}"
127
- end
128
- response
129
- end
130
-
131
- def build_signature(shared_key, date, content_length, method, content_type, resource)
132
- rfc1123date = date.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
133
- string_to_hash = "#{method}\n#{content_length}\n#{content_type}\nx-ms-date:#{rfc1123date}\n#{resource}"
134
- decoded_key = Base64.decode64(shared_key)
135
- secure_hash = OpenSSL::HMAC.digest('SHA256', decoded_key, string_to_hash)
136
-
137
- encoded_hash = Base64.encode64(secure_hash).strip()
138
- authorization = "SharedKey #{workspace}:#{encoded_hash}"
139
-
140
- return authorization
141
- end
142
- end
143
- end
144
- end
1
+ #
2
+ # Copyright 2018- TODO: Write your name
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require "fluent/plugin/output"
17
+ require "time"
18
+ require "base64"
19
+ require "openssl"
20
+ require "uri"
21
+ require "net/https"
22
+ require "json"
23
+
24
+ module Fluent
25
+ module Plugin
26
+ class AzureomsOutput < Fluent::Plugin::Output
27
+
28
+ helpers :event_emitter, :compat_parameters, :record_accessor
29
+
30
+ Fluent::Plugin.register_output("azureoms", self)
31
+
32
+ DEFAULT_BUFFER_TYPE = "memory"
33
+
34
+ config_param :workspace, :string
35
+ config_param :key, :string, secret: true
36
+ config_param :timestamp_field, :string, default: "timestamp"
37
+
38
+ config_section :buffer do
39
+ config_set_default :@type, DEFAULT_BUFFER_TYPE
40
+ config_set_default :chunk_keys, ['tag']
41
+ config_set_default :timekey_use_utc, true
42
+ end
43
+
44
+ def configure(conf)
45
+ # This also calls config_param (don't access configuration parameters before
46
+ # calling super)
47
+ super
48
+
49
+ # Require chunking by tag keys
50
+ raise Fluent::ConfigError, "'tag' in chunk_keys is required." if not @chunk_key_tag
51
+ end
52
+
53
+ # This output plugin uses the raw HTTP data collector
54
+ # API per https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-data-collector-api
55
+
56
+ def prefer_buffered_processing
57
+ true
58
+ end
59
+
60
+ def process(tag, es)
61
+ print "Writing single record set (synchronous)\n"
62
+ es.each do |time, record|
63
+ # Convert record into a JSON body payload for OMS
64
+ record[:timestamp] = Time.at(time).iso8601
65
+
66
+ # Publish event
67
+ send_data(workspace, key, record.to_json, tag)
68
+ end
69
+ end
70
+
71
+ # Synchronous buffered output
72
+ def write(chunk)
73
+ log.debug "Writing buffered record set (synchronous)"
74
+ log.debug "writing data to file", chunk_id: dump_unique_id_hex(chunk.unique_id)
75
+ log.debug "writing data to log type", chunk.metadata.tag
76
+
77
+ tag = chunk.metadata.tag
78
+ elements = Array.new
79
+
80
+ chunk.each do |time, record|
81
+ log.debug "Writing record #{record.inspect}"
82
+
83
+ # Fold the timestamp into the record
84
+ record[:timestamp] = Time.at(time).iso8601
85
+
86
+ # Append the record to the content in the appropriate format
87
+ elements.push(record)
88
+
89
+ # TODO - check size of content buffer and flush when it approaches
90
+ # watermark
91
+ if false
92
+ log.debug "Elements buffer approaching max send size; flushing #{elements.length} to logname #{tag}"
93
+ send_data(workspace, key, elements.to_json, tag)
94
+ elements.clear
95
+ end
96
+ end
97
+
98
+ if elements.length > 0
99
+ log.debug "Flushing #{elements.length} to logname #{tag}"
100
+ send_data(workspace, key, elements.to_json, tag)
101
+ end
102
+ end
103
+
104
+ def send_data(customer_id, shared_key, content, log_name)
105
+ current_time = Time.now.utc
106
+ signature = build_signature(
107
+ shared_key, current_time, content.length,
108
+ "POST", "application/json", "/api/logs")
109
+ publish_data(log_name, signature, current_time, content)
110
+ end
111
+
112
+ def publish_data(log_name, signature, time, json)
113
+ url = "https://#{workspace}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01"
114
+ uri = URI url
115
+
116
+ rfc1123date = time.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
117
+
118
+ response = Net::HTTP.start(uri.hostname, uri.port,
119
+ :use_ssl => uri.scheme == 'https') do |http|
120
+
121
+ req = Net::HTTP::Post.new(uri.to_s)
122
+ req.body = json.to_s
123
+
124
+ # Signature and headers
125
+ req['Content-Type'] = 'application/json'
126
+ req['Log-Type'] = log_name
127
+ req['Authorization'] = signature
128
+ req['x-ms-date'] = rfc1123date
129
+
130
+ log.debug "Publishing record of length #{req.body.length} to OMS workspace #{workspace}"
131
+ http.request(req)
132
+ end
133
+
134
+ case response
135
+ when Net::HTTPSuccess
136
+ log.debug "Successfully published record of length #{json.length} to OMS workspace #{workspace}"
137
+ else
138
+ # TODO - throw error
139
+ log.warn "Could not publish record of length #{json.length} to OMS workspace #{workspace} because #{response}"
140
+ end
141
+ response
142
+ end
143
+
144
+ def build_signature(shared_key, date, content_length, method, content_type, resource)
145
+ rfc1123date = date.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
146
+ string_to_hash = "#{method}\n#{content_length}\n#{content_type}\nx-ms-date:#{rfc1123date}\n#{resource}"
147
+ decoded_key = Base64.decode64(shared_key)
148
+ secure_hash = OpenSSL::HMAC.digest('SHA256', decoded_key, string_to_hash)
149
+
150
+ encoded_hash = Base64.encode64(secure_hash).strip()
151
+ authorization = "SharedKey #{workspace}:#{encoded_hash}"
152
+
153
+ return authorization
154
+ end
155
+ end
156
+ end
157
+ end
@@ -8,15 +8,10 @@ require "pp"
8
8
 
9
9
  class AzureomsOutputTest < Test::Unit::TestCase
10
10
  include Fluent::Test::Helpers
11
-
12
11
 
13
12
  json_string = '[{"DemoField1":"DemoValue1","DemoField2":"DemoValue2"},{"DemoField3":"DemoValue3","DemoField4":"DemoValue4"}]'
14
13
  log_name = "DemoExample";
15
14
 
16
- hashed_string = '3oXy0IjaKA/V2/Kx+/BlXx7y6tvLYMM8/jwpWBO3c+c='
17
- signature = 'SharedKey 424b6a54-6de2-44b5-9768-04497fb2c7e6:1aHwzUHSJ6Ok4ExaKG3i7Opgzy/YqxcjqXH58rssu+I='
18
- time = Time::strptime("21-03-2018 00:12:10+00:00", "%d-%m-%Y %H:%M:%S%z")
19
-
20
15
  content_length = json_string.length
21
16
  method = "POST"
22
17
  content_type = "application/json"
data/testrun.sh CHANGED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-azureoms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Simms
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-27 00:00:00.000000000 Z
11
+ date: 2018-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,6 +79,7 @@ executables: []
79
79
  extensions: []
80
80
  extra_rdoc_files: []
81
81
  files:
82
+ - ".gitignore"
82
83
  - Gemfile
83
84
  - Gemfile.lock
84
85
  - LICENSE
@@ -111,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
112
  version: '0'
112
113
  requirements: []
113
114
  rubyforge_project:
114
- rubygems_version: 2.6.14
115
+ rubygems_version: 2.5.2.1
115
116
  signing_key:
116
117
  specification_version: 4
117
118
  summary: Fluentd output plugin for Azure Log Analytics