fluent-plugin-wendelin 0.1 → 0.5

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.
data/README.md CHANGED
@@ -12,7 +12,7 @@ Configuration
12
12
 
13
13
  A sample configuration to setup ingestion of data for a tag to Wendelin:
14
14
 
15
- ```apache
15
+ ```
16
16
  <match your.sensor.tag>
17
17
  @type wendelin
18
18
  @id wendelin_out
@@ -20,6 +20,7 @@ A sample configuration to setup ingestion of data for a tag to Wendelin:
20
20
  streamtool_uri <Wendelin_URL>/erp5/portal_ingestion_policies/<YOUR_INGESTION_POLICY_ID>
21
21
  user <your_wendelin_user>
22
22
  password <your_wendelin_password>
23
+ use_keep_alive <true or false>
23
24
 
24
25
  # all parameters of BufferedOutput & Output classes are supported too, e.g.
25
26
  # `buffer_type`, `flush_interval`, `num_threads`, `log_level`, etc - see
@@ -43,7 +44,6 @@ See *example/to_wendelin.conf* for fully setup example.
43
44
  TODO
44
45
  ----
45
46
 
46
- - make content to be posted over HTTP as raw (instead of urlencode data).
47
47
  - HTTPS certificates are currently not verified.
48
48
  - X.509 certificates instead of user / password.
49
49
  - cleanup
@@ -1,14 +1,5 @@
1
1
  # Example configuration of Wendelin output for Fluentd
2
2
 
3
- ## built-in TCP input, so we can accept messages from other fluentd(s) and so
4
- ## that fluent-cat works:
5
- ## $ echo <json|msgpack> | fluent-cat <tag>
6
- <source>
7
- @type forward
8
- @id forward_input
9
- </source>
10
-
11
-
12
3
  # HTTP input
13
4
  # http://localhost:8888/<tag>?json=<json>
14
5
  <source>
@@ -17,74 +8,28 @@
17
8
  port 8888
18
9
  </source>
19
10
 
20
-
21
- ## output tag=sensor.** to Wendelin
22
- <match <YOUR_SENSOR_TAG>.**>
23
- @type wendelin
11
+ # This will match all HTTP request like so
12
+ # ivan@debian: ~$ curl -X POST -d 'json={"foo1":"bar1"}' http://localhost:8888/test_sensor.test_product
13
+ # then send to Wendelin and append as MsgPack encoded string at Wendelin side
14
+ <match test_sensor.test_product.**>
15
+ @type wendelin
24
16
  @id wendelin_out
25
-
26
- streamtool_uri <Wendelin_URL>/erp5/portal_ingestion_policies/<YOUR_INGESTION_POLICY_ID>
27
- # TODO ^^^ do not check peer's certificate
28
- user <your_wendelin_user>
29
- password <your_wendelin_password>
30
-
31
- # all parameters of BufferedOutput & Output classes are supported too, e.g.
32
- # `buffer_type`, `flush_interval`, `num_threads`, `log_level`, etc - see
33
- # their code near:
34
- #
35
- # https://github.com/fluent/fluentd/blob/master/lib/fluent/output.rb#L182
36
- #
37
- # logging setup description:
38
- #
39
- # http://docs.fluentd.org/articles/logging
40
-
17
+ streamtool_uri <Wendelin_URL>/erp5/portal_ingestion_policies/default
18
+ user <your_wendelin_user>
19
+ password <your_wendelin_password>
20
+ use_keep_alive true
41
21
  buffer_type memory
42
- #buffer_path "#{ENV['HOME']/var}"
43
22
  flush_interval 5s
44
23
  </match>
45
24
 
