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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +51 -53
- data/fluent-plugin-azureoms.gemspec +2 -1
- data/lib/fluent/plugin/out_azureoms.rb +157 -144
- data/test/plugin/test_out_azureoms.rb +0 -5
- data/testrun.sh +0 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 680cf704074eb4a3f28c32fcfcac08ff893542c7
|
|
4
|
+
data.tar.gz: eccc175af820a495c5246d9ad786153a8b5ffad5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 795a8755ed33d412f8f1d59b88ea0ba4c2b955fe193c7980907665037576c23f184619410ee96ed50f8ef84af5994c26eeffc5e6e96061b7fa4c53c49333aff0
|
|
7
|
+
data.tar.gz: d680350bceff3c4d4060dee39660e3ff65458a805cc9b501999622d519a1ae9b7fd3e8038afcf02982a45fa0ab15079e22fa1a8a8d15d2eedc999d0946b905d3
|
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pkg/
|
data/Gemfile.lock
CHANGED
|
@@ -1,53 +1,51 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
fluent-plugin-azureoms (0.
|
|
5
|
-
fluentd (>= 0.14.10, < 2)
|
|
6
|
-
|
|
7
|
-
GEM
|
|
8
|
-
remote: https://rubygems.org/
|
|
9
|
-
specs:
|
|
10
|
-
cool.io (1.5.3)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
tzinfo (~> 1.0)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
tzinfo (1.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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.
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
config_param :
|
|
35
|
-
config_param :
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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.
|
|
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-
|
|
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.
|
|
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
|