fluent-plugin-appdynamics 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/fluent-plugin-appdynamics.gemspec +1 -1
- data/lib/fluent/plugin/in_appdynamics.rb +173 -15
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02f89af0f06e3e1191e604ad2fa5de824d6d1797
|
4
|
+
data.tar.gz: 3134d8b0bb533e006b9a5cd65c0bb753c9c6930f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9466dc0f158364434671ddf633e46e25a0ef4ea5f5201358bea86322835d207d9b2e06b266b7150c6a1e542d5dbc52bf0522540b715447c64dcb72281ec6cbfa
|
7
|
+
data.tar.gz: 2484bc41ca4f59f2698e559eb2ba65d5e61f27ef27b1e5249027467633d58798287ba8ce6f29dbad49713bc25649569afa6362962ee446a434cf4875d25191c5
|
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.name = "fluent-plugin-appdynamics"
|
6
|
-
gem.version = "0.0.
|
6
|
+
gem.version = "0.0.5"
|
7
7
|
gem.date = '2015-03-02'
|
8
8
|
gem.authors = ["chandrashekar Tippur"]
|
9
9
|
gem.email = ["ctippur@gmail.com"]
|
@@ -14,7 +14,122 @@ module Fluent
|
|
14
14
|
config_param :account, :string, :default => ""
|
15
15
|
config_param :include_raw, :string, :default => "true" #Include original object as raw
|
16
16
|
config_param :attributes, :string, :default => "ALL" # fields to include, ALL for... well, ALL.
|
17
|
-
|
17
|
+
|
18
|
+
config_param :state_type, :string, :default => nil
|
19
|
+
config_param :state_file, :string, :default => nil
|
20
|
+
config_param :select_limit, :time, :default => 10000
|
21
|
+
|
22
|
+
|
23
|
+
# Timewatcher class to handle collio
|
24
|
+
class TimerWatcher < Coolio::TimerWatcher
|
25
|
+
def initialize(interval, repeat, &callback)
|
26
|
+
@callback = callback
|
27
|
+
super(interval, repeat)
|
28
|
+
end # def initialize
|
29
|
+
|
30
|
+
def on_timer
|
31
|
+
@callback.call
|
32
|
+
rescue
|
33
|
+
$log.error $!.to_s
|
34
|
+
$log.error_backtrace
|
35
|
+
end # def on_timer
|
36
|
+
end
|
37
|
+
|
38
|
+
# Class statestore
|
39
|
+
class StateStore
|
40
|
+
def initialize(path,tag)
|
41
|
+
require 'yaml'
|
42
|
+
@path = path
|
43
|
+
if File.exists?(@path)
|
44
|
+
@data = YAML.load_file(@path)
|
45
|
+
if @data == false || @data == []
|
46
|
+
# this happens if an users created an empty file accidentally
|
47
|
+
@data = {}
|
48
|
+
elsif !@data.is_a?(Hash)
|
49
|
+
raise "state_file on #{@path.inspect} is invalid"
|
50
|
+
end
|
51
|
+
else
|
52
|
+
@data = {}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def last_records(tag=nil)
|
57
|
+
return @data[tag]
|
58
|
+
#@data['last_records'] ||= {}
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_records(time, tag=nil)
|
62
|
+
@data[tag]=time
|
63
|
+
pp @data
|
64
|
+
File.open(@path, 'w') {|f|
|
65
|
+
f.write YAML.dump(@data)
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Class store in memory
|
71
|
+
class MemoryStateStore
|
72
|
+
def initialize
|
73
|
+
@data = {}
|
74
|
+
end
|
75
|
+
|
76
|
+
def last_records(tag=nil)
|
77
|
+
@data['last_records'] ||= {}
|
78
|
+
end
|
79
|
+
|
80
|
+
def update_records(time,tag=nil)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Class store in redis
|
85
|
+
class RedisStateStore
|
86
|
+
state_key = ""
|
87
|
+
def initialize(path,tag)
|
88
|
+
state_key=tag
|
89
|
+
#redis_server = $appsettings['redis_server']
|
90
|
+
#redis_port = $appsettings['redis_port']
|
91
|
+
#redis_spectrum_key = $appsettings['redis_spectrum_key']
|
92
|
+
#####
|
93
|
+
require 'redis'
|
94
|
+
$redis = if File.exists?(path)
|
95
|
+
redis_config = YAML.load_file(path)
|
96
|
+
# Connect to Redis using the redis_config host and port
|
97
|
+
if path
|
98
|
+
begin
|
99
|
+
pp "In redis #{path} Host #{redis_config['host']} port #{redis_config['port']}"
|
100
|
+
$redis = Redis.new(host: redis_config['host'], port: redis_config['port'])
|
101
|
+
rescue Exception => e
|
102
|
+
$log.info e.message
|
103
|
+
$log.info e.backtrace.inspect
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
Redis.new
|
108
|
+
end
|
109
|
+
@data = {}
|
110
|
+
end
|
111
|
+
|
112
|
+
def last_records(tag=nil)
|
113
|
+
begin
|
114
|
+
alertStartTime=$redis.get(tag)
|
115
|
+
return alertStartTime
|
116
|
+
rescue Exception => e
|
117
|
+
$log.info e.message
|
118
|
+
$log.info e.backtrace.inspect
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def update_records(time, tag=nil)
|
123
|
+
begin
|
124
|
+
alertStartTime=$redis.set(tag,time)
|
125
|
+
rescue Exception => e
|
126
|
+
$log.info e.message
|
127
|
+
$log.info e.backtrace.inspect
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
18
133
|
# function to UTF8 encode
|
19
134
|
def to_utf8(str)
|
20
135
|
str = str.force_encoding('UTF-8')
|
@@ -26,6 +141,7 @@ module Fluent
|
|
26
141
|
def initialize
|
27
142
|
super
|
28
143
|
require 'json'
|
144
|
+
require 'yaml'
|
29
145
|
require 'rest-client'
|
30
146
|
require 'pp'
|
31
147
|
# Add any other dependencies
|
@@ -35,6 +151,33 @@ module Fluent
|
|
35
151
|
def configure(conf)
|
36
152
|
super
|
37
153
|
@conf = conf
|
154
|
+
|
155
|
+
# State type is a must
|
156
|
+
unless @state_type
|
157
|
+
$log.warn "'state_type <redis/file/memory>' parameter is not set to a valid source."
|
158
|
+
$log.warn "this parameter is highly recommended to save the last known good timestamp to resume event consuming"
|
159
|
+
exit
|
160
|
+
end
|
161
|
+
|
162
|
+
# Define a handler that gets filled with
|
163
|
+
unless @state_file
|
164
|
+
$log.warn "'state_file PATH' parameter is not set to a valid source."
|
165
|
+
log.warn "this parameter is highly recommended to save the last known good timestamp to resume event consuming"
|
166
|
+
@state_store = MemoryStateStore.new
|
167
|
+
else
|
168
|
+
if (@state_type =~ /redis/)
|
169
|
+
@state_store = RedisStateStore.new(@state_file, @tag)
|
170
|
+
elsif (@state_type =~ /file/)
|
171
|
+
@state_store = StateStore.new(@state_file, @tag)
|
172
|
+
else
|
173
|
+
$log.warn "Unknown state type. Need to handle this better"
|
174
|
+
exit
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
#@state_store = @state_file.nil? ? MemoryStateStore.new : StateStore.new(@state_file)
|
180
|
+
|
38
181
|
def appdynamicsEnd(startTime,endTime)
|
39
182
|
# Setup URL Resource
|
40
183
|
# Sample https://ep/controller/rest/applications/Prod/problems/healthrule-violations?time-range-type=BETWEEN_TIMES&output=JSON&start-time=1426270552990&end-time=1426270553000
|
@@ -42,6 +185,7 @@ module Fluent
|
|
42
185
|
$log.info @url
|
43
186
|
RestClient::Resource.new(@url,@user+"@"+@account,@pass)
|
44
187
|
end
|
188
|
+
|
45
189
|
def appdynamicsEntEnd(entityId)
|
46
190
|
# Setup URL Resource
|
47
191
|
# Sample https://ep/controller/rest/applications/Prod/nodes/81376?output=JSON
|
@@ -54,9 +198,11 @@ module Fluent
|
|
54
198
|
|
55
199
|
def start
|
56
200
|
super
|
201
|
+
@stop_flag = false
|
57
202
|
@loop = Coolio::Loop.new
|
58
|
-
timer_trigger = TimerWatcher.new(@interval, true, &method(:input))
|
59
|
-
timer_trigger.attach(@loop)
|
203
|
+
#timer_trigger = TimerWatcher.new(@interval, true, &method(:input))
|
204
|
+
#timer_trigger.attach(@loop)
|
205
|
+
@loop.attach(TimerWatcher.new(@interval, true, &method(:input)))
|
60
206
|
@thread = Thread.new(&method(:run))
|
61
207
|
$log.info "starting appdynamics poller, interval #{@interval}"
|
62
208
|
end
|
@@ -64,6 +210,7 @@ module Fluent
|
|
64
210
|
# Stop Listener and cleanup any open connections.
|
65
211
|
def shutdown
|
66
212
|
super
|
213
|
+
@stop_flag = true
|
67
214
|
@loop.stop
|
68
215
|
@thread.join
|
69
216
|
end
|
@@ -71,17 +218,36 @@ module Fluent
|
|
71
218
|
def run
|
72
219
|
@loop.run
|
73
220
|
$log.info "Running appdynamics Input"
|
221
|
+
rescue
|
222
|
+
$log.error "unexpected error", :error=>$!.to_s
|
223
|
+
$log.error_backtrace
|
74
224
|
end
|
75
225
|
|
76
226
|
# Start appdynamics Trap listener
|
77
227
|
# Add the code to run this
|
78
228
|
def input
|
79
|
-
|
229
|
+
if not @stop_flag
|
230
|
+
pollingStart = Engine.now.to_i * 1000
|
231
|
+
#alertStartTime = (Engine.now.to_f * 1000).to_i - @interval.to_i
|
232
|
+
#alertStartTime = Engine.now.to_i * 1000
|
233
|
+
if @state_store.last_records(@tag)
|
234
|
+
alertStartTime = @state_store.last_records(@tag)
|
235
|
+
$log.info @tag + " :: Got time record from state_store - #{alertStartTime}"
|
236
|
+
else
|
237
|
+
alertStartTime = pollingStart.to_i - @interval.to_i
|
238
|
+
#$log.info "Spectrum :: Got time record from initial config - #{alertStartTime}"
|
239
|
+
end
|
240
|
+
pollingEnd = ''
|
241
|
+
pollingDuration = ''
|
242
|
+
|
80
243
|
$log.info "appdynamics :: Polling alerts for time period: #{alertStartTime.to_i} - #{(Engine.now.to_f * 1000).to_i}"
|
81
244
|
# Post to Appdynamics and parse results
|
82
245
|
|
83
246
|
begin
|
84
247
|
responsePost=appdynamicsEnd(alertStartTime,(Engine.now.to_f * 1000).to_i).get
|
248
|
+
pollingEnd = Engine.now.to_i * 1000
|
249
|
+
#@state_store.update(pollingEnd, @tag)
|
250
|
+
pollingDuration = pollingEnd - pollingStart
|
85
251
|
rescue Exception => e
|
86
252
|
$log.info e.message
|
87
253
|
$log.info e.backtrace.inspect
|
@@ -131,25 +297,17 @@ module Fluent
|
|
131
297
|
$log.info val
|
132
298
|
begin
|
133
299
|
Engine.emit(@tag, val['startTimeInMillis'].to_i,val)
|
300
|
+
#@state_store.update
|
134
301
|
rescue Exception => e
|
135
302
|
$log.info e.message
|
136
303
|
$log.info e.backtrace.inspect
|
137
304
|
end
|
138
305
|
}
|
139
306
|
#pp body.class
|
307
|
+
@state_store.update_records(pollingEnd, @tag)
|
308
|
+
end # END Stop flag
|
140
309
|
end # def Input
|
141
310
|
|
142
311
|
end # End Input class
|
143
312
|
|
144
|
-
class TimerWatcher < Coolio::TimerWatcher
|
145
|
-
def initialize(interval, repeat, &callback)
|
146
|
-
@callback = callback
|
147
|
-
super(interval, repeat)
|
148
|
-
end
|
149
|
-
|
150
|
-
def on_timer
|
151
|
-
@callback.call
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
313
|
end # module Fluent
|