46
-
47
-
48
-
49
- # ---- monitoring & debugging ----
50
-
51
-
52
- # Listen HTTP for monitoring
53
- # http://localhost:24220/api/plugins
54
- # http://localhost:24220/api/plugins?type=TYPE
55
- # http://localhost:24220/api/plugins?tag=MYTAG
56
- <source>
57
- @type monitor_agent
58
- @id monitor_agent_input
59
-
60
- port 24220
61
- </source>
62
-
63
- # Listen DRb for debug
64
- <source>
65
- @type debug_agent
66
- @id debug_agent_input
67
-
68
- bind 127.0.0.1
69
- port 24230
70
- </source>
71
-
72
-
73
- ## match tag=debug.** and dump to console
74
- <match debug.**>
75
- @type stdout
76
- @id stdout_output
77
- </match>
78
-
79
-
80
- ## match fluent's internal events
81
- #<match fluent.**>
82
- # @type null
83
- #</match>
84
-
85
- ## match not matched logs and write to file
86
- #<match **>
87
- # @type file
88
- # path /var/log/fluent/else
89
- # compress gz
90
- #</match>
25
+ # Example: tailing existing file and send its contents to Wendelin
26
+ # Uncomment below to enable
27
+ #<source>
28
+ # @type tail
29
+ # path test.log
30
+ # pos_file test.log.pos
31
+ # tag test_sensor.test_product
32
+ # <parse>
33
+ # @type none
34
+ # </parse>
35
+ #</source>
@@ -1,17 +1,17 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "fluent-plugin-wendelin"
3
- gem.version = "0.1"
4
- gem.authors = ["Kirill Smelkov"]
5
- gem.email = ["kirr@nexedi.com"]
3
+ gem.version = "0.5"
4
+ gem.authors = ["Nexedians"]
5
+ gem.email = ["klaus@nexedi.com"]
6
6
  gem.summary = %q{Fluentd output to Wendelin}
7
7
  gem.description = %q{Fluentd output plugin to forward data to Wendelin system}
8
8
  gem.homepage = "https://lab.nexedi.com/nexedi/fluent-plugin-wendelin"
9
- gem.license = "APLv2"
9
+ gem.license = "GPLv3+ with wide exception for Open-Source"
10
10
 
11
11
  gem.files = `git ls-files -z`.split("\x0")
12
12
  gem.require_paths = ["lib"]
13
13
 
14
- gem.add_runtime_dependency "fluentd", "~> 0"
14
+ gem.add_runtime_dependency "fluentd", "< 2"
15
15
  # ? net/http
16
16
  # ? openssl
17
17
  end
@@ -2,31 +2,35 @@
2
2
  # Copyright (C) 2015 Nexedi SA and Contributors.
3
3
  # Kirill Smelkov <kirr@nexedi.com>
4
4
  #
5
- # This program is free software: you can Use, Study, Modify and Redistribute
6
- # it under the terms of the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
5
+ # This program is free software: you can Use, Study, Modify and Redistribute
6
+ # it under the terms of the GNU General Public License version 3, or (at your
7
+ # option) any later version, as published by the Free Software Foundation.
9
8
  #
10
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # You can also Link and Combine this program with other software covered by
10
+ # the terms of any of the Free Software licenses or any of the Open Source
11
+ # Initiative approved licenses and Convey the resulting work. Corresponding
12
+ # source of such a combination shall include the source code for all other
13
+ # software used.
11
14
  #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
15
+ # This program is distributed WITHOUT ANY WARRANTY; without even the implied
16
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
+ #
18
+ # See COPYING file for full licensing terms.
19
+ # See https://www.nexedi.com/licensing for rationale and options.
20
+
17
21
 
18
22
 
19
23
  # This plugin hooks into Fluentd in a way similiar to out_forward and
20
24
  # out_secure_forward and outputs event stream to a Wendelin HTTP endpoint.
21
25
 
22
- require 'fluent/output'
26
+ require 'fluent/plugin/output'
23
27
  require_relative 'wendelin_client'
24
28
 
25
29
 
26
- module Fluent
30
+ module Fluent::Plugin
27
31
 
28
- class WendelinOutput < ObjectBufferedOutput # XXX verify base class
29
- Plugin.register_output('wendelin', self)
32
+ class WendelinOutput < Output
33
+ Fluent::Plugin.register_output('wendelin', self)
30
34
 
31
35
  # where Wendelin's Input Stream Tool is located,
32
36
  # ex http://example.com/erp5/portal_ingestion_policies/example_ingestion
@@ -38,16 +42,32 @@ module Fluent
38
42
  config_param :user, :string, :default => nil
