logstash-output-clickhouse 0.1.1 → 0.1.3

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
  SHA256:
3
- metadata.gz: 1fbf922d44fe511cc743b7fd7c86ad3ea3de2ed8ed8afc3bbe549eb7dace1b03
4
- data.tar.gz: 6ead7854b8ef425526d9617a3e178c9ff7298eb57fac8f6a84b04c75e9873f08
3
+ metadata.gz: 05f2b2d96799587dc5678cd80a6ef5d0c62a103797a298dfbe86acb1dbe09b89
4
+ data.tar.gz: ffeb98ddb2e27497ff54e9304180a2a44e88d093ce33755f842409a2101d4153
5
5
  SHA512:
6
- metadata.gz: c5f5f85f5dc3e2f188cac06a78289e269d6b47a114fec1b2defd37fa343ce3af6cf1ace1a85d8fd5e323dd61866ad944ea2b5d45d6cea1f23f1c797997f24007
7
- data.tar.gz: 88e06fa018fc126c056cfc4a8c8c6237d5921d10449aa1878e506746f77cddc8b3db88dc73f34f5a631c7fd273ca95274a4fc44d348603514d123307f9150d22
6
+ metadata.gz: 1c6d244d35441f46a0b49b79d1f278004e634334349d3949ec8d49e96fb02e31c942d13f8be72e7ddcd9996687acf81f1378b3587cbab6c6a9a9f93eb6634a6a
7
+ data.tar.gz: 530b73e05f582bf9b9af8a3be95aa1139fd0b21c3a75b411635453fa9c5e4bc538f8fb8477ab2388fad2560570c92a3623d614c97e69f103850ef6e54d45a23a
data/README.md CHANGED
@@ -1,5 +1,3 @@
1
- # I switched to vector -> https://github.com/timberio/vector.
2
-
3
1
  # Logstash Plugin
4
2
 
5
3
  This plugin is a modified version of the Lucidworks logstash json_batch. That plugin is available [here](https://github.com/lucidworks/logstash-output-json_batch).
@@ -19,6 +17,9 @@ Please note that the name of the plugin when used is `clickhouse`, it only suppo
19
17
  "to1" => "from1"
20
18
  "to2" => [ "from2", "(.)(.)", '\1\2' ]
21
19
  }
20
+ extra_params => {
21
+ "date_time_input_format" => "best_effort"
22
+ }
22
23
  }
23
24
  }
24
25
 
@@ -28,6 +29,7 @@ Please note that the name of the plugin when used is `clickhouse`, it only suppo
28
29
  * `automatic_retries` (default: 1) - number of connect retry attempts to each host in `http_hosts`
29
30
  * `request_tolerance` (default: 5) - number of http request send retry attempts if response status code is not 200
30
31
  * `backoff_time` (default: 3) - time to wait in seconds for next retry attempt of connect or request
32
+ * `extra_params` (default: {}) - extra parameters to be passed to the clickhouse http client
31
33
 
32
34
  Default batch size is 50, with a wait of at most 5 seconds per send. These can be tweaked with the parameters `flush_size` and `idle_flush_time` respectively.
33
35
 
@@ -8,7 +8,6 @@ require "stud/buffer"
8
8
  require "logstash/plugin_mixins/http_client"
9
9
  require "securerandom"
10
10
 
11
-
12
11
  class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
13
12
  include LogStash::PluginMixins::HttpClient
14
13
  include Stud::Buffer
@@ -20,7 +19,7 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
20
19
  config :http_hosts, :validate => :array, :required => true
21
20
 
22
21
  config :table, :validate => :string, :required => true
23
-
22
+
24
23
  # Custom headers to use
25
24
  # format is `headers => ["X-My-Header", "%{host}"]`
26
25
  config :headers, :validate => :hash
@@ -38,7 +37,7 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
38
37
  config :save_file, :validate => :string, :default => "failed.json"
39
38
 
40
39
  config :request_tolerance, :validate => :number, :default => 5
41
-
40
+
42
41
  config :backoff_time, :validate => :number, :default => 3
43
42
 
44
43
  config :automatic_retries, :validate => :number, :default => 3
@@ -47,19 +46,21 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
47
46
 
48
47
  config :host_resolve_ttl_sec, :validate => :number, :default => 120
49
48
 
49
+ config :extra_params, :validate => :hash, :default => {}
50
+
50
51
  def print_plugin_info()
