logstash-output-thinkingdata 0.1.1 → 1.0.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
  SHA256:
3
- metadata.gz: c02a307fd4272626a3066db6f4d924767fa058dbb889477583d19db2b195b9e3
4
- data.tar.gz: e019db8cd60d9fd6625d6a16391f2bcd899c88082442d6004579b3213fc8e7e4
3
+ metadata.gz: 6859f106a23f8b6f24120c2d51905b7b09e0c9b713235319b0c71f60c105325b
4
+ data.tar.gz: 50fe28c3a55a3029473afbe70ba115d0e38aa7b17da1c3acacd3572b6e4915a9
5
5
  SHA512:
6
- metadata.gz: f990de3bab4004e223ad6f9691ec22f217f51ed711d617036fd14527ddc73a4fa353da3aae9713a95533006cb0793aba44aa9b999d57acc9369da7e590c2dc70
7
- data.tar.gz: 92787899f34fc00787ec28130b91013a8197e5ba22534a6958a0fec36c602ef5dd5a816c9f6744818cf8f9ddb941c89c2cd9b087f8efa0ed713dd39f6552d077
6
+ metadata.gz: dda99ed3e2c10d2c7b86e09e71b01f1074609829791d8cb1b8fd42daf54c173cb72d3f644b007b7592d3652e8068cfd2cc6179ff25f80909c1bec292a68462e1
7
+ data.tar.gz: 3fe885fd3bcd52ef37442d52fbbe37a6b37835d80101f0afb179ecd1b3034e50834436f45dfe6248d5d7b4b511fda4e6b6ee4bdf95d6519641008361c35ce722
@@ -1,2 +1,6 @@
1
+ **v1.0.0** (2020-06-09)
2
+ - 接收Logstash中event传递的message发送到TA中
3
+ - filebeat 日志打印支持
4
+
1
5
  **v0.1.1** (2020-04-27)
2
6
  - thinkingdata output plugin created with the logstash plugin generator
@@ -28,12 +28,22 @@ class LogStash::Outputs::Thinkingdata < LogStash::Outputs::Base
28
28
  config :flush_interval_sec, :validate => :number, :default => 2
29
29
 
30
30
  # 批次flush 最大 content 数量
31
- config :flush_batch_size, :validate => :number, :default => 100
31
+ config :flush_batch_size, :validate => :number, :default => 500
32
32
 
33
33
  # 是否压缩数据 0:不压缩,1:gzip压缩
34
34
  config :compress, :validate => :number, :default => 1
35
35
 
36
- PLUGIN_VERSION = "0.1.1"
36
+ #是否开启uuid
37
+ config :uuid, :validate => :boolean, :default => false
38
+
39
+
40
+ # 开启 filebeat 状态记录
41
+ config :is_filebeat_status_record, :validate => :boolean, :default => true
42
+
43
+ # 是否检测appid
44
+ config :appid_check, :validate => :boolean, :default => false
45
+
46
+ PLUGIN_VERSION = "1.0.0"
37
47
 
38
48
  public
39
49
  def register
@@ -42,24 +52,38 @@ class LogStash::Outputs::Thinkingdata < LogStash::Outputs::Base
42
52
  :appid => @appid,
43
53
  :flush_interval_sec => @flush_interval_sec,
44
54
  :flush_batch_size => @flush_batch_size,
45
- :compress =>@compress
55
+ :compress =>@compress,
56
+ :uuid => @uuid,
57
+ :is_filebeat_status_record => @is_filebeat_status_record,
58
+ :appid_check => @appid_check
46
59
  )
47
60
 
48
61
  http_client_config = client_config
49
62
  http_client_config[:user_agent] = "thinkingdata_logstash_output_plugin_" + PLUGIN_VERSION
50
63
  @client = Manticore::Client.new(http_client_config)
51
- appid_check
64
+ ta_appid_check if @appid_check
65
+ @receive_count = 0
66
+ @parse_error_count = 0
67
+ @last_report_count = 0
68
+ @total_send_count = 0
52
69
  buffer_config = {
53
70
  :max_items => @flush_batch_size.to_i,
54
71
  :max_interval => @flush_interval_sec.to_i,
55
72
  :logger => @logger
56
73
  }
57
74
  buffer_initialize(buffer_config)
75
+ @filebeat_status = {} if @is_filebeat_status_record
76
+ @report_thread = Thread.new do
77
+ loop do
78
+ sleep 60
79
+ report
80
+ end
81
+ end
58
82
  end # def register
59
83
 
60
84
  #验证appid
61
- public
62
- def appid_check
85
+ private
86
+ def ta_appid_check
63
87
  @server_uri = URI(@url)
64
88
  @server_uri.path = "/check_appid"
65
89
  @server_uri.query= "appid="+@appid
@@ -74,26 +98,39 @@ class LogStash::Outputs::Thinkingdata < LogStash::Outputs::Base
74
98
  public
75
99
  def multi_receive(events)
76
100
  return if events.empty?
77
-
78
- events.each do |e|
101
+ @receive_count += events.length
102
+ events.each do |event|
79
103
  begin