39
43
  config_param :password, :string, :default => nil
40
44
 
41
-
45
+ config_param :use_keep_alive, :bool, :default => false
46
+
47
+ config_param :ssl_timeout, :integer, :default => 60
48
+ config_param :open_timeout, :integer, :default => 60
49
+ config_param :read_timeout, :integer, :default => 60
50
+ config_param :keep_alive_timeout, :integer, :default => 300
51
+
52
+ config_section :buffer do
53
+ config_set_default :chunk_keys, ["tag"]
54
+ end
55
+
42
56
  def configure(conf)
43
57
  super
58
+
59
+ unless @chunk_key_tag
60
+ raise Fluent::ConfigError, "buffer chunk key must include 'tag' for wendelin output"
61
+ end
44
62
 
45
63
  credentials = {}
46
64
  if @user
47
65
  credentials['user'] = @user
48
66
  credentials['password'] = @password
49
67
  end
50
- @wendelin = WendelinClient.new(@streamtool_uri, credentials)
68
+ @wendelin = WendelinClient.new(@streamtool_uri, credentials, @log,
69
+ @ssl_timeout, @open_timeout,
70
+ @read_timeout, @keep_alive_timeout)
51
71
  end
52
72
 
53
73
  def start
@@ -60,12 +80,11 @@ module Fluent
60
80
  # TODO
61
81
  end
62
82
 
63
-
64
- # hooked to ObjectBufferedOutput - write out records from a buffer chunk for a tag.
83
+ # Use normal "Synchronous Buffer" - write out records from a buffer chunk for a tag.
65
84
  #
66
- # NOTE this is called from a separate thread (see OutputThread and BufferedOutput)
67
- def write_objects(tag, chunk)
68
- # NOTE if this fail and raises -> it will unroll to BufferedOutput#try_flush
85
+ def write(chunk)
86
+ return if chunk.empty?
87
+ # NOTE if this fail and raises -> it will unroll to Output#try_flush
69
88
  # which detects errors and retries outputting logs up to retry maxcount
70
89
  # times and aborts outputting current logs if all try fail.
71
90
  #
@@ -78,9 +97,13 @@ module Fluent
78
97
 
79
98
  # for input_stream_ref use tag as-is - it will be processed/translated
80
99
  # further on server by Wendelin
81
- reference = tag
100
+ reference = chunk.metadata.tag
82
101
 
83
- @wendelin.ingest(reference, data_chunk)
102
+ if @use_keep_alive
103
+ @wendelin.ingest_with_keep_alive(reference, data_chunk)
104
+ else
105
+ @wendelin.ingest(reference, data_chunk)
106
+ end
84
107
  end
85
108
 
86
109
  end
@@ -0,0 +1,57 @@
1
+ # Fluentd output plugin to ingest data to Wendelin system
2
+ # Copyright (C) 2015 Nexedi SA and Contributors.
3
+ # Kirill Smelkov <kirr@nexedi.com>
4
+ #
5
+ # This program is free software: you can Use, Study, Modify and Redistribute
6
+ # it under the terms of the GNU General Public License version 3, or (at your
7
+ # option) any later version, as published by the Free Software Foundation.
8
+ #
9
+ # You can also Link and Combine this program with other software covered by
10
+ # the terms of any of the Free Software licenses or any of the Open Source
11
+ # Initiative approved licenses and Convey the resulting work. Corresponding
12
+ # source of such a combination shall include the source code for all other
13
+ # software used.
14
+ #
15
+ # This program is distributed WITHOUT ANY WARRANTY; without even the implied
16
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
+ #
18
+ # See COPYING file for full licensing terms.
19
+ # See https://www.nexedi.com/licensing for rationale and options.
20
+
21
+ # This plugin hooks into Fluentd in a way similiar to out_forward and
22
+ # out_secure_forward and outputs event stream to a Wendelin HTTP endpoint.
23
+
24
+ require 'fluent/plugin/formatter'
25
+ require_relative 'out_wendelin'
26
+
27
+
28
+ module Fluent::Plugin
29
+ class WendelinOutputFormatted < WendelinOutput
30
+ Fluent::Plugin.register_output('wendelin_formatted', self)
31
+
32
+ helpers :formatter
33
+
34
+ config_section :format do
35
+ config_set_default :@type, 'single_value'
36
+ end
37
+
38
+ def configure(conf)
39
+ super
40
+ @formatter = formatter_create
41
+ end
42
+
43
+ def formatted_to_msgpack_binary?
44
+ @formatter_configs.first[:@type] == 'msgpack'
45
+ end
46
+
47
+ def format(tag, time, record)
48
+ @formatter.format(tag, time, record)
49
+ end
50
+
51
+ def write(chunk)
52
+ super
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -2,97 +2,190 @@
2
2
  # Copyright (C) 2015 Nexedi SA and Contributors.
3
3
  # Kirill Smelkov <kirr@nexedi.com>
4
4
  #
5
- # This program is free software: you can Use, Study, Modify and Redistribute
6
- # it under the terms of the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
5
+ # This program is free software: you can Use, Study, Modify and Redistribute
6
+ # it under the terms of the GNU General Public License version 3, or (at your
7
+ # option) any later version, as published by the Free Software Foundation.
9
8
  #
10
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # You can also Link and Combine this program with other software covered by
10
+ # the terms of any of the Free Software licenses or any of the Open Source
11
+ # Initiative approved licenses and Convey the resulting work. Corresponding
12
+ # source of such a combination shall include the source code for all other
13
+ # software used.
11
14
  #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
-
15
+ # This program is distributed WITHOUT ANY WARRANTY; without even the implied
16
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
+ #
18
+ # See COPYING file for full licensing terms.
19
+ # See https://www.nexedi.com/licensing for rationale and options.
18
20
 
19
21
  require 'net/http'
20
22
  require 'openssl'
21
23
 
22
- # show request/response traces or not
23
- $trace = false
24
-
25
-
26
24
  # class representing a Wendelin client
27
25
  class WendelinClient
28
26
 
29
27
  # `streamtool_uri` - URI pointing to portal_input_data_stream "mountpoint"
30
28
  # `credentials` # {'user' => _, 'password' => _} TODO change to certificate
31
- def initialize(streamtool_uri, credentials)
32
- @streamtool_uri = streamtool_uri
33
- @credentials = credentials
29
+ # `log` - logger to use
30
+ def initialize(streamtool_uri, credentials, log,
31
+ ssl_timeout, open_timeout, read_timeout, keep_alive_timeout)
32
+ @streamtool_uri = streamtool_uri
33
+ @credentials = credentials
34
+ @log = log
35
+ @ssl_timeout = ssl_timeout
36
+ @open_timeout = open_timeout
37
+ @read_timeout = read_timeout
38
+ @keep_alive_timeout = keep_alive_timeout
34
39
  end
35
40
 
36
41
 
42
+ # start request in an independent function to keep the connection open
43
+ def start_connection(uri)
44
+
45
+ @log.debug "start new connection"
46
+
47
+ @http = Net::HTTP.start(uri.hostname, uri.port,
48
+ :use_ssl => (uri.scheme == 'https'),
49
+ :verify_mode => OpenSSL::SSL::VERIFY_NONE,
50
+
51
+ # Net::HTTP default open timeout is infinity, which results
52
+ # in thread hang forever if other side does not fully
53
+ # establish connection. Default read_timeout is 60 seconds.
54
+ # We go safe way and make sure all timeouts are defined.
55
+ :ssl_timeout => @ssl_timeout,
56
+ :open_timeout => @open_timeout,
57
+ :read_timeout => @read_timeout,
58
+ :keep_alive_timeout => @keep_alive_timeout,)
59
+ end
60
+
37
61
  # ingest `data_chunk` to a stream referenced as `reference`