51
- @@plugins = Gem::Specification.find_all{|spec| spec.name =~ /logstash-output-clickhouse/ }
52
+ @@plugins = Gem::Specification.find_all { |spec| spec.name =~ /logstash-output-clickhouse/ }
52
53
  @plugin_name = @@plugins[0].name
53
54
  @plugin_version = @@plugins[0].version
54
55
  @logger.info("Running #{@plugin_name} version #{@plugin_version}")
55
56
 
56
57
  @logger.info("Initialized clickhouse with settings",
57
- :flush_size => @flush_size,
58
- :idle_flush_time => @idle_flush_time,
59
- :request_tokens => @pool_max,
60
- :http_hosts => @http_hosts,
61
- :http_query => @http_query,
62
- :headers => request_headers)
58
+ :flush_size => @flush_size,
59
+ :idle_flush_time => @idle_flush_time,
60
+ :request_tokens => @pool_max,
61
+ :http_hosts => @http_hosts,
62
+ :http_query => @http_query,
63
+ :headers => request_headers)
63
64
  end
64
65
 
65
66
  def register
@@ -71,18 +72,20 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
71
72
  # When this queue is empty no new requests may be sent,
72
73
  # tokens must be added back by the client on success
73
74
  @request_tokens = SizedQueue.new(@pool_max)
74
- @pool_max.times {|t| @request_tokens << true }
75
+ @pool_max.times { |t| @request_tokens << true }
75
76
  @requests = Array.new
76
- @http_query = "/?query=INSERT%20INTO%20#{table}%20FORMAT%20JSONEachRow"
77
+
78
+ params = { "query" => "INSERT INTO #{table} FORMAT JSONEachRow" }.merge(@extra_params)
79
+ @http_query = "?#{URI.encode_www_form(params)}"
77
80
 
78
81
  @hostnames_pool =
79
82
  parse_http_hosts(http_hosts,
80
- ShortNameResolver.new(ttl: @host_resolve_ttl_sec, logger: @logger))
83
+ ShortNameResolver.new(ttl: @host_resolve_ttl_sec, logger: @logger))
81
84
 
82
85
  buffer_initialize(
83
86
  :max_items => @flush_size,
84
87
  :max_interval => @idle_flush_time,
85
- :logger => @logger
88
+ :logger => @logger,
86
89
  )
87
90
 
88
91
  print_plugin_info()
@@ -117,7 +120,7 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
117
120
  begin
118
121
  @hostnames_pool.call
119
122
  rescue Exception => ex
120
- @logger.error('Error while resolving host', :error => ex.to_s)
123
+ @logger.error("Error while resolving host", :error => ex.to_s)
121
124
  end
122
125
  end
123
126
 
@@ -126,33 +129,34 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
126
129
  buffer_receive(event)
127
130
  end
128
131
 
129
- def mutate( src )
132
+ def mutate(src)
130
133
  return src if @mutations.empty?
131
134
  res = {}
132
135
  @mutations.each_pair do |dstkey, source|
133
136
  case source
134
- when String then
135
- scrkey = source
136
- next unless src.key?(scrkey)
137
-
138
- res[dstkey] = src[scrkey]
139
- when Array then
140
- scrkey = source[0]
141
- next unless src.key?(scrkey)
142
- pattern = source[1]
143
- replace = source[2]
144
- res[dstkey] = src[scrkey].sub( Regexp.new(pattern), replace )
137
+ when String
138
+ scrkey = source
139
+ next unless src.key?(scrkey)
140
+
141
+ res[dstkey] = src[scrkey]
142
+ when Array
143
+ scrkey = source[0]
144
+ next unless src.key?(scrkey)
145
+ pattern = source[1]
146
+ replace = source[2]
147
+ res[dstkey] = src[scrkey].sub(Regexp.new(pattern), replace)
145
148
  end
146
149
  end
147
150
  res
148
151
  end
149
152
 
150
153
  public
151
- def flush(events, close=false)
154
+
155
+ def flush(events, close = false)
152
156
  documents = "" #this is the string of hashes that we push to Fusion as documents
153
157
 
154
158
  events.each do |event|
155
- documents << LogStash::Json.dump( mutate( event.to_hash() ) ) << "\n"
159
+ documents << LogStash::Json.dump(mutate(event.to_hash())) << "\n"
156
160
  end
157
161
 
158
162
  hosts = get_host_addresses()
@@ -165,10 +169,10 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
165
169
  def save_to_disk(documents)
166
170
  begin
167
171
  file = File.open("#{save_dir}/#{table}_#{save_file}", "a")