80
- content = JSON.parse(e.get("message"))
104
+ content = LogStash::Json.load(event.get("message"))
105
+ content['#uuid'] = SecureRandom.uuid if @uuid
106
+ if is_filebeat_input?(event) #filebeat input 记录
107
+ host = event.get("[host][name]")
108
+ file = event.get("[log][file][path]")
109
+ file = event.get("[source]")if file.nil?
110
+ offset = event.get("[log][offset]")
111
+ offset = event.get("[offset]") if offset.nil?
112
+ log_detail = "host: #{host}, file: #{file}"
113
+ record_filebeat_status(log_detail, offset) if @is_filebeat_status_record
114
+ end
81
115
  buffer_receive(content)
82
- rescue
83
- @logger.error("Could not process content", :content => e.to_s)
116
+ rescue => e
117
+ @logger.error("Could not process content", :content => event.to_s, :Exception => e)
118
+ @parse_error_count += 1
84
119
  end
85
120
  end
86
- # return "Event received"
87
121
  end # def event
88
122
 
89
123
  public
90
124
  def close
125
+ buffer_state[:timer].kill
91
126
  buffer_flush(:final => true)
92
- client.close
127
+ @report_thread.kill
128
+ @client.close
129
+ report
93
130
  end
94
131
 
95
132
  public
96
- def flush(events, final = false)
133
+ def flush(events, final)
97
134
  if @compress == 0
98
135
  data = events.to_json
99
136
  compress_type = 'none'
@@ -108,14 +145,71 @@ class LogStash::Outputs::Thinkingdata < LogStash::Outputs::Base
108
145
  end
109
146
  headers ={'appid' => @appid,'version'=>PLUGIN_VERSION,'user-agent' =>'logstash_'+ PLUGIN_VERSION,
110
147
  'compress' => compress_type}
111
- response = client.post(@url, :body => data,:headers =>headers).call
112
- result = JSON.parse(response.body)
113
- if response.code != 200
114
- @logger.warn("Send failed, code: #{response.code}, body: #{response.body}")
115
- raise
148
+ until do_send(data,headers)
149
+ sleep 5
150
+ end
151
+ @total_send_count += events.length
152
+ end
153
+
154
+ private
155
+ def do_send(data, headers)
156
+ begin
157
+ response = @client.post(@url, :body => data,:headers =>headers).call
158
+ if response.code != 200
159
+ @logger.error("Send failed, code: #{response.code}, body: #{response.body}",:url => @url)
160
+ return false
161
+ end
162
+ rescue => e
163
+ @logger.error("Send failed",:url => @url, :exception => e.class.name, :backtrace => e.backtrace)
164
+ return false
116
165
  end
117
- if result['code'] != 0
118
- @logger.error(" Send failed data:" , :failData => events.to_json,:responseBody => response.body)
166
+ true
167
+ end
168
+
169
+ private
170
+ def is_filebeat_input?(event)
171
+ type = event.get("[agent][type]")
172
+ return true if !type.nil? && type == "filebeat"
173
+ type = event.get("[@metadata][beat]")
174
+ return true if !type.nil? && type == "filebeat"
175
+ type = event.get("[beat]")
176
+ return true unless type.nil?
177
+ false
178
+ end
179
+
180
+ private
181
+ def record_filebeat_status(log_detail, offset)
182
+ status = @filebeat_status[log_detail]
183
+ if status.nil?
184
+ status = {:receive_time => Time.now, :offset => offset}
185
+ @filebeat_status[log_detail] = status
186
+ else
187
+ status[:offset] = offset
188
+ status[:receive_time] = Time.now
119
189
  end
120
190
  end
191
+
192
+ private
193
+ def report
194
+ interval_count = @total_send_count - @last_report_count
195
+ @last_report_count = @total_send_count
196
+ @logger.info("Report",
197
+ "IntervalReceive(records):" => interval_count,
198
+ "Receive(records):" => @receive_count,
199
+ "TotalSend(records)" => @total_send_count,
200
+ "ParseError(records)" => @parse_error_count)
201
+ @logger.info("Filebeat Status Report: #{format_filebeat_report}") if @is_filebeat_status_record && @filebeat_status !={}
202
+ end
203
+
204
+ private
205
+
206
+ def format_filebeat_report
207
+ result = "\n"
208
+ @filebeat_status.each do |k, v|
209
+ result << k << "=>" << v.to_s << "\n"
210
+ end
211
+ @filebeat_status = {}
212
+ result
213
+ end
214
+
121
215
  end # class LogStash::Outputs::Thinkingdata
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-thinkingdata'
3
- s.version = '0.1.1'
3
+ s.version = '1.0.0'
4
4
  s.licenses = ['Apache-2.0']
5
5
  s.summary = 'Output plugin for Thinkingdata Analytics'
6
6
  s.description = 'This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program.'
7
7
  s.homepage = 'https://www.thinkingdata.cn/manual/api.html'
8
- s.authors = ['xuzz']
9
- s.email = 'xuzz@thinkingdata.cn'
8
+ s.authors = ['sdk']
9
+ s.email = 'sdk@thinkingdata.cn'
10
10
  s.require_paths = ['lib']
11
11
 
12
12
  # Files
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-thinkingdata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - xuzz
7
+ - sdk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-27 00:00:00.000000000 Z
11
+ date: 2020-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-core-plugin-api
@@ -123,7 +123,7 @@ dependencies:
123
123
  description: This gem is a logstash plugin required to be installed on top of the
124
124
  Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
125
125
  gem is not a stand-alone program.
126
- email: xuzz@thinkingdata.cn
126
+ email: sdk@thinkingdata.cn
127
127
  executables: []
128
128
  extensions: []
129
129
  extra_rdoc_files: []