td-logger 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +10 -0
- data/lib/td/logger/agent/access_log.rb +10 -0
- data/lib/td/logger/agent/rails.rb +20 -3
- data/lib/td/logger/tdlog.rb +74 -34
- data/lib/td/logger/version.rb +1 -1
- metadata +4 -4
data/ChangeLog
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
|
2
|
+
== 2011-09-13 version 0.2.4
|
3
|
+
|
4
|
+
* Increase flush_interval from 10 sec to 5 mins gradually
|
5
|
+
* Flush buffered logs when Rails stops
|
6
|
+
* Adds 'elapsed' column to access logs
|
7
|
+
* Use TREASURE_DATA_API_KEY environment variable by default
|
8
|
+
* Enable event logger if apikey is available with default database name
|
9
|
+
and access log table name
|
10
|
+
|
11
|
+
|
2
12
|
== 2011-09-08 version 0.2.3
|
3
13
|
|
4
14
|
* Loggers use STDERR instead of STDOUT
|
@@ -35,10 +35,20 @@ module Agent
|
|
35
35
|
data = {}
|
36
36
|
Thread.current['td.access_log'] = data
|
37
37
|
env['td.access_log'] = data
|
38
|
+
env['td.access_time'] = Time.now
|
38
39
|
end
|
39
40
|
|
40
41
|
Middleware.after do |env,result|
|
41
42
|
data = env['td.access_log'] || {}
|
43
|
+
access_time = env['td.access_time']
|
44
|
+
|
45
|
+
# add 'elapsed' column
|
46
|
+
if access_time
|
47
|
+
elapsed = Time.now - access_time
|
48
|
+
data['elapsed'] = elapsed
|
49
|
+
# set 'time' column to access time
|
50
|
+
data['time'] = access_time
|
51
|
+
end
|
42
52
|
|
43
53
|
ACCESS_LOG_PRESET_ENV_KEYS.each_pair {|key,val|
|
44
54
|
data[key] ||= env[val] if env[val]
|
@@ -86,14 +86,31 @@ EOF
|
|
86
86
|
require 'yaml'
|
87
87
|
require 'erb'
|
88
88
|
logger = ::Rails.logger || ::Logger.new(STDERR)
|
89
|
+
|
90
|
+
unless File.exist?(CONFIG_PATH)
|
91
|
+
apikey = ENV['TREASURE_DATA_API_KEY'] || ENV['TD_API_KEY']
|
92
|
+
unless apikey
|
93
|
+
logger.warn "TREASURE_DATA_API_KEY environment variable is not set"
|
94
|
+
logger.warn "#{CONFIG_PATH} does not exist."
|
95
|
+
logger.warn "Disabling Treasure Data logger."
|
96
|
+
return
|
97
|
+
end
|
98
|
+
return Config.new({
|
99
|
+
'apikey' => apikey,
|
100
|
+
'database' => ENV['TREASURE_DATA_DB'] || "rails_#{rails_env}",
|
101
|
+
'access_log_table' => ENV['TREASURE_DATA_TABLE'] || 'web_access',
|
102
|
+
'auto_create_table' => true
|
103
|
+
})
|
104
|
+
end
|
105
|
+
|
89
106
|
begin
|
90
107
|
src = File.read("#{rails_root}/#{CONFIG_PATH}")
|
91
108
|
yaml = ERB.new(src).result
|
92
109
|
env_conf = YAML.load(yaml)
|
93
110
|
rescue
|
94
|
-
logger.warn "Can't load #{CONFIG_PATH} file
|
95
|
-
logger.warn "
|
96
|
-
logger.warn "
|
111
|
+
logger.warn "Can't load #{CONFIG_PATH} file: #{$!}"
|
112
|
+
logger.warn "Disabling Treasure Data logger."
|
113
|
+
logger.warn "Example:"
|
97
114
|
logger.warn CONFIG_SAMPLE
|
98
115
|
return
|
99
116
|
end
|
data/lib/td/logger/tdlog.rb
CHANGED
@@ -2,9 +2,27 @@
|
|
2
2
|
module TreasureData
|
3
3
|
module Logger
|
4
4
|
|
5
|
-
# TODO shutdown handler (deadlock)
|
6
5
|
|
7
6
|
class TreasureDataLogger < Fluent::Logger::LoggerBase
|
7
|
+
module Finalizable
|
8
|
+
require 'delegate'
|
9
|
+
def new(*args, &block)
|
10
|
+
obj = allocate
|
11
|
+
obj.instance_eval { initialize(*args, &block) }
|
12
|
+
dc = DelegateClass(obj.class).new(obj)
|
13
|
+
ObjectSpace.define_finalizer(dc, finalizer(obj))
|
14
|
+
dc
|
15
|
+
end
|
16
|
+
|
17
|
+
def finalizer(obj)
|
18
|
+
fin = obj.method(:finalize)
|
19
|
+
proc {|id|
|
20
|
+
fin.call
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
extend Finalizable
|
25
|
+
|
8
26
|
def initialize(apikey, tag, auto_create_table)
|
9
27
|
require 'thread'
|
10
28
|
require 'stringio'
|
@@ -18,7 +36,9 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
18
36
|
|
19
37
|
@tag = tag
|
20
38
|
@auto_create_table = auto_create_table
|
39
|
+
|
21
40
|
@logger = ::Logger.new(STDERR)
|
41
|
+
@logger.level = ::Logger::INFO
|
22
42
|
|
23
43
|
@client = TreasureData::Client.new(apikey)
|
24
44
|
|
@@ -28,7 +48,8 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
28
48
|
@queue = []
|
29
49
|
|
30
50
|
@chunk_limit = 8*1024*1024
|
31
|
-
@flush_interval =
|
51
|
+
@flush_interval = 10
|
52
|
+
@max_flush_interval = 300
|
32
53
|
@retry_wait = 1.0
|
33
54
|
@retry_limit = 8
|
34
55
|
|
@@ -41,11 +62,21 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
41
62
|
attr_accessor :logger
|
42
63
|
|
43
64
|
def close
|
44
|
-
@finish
|
45
|
-
|
46
|
-
@
|
47
|
-
|
48
|
-
|
65
|
+
unless @finish
|
66
|
+
@finish = true
|
67
|
+
@mutex.synchronize {
|
68
|
+
@flush_now = true
|
69
|
+
@cond.signal
|
70
|
+
}
|
71
|
+
@upload_thread.join
|
72
|
+
|
73
|
+
@map.each {|(db,table),buffer|
|
74
|
+
upload(db, table, buffer)
|
75
|
+
}
|
76
|
+
@queue.each {|tuple|
|
77
|
+
upload(*tuple)
|
78
|
+
}
|
79
|
+
end
|
49
80
|
end
|
50
81
|
|
51
82
|
def post(tag, record)
|
@@ -70,29 +101,32 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
70
101
|
end
|
71
102
|
|
72
103
|
def upload_main
|
73
|
-
|
74
|
-
|
75
|
-
|
104
|
+
@mutex.lock
|
105
|
+
until @finish
|
106
|
+
now = Time.now.to_i
|
107
|
+
|
108
|
+
if @next_time <= now || (@flush_now && @error_count == 0)
|
109
|
+
@mutex.unlock
|
110
|
+
begin
|
111
|
+
flushed = try_flush
|
112
|
+
ensure
|
113
|
+
@mutex.lock
|
114
|
+
end
|
115
|
+
@flush_now = false
|
116
|
+
end
|
76
117
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
118
|
+
if @error_count == 0
|
119
|
+
if flushed && @flush_interval < @max_flush_interval
|
120
|
+
@flush_interval = [@flush_interval + 60, @max_flush_interval].min
|
121
|
+
end
|
122
|
+
next_wait = @flush_interval
|
123
|
+
else
|
124
|
+
next_wait = @retry_wait * (2 ** (@error_count-1))
|
83
125
|
end
|
84
|
-
@
|
85
|
-
end
|
126
|
+
@next_time = next_wait + now
|
86
127
|
|
87
|
-
|
88
|
-
next_wait = @flush_interval
|
89
|
-
else
|
90
|
-
next_wait = @retry_wait * (2 ** (@error_count-1))
|
128
|
+
cond_wait(next_wait)
|
91
129
|
end
|
92
|
-
@next_time = next_wait + now
|
93
|
-
|
94
|
-
cond_wait(next_wait)
|
95
|
-
end
|
96
130
|
|
97
131
|
rescue
|
98
132
|
@logger.error "Unexpected error: #{$!}"
|
@@ -113,6 +147,8 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
113
147
|
end
|
114
148
|
end
|
115
149
|
|
150
|
+
flushed = false
|
151
|
+
|
116
152
|
until @queue.empty?
|
117
153
|
tuple = @queue.first
|
118
154
|
|
@@ -120,12 +156,13 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
120
156
|
upload(*tuple)
|
121
157
|
@queue.shift
|
122
158
|
@error_count = 0
|
159
|
+
flushed = true
|
123
160
|
rescue
|
124
161
|
if @error_count < @retry_limit
|
125
|
-
@logger.error "Failed to
|
162
|
+
@logger.error "Failed to import logs to Treasure Data, retrying: #{$!}"
|
126
163
|
@error_count += 1
|
127
164
|
else
|
128
|
-
@logger.error "Failed to
|
165
|
+
@logger.error "Failed to import logs to Treasure Data, trashed: #{$!}"
|
129
166
|
$!.backtrace.each {|bt|
|
130
167
|
@logger.info bt
|
131
168
|
}
|
@@ -135,14 +172,17 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
135
172
|
return
|
136
173
|
end
|
137
174
|
end
|
175
|
+
|
176
|
+
flushed
|
138
177
|
end
|
139
178
|
|
140
179
|
def upload(db, table, buffer)
|
141
|
-
|
142
|
-
Zlib::GzipWriter.wrap(out) {|gz| gz.write buffer }
|
143
|
-
stream = StringIO.new(out.string)
|
144
|
-
|
180
|
+
@logger.debug "Importing logs to #{db}.#{table} table on TreasureData"
|
145
181
|
begin
|
182
|
+
out = StringIO.new
|
183
|
+
Zlib::GzipWriter.wrap(out) {|gz| gz.write buffer }
|
184
|
+
stream = StringIO.new(out.string)
|
185
|
+
|
146
186
|
@client.import(db, table, "msgpack.gz", stream, stream.size)
|
147
187
|
rescue TreasureData::NotFoundError
|
148
188
|
unless @auto_create_table
|
@@ -159,8 +199,8 @@ class TreasureDataLogger < Fluent::Logger::LoggerBase
|
|
159
199
|
end
|
160
200
|
end
|
161
201
|
|
162
|
-
def
|
163
|
-
|
202
|
+
def finalize
|
203
|
+
close
|
164
204
|
end
|
165
205
|
|
166
206
|
if ConditionVariable.new.method(:wait).arity == 1
|
data/lib/td/logger/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: td-logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 4
|
10
|
+
version: 0.2.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sadayuki Furuhashi
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-09-
|
18
|
+
date: 2011-09-13 00:00:00 +09:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|