168
- file.write(documents)
172
+ file.write(documents)
169
173
  rescue IOError => e
170
174
  log_failure("An error occurred while saving file to disk: #{e}",
171
- :file_name => file_name)
175
+ :file_name => file_name)
172
176
  ensure
173
177
  file.close unless file.nil?
174
178
  end
@@ -177,21 +181,20 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
177
181
  def delay_attempt(attempt_number, delay)
178
182
  # sleep delay grows roughly as k*x*ln(x) where k is the initial delay set in @backoff_time param
179
183
  attempt = [attempt_number, 1].max
180
- timeout = lambda { |x| [delay*x*Math.log(x), 1].max }
184
+ timeout = lambda { |x| [delay * x * Math.log(x), 1].max }
181
185
  # using rand() to pick final sleep delay to reduce the risk of getting in sync with other clients writing to the DB
182
- sleep_time = rand(timeout.call(attempt)..timeout.call(attempt+1))
186
+ sleep_time = rand(timeout.call(attempt)..timeout.call(attempt + 1))
183
187
  sleep sleep_time
184
188
  end
185
189
 
186
190
  private
187
191
 
188
192
  def make_request(documents, hosts, query, con_count = 1, req_count = 1, host = "", uuid = SecureRandom.hex)
189
-
190
193
  if host == ""
191
194
  host = hosts.pop
192
195
  end
193
196
 
194
- url = host+query
197
+ url = host + query
195
198
 
196
199
  # Block waiting for a token
197
200
  #@logger.info("Requesting token ", :tokens => request_tokens.length())
@@ -210,25 +213,26 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
210
213
  @request_tokens << token
211
214
 
212
215
  if response.code == 200
213
- @logger.debug("Successfully submitted",
214
- :size => documents.length,
215
- :response_code => response.code,
216
- :uuid => uuid)
216
+ @logger.debug("Successfully submitted",
217
+ :size => documents.length,
218
+ :response_code => response.code,
219
+ :uuid => uuid)
217
220
  else
218
221
  if req_count >= @request_tolerance
219
222
  log_failure(
220
- "Encountered non-200 HTTP code #{response.code}",
221
- :response_code => response.code,
222
- :url => url,
223
- :size => documents.length,
224
- :uuid => uuid)
223
+ "Encountered non-200 HTTP code #{response.code}",
224
+ :response_code => response.code,
225
+ :url => url,
226
+ :size => documents.length,
227
+ :uuid => uuid,
228
+ )
225
229
  if @save_on_failure
226
230
  save_to_disk(documents)
227
231
  end
228
232
  else
229
233
  @logger.info("Retrying request", :url => url, :message => response.message, :response => response.body, :uuid => uuid)
230
234
  delay_attempt(req_count, @backoff_time)
231
- make_request(documents, hosts, query, con_count, req_count+1, host, uuid)
235
+ make_request(documents, hosts, query, con_count, req_count + 1, host, uuid)
232
236
  end
233
237
  end
234
238
  end
@@ -238,21 +242,21 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
238
242
  @request_tokens << token
239
243
 
240
244
  if hosts.length == 0
241
- log_failure("Could not access URL",
242
- :url => url,
243
- :method => @http_method,
244
- :headers => headers,
245
- :message => exception.message,
246
- :class => exception.class.name,
247
- :backtrace => exception.backtrace,
248
- :size => documents.length,
249
- :uuid => uuid)
250
- if @save_on_failure
251
- save_to_disk(documents)
252
- end
253
- return
245
+ log_failure("Could not access URL",
246
+ :url => url,
247
+ :method => @http_method,
248
+ :headers => headers,
249
+ :message => exception.message,
250
+ :class => exception.class.name,
251
+ :backtrace => exception.backtrace,
252
+ :size => documents.length,
253
+ :uuid => uuid)
254
+ if @save_on_failure
255
+ save_to_disk(documents)
256
+ end
257
+ return
254
258
  end
255
-
259
+
256
260
  if con_count >= @automatic_retries
257
261
  host = ""
258
262
  con_count = 0
@@ -260,7 +264,7 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
260
264
 
261
265
  @logger.info("Retrying connection", :url => url, :uuid => uuid)
262
266
  delay_attempt(con_count, @backoff_time)
263
- make_request(documents, hosts, query, con_count+1, req_count, host, uuid)
267
+ make_request(documents, hosts, query, con_count + 1, req_count, host, uuid)
264
268
  end
265
269
 
266
270
  client.execute!