38
- def ingest(reference, data_chunk)
39
- uri = URI("#{@streamtool_uri}/ingest?reference=#{reference}")
40
- req = Net::HTTP::Post.new(uri)
41
- if @credentials.has_key?('user')
42
- req.basic_auth @credentials['user'], @credentials['password']
43
- end
44
-
45
- # TODO ensure content-type is 'raw', e.g. this way
46
- # (but then querystring ?reference=... is lost)
47
- # req.body = data_chunk
48
- # req.content_type = 'application/octet-stream'
49
- req.set_form_data('data_chunk' => data_chunk)
50
-
51
- if $trace
52
- puts '>>> REQUEST'
53
- puts "method\t=> #{req.method}"
54
- puts "path\t=> #{req.path}"
55
- puts "uri\t=> #{req.uri}"
56
- puts "body\t=> #{req.body}"
57
- puts "body_stream\t=> #{req.body_stream}"
58
- req.each {|h| puts "#{h}:\t#{req[h]}"}
59
- puts
60
- end
61
-
62
- begin
63
- # TODO keep connection open (so that every new ingest does not do
64
- # full connect again)
65
- res = Net::HTTP.start(uri.hostname, uri.port,
66
- :use_ssl => (uri.scheme == 'https'),
67
- # NOTE = "do not check server cert"
68
- # TODO move this out to conf parameters
69
- :verify_mode => OpenSSL::SSL::VERIFY_NONE
70
- ) do |http|
71
- http.request(req)
72
- end
73
-
74
- rescue
75
- # some http/ssl/other connection error
76
- puts "HTTP ERROR:"
77
- raise
78
-
79
- else
80
- if $trace
81
- puts '>>> RESPONSE'
82
- res.each {|h| puts "#{h}:\t#{res[h]}"}
83
- puts "code\t=> #{res.code}"
84
- puts "msg\t=> #{res.message}"
85
- puts "class\t=> #{res.class}"
86
- puts "body:", res.body
87
- end
88
-
89
- if res.kind_of?(Net::HTTPSuccess) # res.code is 2XX
90
- #puts "ingested ok"
91
- else
92
- puts "FAIL:"
93
- res.value
94
- end
95
- end
62
+ def ingest_with_keep_alive(reference, data_chunk)
63
+ uri = URI("#{@streamtool_uri}/ingest?reference=#{reference}")
64
+ # call start_connection if http is undefined
65
+ if ! defined? @http
66
+ start_connection(uri)
67
+ end
68
+
69
+ # connect again if the connection is not started
70
+ if ! @http.started?()
71
+ start_connection(uri)
72
+ end
73
+
74
+ @request = Net::HTTP::Post.new(uri)
75
+
76
+ # When using 'application/x-www-form-urlencoded', Ruby encodes with regex
77
+ # and it is far too slow. Such POST is legit:
78
+ # https://stackoverflow.com/a/14710450
79
+ @request.body = data_chunk
80
+ @request.content_type = 'application/octet-stream'
81
+
82
+ if @credentials.has_key?('user')
83
+ @request.basic_auth @credentials['user'], @credentials['password']
84
+ end
85
+
86
+ @log.on_trace do
87
+ @log.trace '>>> REQUEST'
88
+ @log.trace "method\t=> #{@request.method}"
89
+ @log.trace "path\t=> #{@request.path}"
90
+ @log.trace "uri\t=> #{@request.uri}"
91
+ @log.trace "body\t=> #{@request.body}"
92
+ @log.trace "body_stream\t=> #{@request.body_stream}"
93
+ @request.each {|h| @log.trace "#{h}:\t#{@request[h]}"}
94
+ @log.trace
95
+ end
96
+
97
+ begin
98
+ res = @http.request(@request) # Net::HTTPResponse object
99
+ end
100
+
101
+ rescue
102
+ # some http/ssl/other connection error
103
+ @log.warn "HTTP ERROR:"
104
+ raise
105
+ else
106
+ @log.on_trace do
107
+ @log.trace '>>> RESPONSE'
108
+ res.each {|h| @log.trace "#{h}:\t#{res[h]}"}
109
+ @log.trace "code\t=> #{res.code}"
110
+ @log.trace "msg\t=> #{res.message}"
111
+ @log.trace "class\t=> #{res.class}"
112
+ @log.trace "body:", res.body
113
+ end
114
+
115
+ if res.kind_of?(Net::HTTPSuccess) # res.code is 2XX
116
+ #@log.info "ingested ok"
117
+ else
118
+ @log.warn "FAIL:"
119
+ res.value
120
+ end
96
121
  end
97
122
 
123
+ def ingest(reference, data_chunk)
124
+ uri = URI("#{@streamtool_uri}/ingest?reference=#{reference}")
125
+ req = Net::HTTP::Post.new(uri)
126
+ if @credentials.has_key?('user')
127
+ req.basic_auth @credentials['user'], @credentials['password']
128
+ end
129
+
130
+ # When using 'application/x-www-form-urlencoded', Ruby encodes with regex
131
+ # and it is far too slow. Such POST is legit:
132
+ # https://stackoverflow.com/a/14710450
133
+ req.body = data_chunk
134
+ req.content_type = 'application/octet-stream'
135
+
136
+ @log.on_trace do
137
+ @log.trace '>>> REQUEST'
138
+ @log.trace "method\t=> #{req.method}"
139
+ @log.trace "path\t=> #{req.path}"
140
+ @log.trace "uri\t=> #{req.uri}"
141
+ @log.trace "body\t=> #{req.body}"
142
+ @log.trace "body_stream\t=> #{req.body_stream}"
143
+ req.each {|h| @log.trace "#{h}:\t#{req[h]}"}
144
+ @log.trace
145
+ end
146
+
147
+ begin
148
+ # TODO keep connection open (so that every new ingest does not do
149
+ # full connect again)
150
+ res = Net::HTTP.start(uri.hostname, uri.port,
151
+ :use_ssl => (uri.scheme == 'https'),
152
+ # NOTE = "do not check server cert"
153
+ # TODO move this out to conf parameters
154
+ :verify_mode => OpenSSL::SSL::VERIFY_NONE,
155
+
156
+ # Net::HTTP default open timeout is infinity, which results
157
+ # in thread hang forever if other side does not fully
158
+ # establish connection. Default read_timeout is 60 seconds.
159
+ # We go safe way and make sure all timeouts are defined.
160
+ :ssl_timeout => @ssl_timeout,
161
+ :open_timeout => @open_timeout,
162
+ :read_timeout => @read_timeout,
163
+ ) do |http|
164
+ http.request(req)
165
+ end
166
+
167
+ rescue
168
+ # some http/ssl/other connection error
169
+ @log.warn "HTTP ERROR:"
170
+ raise
171
+
172
+ else
173
+ @log.on_trace do
174
+ @log.trace '>>> RESPONSE'
175
+ res.each {|h| @log.trace "#{h}:\t#{res[h]}"}
176
+ @log.trace "code\t=> #{res.code}"
177
+ @log.trace "msg\t=> #{res.message}"
178
+ @log.trace "class\t=> #{res.class}"
179
+ @log.trace "body:", res.body
180
+ end
181
+
182
+ if res.kind_of?(Net::HTTPSuccess) # res.code is 2XX
183
+ #@log.info "ingested ok"
184
+ else
185
+ @log.warn "FAIL:"
186
+ res.value
187
+ end
188
+ end
189
+ end
190
+
98
191
  end
@@ -5,6 +5,10 @@
5
5
  here = File.dirname(__FILE__)
6
6
  $LOAD_PATH << File.expand_path(File.join(here, '../lib'))
7
7
  require 'fluent/plugin/wendelin_client'
8
+ require 'fluent/log'
9
+ require 'fluent/engine' # for log
10
+
11
+ log = Fluent::Log.new(out=STDERR, level=Fluent::Log::LEVEL_TRACE)
8
12
 
9
13
  # FIXME hardcoded
10
14
  $user = 'user'
@@ -14,7 +18,7 @@ $password = 'password'
14
18
  $erp5 = "https://example.com/erp5" # erp5 root
15
19
  $streamtool = "#{$erp5}/portal_input_data_streams" # where Input Stream Tool is mounted
16
20
 
17
- $wendelin = WendelinClient.new($streamtool, {'user' => $user, 'password' => $password})
21
+ $wendelin = WendelinClient.new($streamtool, {'user' => $user, 'password' => $password}, log)
18
22
 
19
23
 
20
24
  def ingest(input_stream_ref, data_chunk)