@@ -276,5 +280,4 @@ class LogStash::Outputs::ClickHouse < LogStash::Outputs::Base
276
280
  headers["Content-Type"] ||= "application/json"
277
281
  headers
278
282
  end
279
-
280
283
  end
@@ -1,16 +1,16 @@
1
1
  Gem::Specification.new do |s|
2
- s.name = 'logstash-output-clickhouse'
3
- s.version = '0.1.1'
4
- s.licenses = ['Apache-2.0']
5
- s.summary = "This output lets you `POST` messages as JSON in a batched fashion to ClickHouse HTTP endpoint"
6
- 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"
7
- s.authors = ["kmajk"]
8
- s.email = 'k.majk@getresponse.com'
9
- s.homepage = "http://getresponse.com"
2
+ s.name = "logstash-output-clickhouse"
3
+ s.version = "0.1.3"
4
+ s.licenses = ["Apache-2.0"]
5
+ s.summary = "This output lets you `POST` messages as JSON in a batched fashion to ClickHouse HTTP endpoint"
6
+ 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"
7
+ s.authors = ["kmajk", "maltoze"]
8
+ s.email = "atonezzz@gmail.com"
9
+ s.homepage = "https://github.com/maltoze/logstash-output-clickhouse"
10
10
  s.require_paths = ["lib"]
11
11
 
12
12
  # Files
13
- s.files = Dir['lib/**/*','spec/**/*','*.gemspec','*.md','Gemfile','LICENSE' ]
13
+ s.files = Dir["lib/**/*", "spec/**/*", "*.gemspec", "*.md", "Gemfile", "LICENSE"]
14
14
 
15
15
  # Tests
16
16
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
@@ -20,10 +20,10 @@ Gem::Specification.new do |s|
20
20
 
21
21
  # Gem dependencies
22
22
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
23
- s.add_runtime_dependency "logstash-mixin-http_client", ">= 6.0.0", "<= 7.0.0"
24
- s.add_runtime_dependency 'mini_cache', ">= 1.0.0", "< 2.0.0"
23
+ s.add_runtime_dependency "logstash-mixin-http_client", ">= 6.0.0", "< 8.0.0"
24
+ s.add_runtime_dependency "mini_cache", ">= 1.0.0", "< 2.0.0"
25
25
 
26
- s.add_development_dependency 'logstash-devutils'
27
- s.add_development_dependency 'sinatra'
28
- s.add_development_dependency 'webrick'
26
+ s.add_development_dependency "logstash-devutils"
27
+ s.add_development_dependency "sinatra"
28
+ s.add_development_dependency "webrick"
29
29
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-clickhouse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - kmajk
8
+ - maltoze
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2021-08-04 00:00:00.000000000 Z
12
+ date: 2022-07-15 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: logstash-core-plugin-api
@@ -37,9 +38,9 @@ dependencies:
37
38
  - - ">="
38
39
  - !ruby/object:Gem::Version
39
40
  version: 6.0.0
40
- - - "<="
41
+ - - "<"
41
42
  - !ruby/object:Gem::Version
42
- version: 7.0.0
43
+ version: 8.0.0
43
44
  type: :runtime
44
45
  prerelease: false
45
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -47,9 +48,9 @@ dependencies:
47
48
  - - ">="
48
49
  - !ruby/object:Gem::Version
49
50
  version: 6.0.0
50
- - - "<="
51
+ - - "<"
51
52
  - !ruby/object:Gem::Version
52
- version: 7.0.0
53
+ version: 8.0.0
53
54
  - !ruby/object:Gem::Dependency
54
55
  name: mini_cache
55
56
  requirement: !ruby/object:Gem::Requirement
@@ -115,7 +116,7 @@ dependencies:
115
116
  description: This gem is a logstash plugin required to be installed on top of the
116
117
  Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not
117
118
  a stand-alone program
118
- email: k.majk@getresponse.com
119
+ email: atonezzz@gmail.com
119
120
  executables: []
120
121
  extensions: []
121
122
  extra_rdoc_files: []
@@ -126,7 +127,7 @@ files:
126
127
  - lib/logstash/outputs/clickhouse.rb
127
128
  - lib/logstash/util/shortname_resolver.rb
128
129
  - logstash-output-clickhouse.gemspec
129
- homepage: http://getresponse.com
130
+ homepage: https://github.com/maltoze/logstash-output-clickhouse
130
131
  licenses:
131
132
  - Apache-2.0
132
133
  metadata: