fluent-logger 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+
2
+ Release 0.3.0 - 2011/08/21
3
+
4
+ * Added 'tag' for event logs
5
+
6
+
7
+ Release 0.2.0 - 2011/08/05
8
+
9
+ * Redesigned Event class
10
+ * Added TestLogger (Fluent.open(:test))
11
+ * Added test programs
12
+
13
+
14
+ Release 0.1.0 - 2011/08/04
15
+
16
+ * First release
17
+
@@ -0,0 +1,117 @@
1
+ = Fluent logger
2
+
3
+ A structured event loger
4
+
5
+ == Examples
6
+
7
+ === Simple
8
+
9
+ require 'fluent-logger'
10
+
11
+ EventLogger = Fluent::Logger::ConsoleLogger.new(STDOUT)
12
+
13
+ module Event
14
+ AccessEvent = EventLogger.create_event('access', :agent, :action=>'access')
15
+ end
16
+
17
+ #=> access: action="access" agent="foo"
18
+ Event::AccessEvent.agent('foo').post!
19
+
20
+
21
+ === Singleton
22
+
23
+ require 'fluent-logger'
24
+
25
+ Fluent::Logger::ConsoleLogger.open(STDOUT)
26
+
27
+ module Event
28
+ AccessEvent = Fluent::Logger.create_event('access', :agent, :action=>'access')
29
+ end
30
+
31
+ #=> access: action="access" agent="foo"
32
+ Event::AccessEvent.agent('foo').post!
33
+
34
+
35
+ === Combine events
36
+
37
+ require 'fluent-logger'
38
+
39
+ EventLogger = Fluent::Logger::ConsoleLogger.new(STDOUT)
40
+
41
+ module Event
42
+ User = EventLogger.create_event('user', :name, :age)
43
+ LoginEvent = EventLogger.create_event('login', :action=>'login')
44
+ BuyEvent = EventLogger.create_event('buy', :item, :action=>'login')
45
+ end
46
+
47
+ e_user = Event::User.name('me').age(24)
48
+
49
+ #=> login: action="login" name="me" age=24
50
+ Event::LoginEvent.with(e_user).post!
51
+
52
+ #=> buy: action="login" name="me" age=24 item="item01"
53
+ Event::BuyEvent.with(e_user).item("item01").post!
54
+
55
+ === Update created events
56
+
57
+ require 'fluent-logger'
58
+
59
+ EventLogger = Fluent::Logger::ConsoleLogger.new(STDOUT)
60
+
61
+ module Event
62
+ User = EventLogger.create_event('user', :name, :age)
63
+ AgeChangeEvent = EventLogger.create_event('age_change', :changed_age, :action=>'age_change')
64
+ BuyEvent = EventLogger.create_event('buy', :item, :action=>'buy')
65
+ end
66
+
67
+ e_user = User.name('me').age(24)
68
+
69
+ #=> age_change: action="age_change" name="me" age=24 changed_age=25
70
+ Event::AgeChangeEvent.with(e_user).changed_age(25).post!
71
+ e_user.age!(25)
72
+
73
+ #=> buy: action="buy" name="me" age=25 item="item01"
74
+ Event::BuyEvent.with(e_user).item("item01").post!
75
+
76
+ === Update created events by combining
77
+
78
+ require 'fluent-logger'
79
+
80
+ EventLogger = Fluent::Logger::ConsoleLogger.new(STDOUT)
81
+
82
+ module Event
83
+ User = EventLogger.create_event('user', :name, :age)
84
+ Browser = EventLogger.create_event('browser', :host, :agent)
85
+ LoginEvent = EventLogger.create_event('login', :action=>'login')
86
+ end
87
+
88
+ e_user = Event::User.name('me').age(24)
89
+ e_browser = Event::Browser.host('remoteip').agent('firefox')
90
+ e_user.with!(e_browser)
91
+
92
+ #=> login: action="login" name="me" age=24 host="remoteip" agent="firefox"
93
+ Event::LoginEvent.with(e_user).post!
94
+
95
+
96
+ == Loggers
97
+
98
+ === Console
99
+
100
+ Fluent::Logger::ConsoleLogger.open(io)
101
+
102
+ === Syslog
103
+
104
+ Fluent::Logger::SyslogLogger.open(ident=$0, level=:info)
105
+
106
+ === Fluent
107
+
108
+ Fluent::Logger::FluentLogger.open('tag_prefix', 'host', port=24224)
109
+
110
+
111
+ Web site:: http://fluent.github.com/
112
+ Documents:: http://fluent.github.com/doc/
113
+ Source repository:: http://github.com/fluent
114
+ Author:: Sadayuki Furuhashi
115
+ Copyright:: (c) 2011 FURUHASHI Sadayuki
116
+ License:: Apache License, Version 2.0
117
+
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'fluent', 'logger')
@@ -0,0 +1,92 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+
20
+
21
+ module Logger
22
+ require 'fluent/logger/event'
23
+ require 'fluent/logger/base'
24
+
25
+ class DefaultLogger < LoggerBase
26
+ INSTANCE = self.new
27
+
28
+ def self.instance
29
+ INSTANCE
30
+ end
31
+
32
+ def self.new
33
+ INSTANCE
34
+ end
35
+
36
+ def post(tag, map)
37
+ Fluent::Logger.default.post(tag, map)
38
+ end
39
+
40
+ def close
41
+ Fluent::Logger.default.close
42
+ end
43
+ end
44
+
45
+ @@default_logger = nil
46
+
47
+ def self.new(*args)
48
+ if args.first.is_a?(Class) && args.first.ancestors.include?(LoggerBase)
49
+ type = args.shift
50
+ else
51
+ type = FluentLogger
52
+ end
53
+ type.new(*args)
54
+ end
55
+
56
+ def self.open(*args)
57
+ close
58
+ @@default_logger = new(*args)
59
+ end
60
+
61
+ def self.close
62
+ if @@default_logger
63
+ @@default_logger.close
64
+ @@default_logger = nil
65
+ end
66
+ end
67
+
68
+ def self.create_event(*args)
69
+ DefaultLogger.instance.create_event(*args)
70
+ end
71
+
72
+ def self.post(tag, map)
73
+ DefaultLogger.instance.post(tag, map)
74
+ end
75
+
76
+ def self.default
77
+ @@default_logger ||= ConsoleLogger.new(STDOUT)
78
+ end
79
+
80
+ def self.default=(logger)
81
+ @@default_logger = logger
82
+ end
83
+
84
+ autoload :FluentLogger, 'fluent/logger/fluent'
85
+ autoload :ConsoleLogger, 'fluent/logger/console'
86
+ autoload :SyslogLogger, 'fluent/logger/syslog'
87
+ autoload :TestLogger, 'fluent/logger/test'
88
+ end
89
+
90
+
91
+ end
92
+
@@ -0,0 +1,89 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+ module Logger
20
+
21
+
22
+ class LoggerBase
23
+ def self.open(*args, &block)
24
+ Fluent::Logger.open(self, *args, &block)
25
+ end
26
+
27
+ def create_event(tag, *args)
28
+ map = {}
29
+ keys = []
30
+ args.each {|a|
31
+ case a
32
+ when Hash
33
+ a.each_pair {|k,v|
34
+ keys << k.to_sym
35
+ map[k.to_sym] = v
36
+ }
37
+ else
38
+ keys << a.to_sym
39
+ end
40
+ }
41
+
42
+ m = Module.new
43
+ m.module_eval do
44
+ keys.each {|key|
45
+ define_method(key) do |v|
46
+ with(key=>v)
47
+ end
48
+ define_method(:"#{key}!") do |v|
49
+ with!(key=>v)
50
+ end
51
+ }
52
+ define_method(:MODULE) { m }
53
+ end
54
+
55
+ e = TerminalEvent.new(self, tag, map)
56
+ e.extend(m)
57
+ e
58
+ end
59
+
60
+ #def post(tag, map)
61
+ #end
62
+
63
+ #def close(map)
64
+ #end
65
+ end
66
+
67
+
68
+ class TextLogger < LoggerBase
69
+ def initialize
70
+ require 'json'
71
+ @time_format = "%b %e %H:%M:%S"
72
+ end
73
+
74
+ def post(tag, map)
75
+ a = [Time.now.strftime(@time_format), " ", tag, ":"]
76
+ map.each_pair {|k,v|
77
+ a << " #{k}="
78
+ a << v.to_json
79
+ }
80
+ post_text a.join
81
+ end
82
+
83
+ #def post_text(text)
84
+ #end
85
+ end
86
+
87
+
88
+ end
89
+ end
@@ -0,0 +1,56 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+ module Logger
20
+
21
+
22
+ class ConsoleLogger < TextLogger
23
+ def initialize(out)
24
+ super()
25
+ require 'time'
26
+
27
+ if out.is_a?(String)
28
+ @io = File.open(out, "a")
29
+ @on_reopen = Proc.new { @io.reopen(out, "a") }
30
+ elsif out.respond_to?(:write)
31
+ @io = out
32
+ @on_reopen = Proc.new { }
33
+ else
34
+ raise "Invlaid output: #{out.inspect}"
35
+ end
36
+ end
37
+
38
+ attr_accessor :time_format
39
+
40
+ def reopen!
41
+ @on_reopen.call
42
+ end
43
+
44
+ def post_text(text)
45
+ @io.puts text
46
+ end
47
+
48
+ def close
49
+ @io.close
50
+ self
51
+ end
52
+ end
53
+
54
+
55
+ end
56
+ end
@@ -0,0 +1,118 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+ module Logger
20
+
21
+
22
+ class Event
23
+ def initialize(link, map)
24
+ @link = link
25
+ @map = map
26
+ end
27
+
28
+ def to_hash(o={})
29
+ @link.to_hash(o)
30
+ o.merge!(@map)
31
+ o
32
+ end
33
+
34
+ def tag
35
+ @link.tag
36
+ end
37
+
38
+ def logger
39
+ @link.logger
40
+ end
41
+
42
+ def logger=(logger)
43
+ @link.logger = logger
44
+ end
45
+
46
+ def post!(with_tag=tag)
47
+ logger.post(with_tag, to_hash)
48
+ self
49
+ end
50
+
51
+ alias post post!
52
+
53
+ def with(a)
54
+ if a.is_a?(Event)
55
+ ma = MODULE()
56
+ mb = a.MODULE()
57
+ m = Module.new
58
+ m.module_eval do
59
+ include ma
60
+ include mb
61
+ define_method(:MODULE) { m }
62
+ end
63
+ map = a.to_hash(to_hash)
64
+ e = TerminalEvent.new(LOGGER(), tag, map)
65
+ e.extend(m)
66
+ else
67
+ map = a.to_hash
68
+ e = Event.new(self, map)
69
+ e.extend(MODULE())
70
+ end
71
+ e
72
+ end
73
+
74
+ alias + with
75
+
76
+ def with!(a)
77
+ if a.is_a?(Event)
78
+ self.extend a.MODULE()
79
+ a.to_hash(@map)
80
+ else
81
+ @map.merge!(a.to_hash)
82
+ end
83
+ self
84
+ end
85
+
86
+ def create_event(*args)
87
+ self.with(LOGGER().create_event(*args))
88
+ end
89
+
90
+ def LOGGER
91
+ @link.LOGGER()
92
+ end
93
+ end
94
+
95
+
96
+ class TerminalEvent < Event
97
+ def initialize(logger, tag, map)
98
+ @logger = logger
99
+ @tag = tag
100
+ @map = map
101
+ end
102
+
103
+ def to_hash(o={})
104
+ o.merge!(@map)
105
+ o
106
+ end
107
+
108
+ attr_accessor :tag
109
+ attr_accessor :logger
110
+
111
+ def LOGGER
112
+ @logger
113
+ end
114
+ end
115
+
116
+
117
+ end
118
+ end
@@ -0,0 +1,115 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+ module Logger
20
+
21
+
22
+ class FluentLogger < LoggerBase
23
+ BUFFER_LIMIT = 8*1024*1024
24
+
25
+ def initialize(tag, host, port=24224)
26
+ super()
27
+ require 'msgpack'
28
+ require 'socket'
29
+ require 'monitor'
30
+ require 'logger'
31
+ @mon = Monitor.new
32
+
33
+ @tag = tag
34
+
35
+ @pending = nil
36
+ @host = host
37
+ @port = port
38
+ connect!
39
+
40
+ @limit = BUFFER_LIMIT
41
+ @logger = ::Logger.new(STDERR)
42
+
43
+ FluentLogger.close_on_exit(self)
44
+ end
45
+
46
+ attr_accessor :limit, :logger
47
+
48
+ def post(tag, map)
49
+ time = Time.now.to_i
50
+ write ["#{@tag}.#{tag}", time, map]
51
+ end
52
+
53
+ def close
54
+ if @pending
55
+ @logger.error("FluentLogger: Can't send logs to #{@host}:#{@port}")
56
+ end
57
+ @con.close if @con
58
+ @con = nil
59
+ @pending = nil
60
+ self
61
+ end
62
+
63
+ private
64
+ def write(msg)
65
+ data = msg.to_msgpack
66
+ @mon.synchronize {
67
+ if @pending
68
+ @pending << data
69
+ data = @pending
70
+ end
71
+ begin
72
+ unless @con
73
+ connect!
74
+ end
75
+ while true
76
+ n = @con.syswrite(data)
77
+ if n >= data.bytesize
78
+ break
79
+ end
80
+ data = data[n..-1]
81
+ end
82
+ @pending = nil
83
+ rescue
84
+ if @pending
85
+ if @pending.bytesize > @limit
86
+ @logger.error("FluentLogger: Can't send logs to #{@host}:#{@port}")
87
+ @pending = nil
88
+ end
89
+ else
90
+ @pending = data
91
+ end
92
+ @con.close if @con
93
+ @con = nil
94
+ end
95
+ }
96
+ end
97
+
98
+ def connect!
99
+ @con = TCPSocket.new(@host, @port)
100
+ end
101
+
102
+ def self.close_on_exit(logger)
103
+ ObjectSpace.define_finalizer(logger, self.finalizer(logger))
104
+ end
105
+
106
+ def self.finalizer(logger)
107
+ proc {
108
+ logger.close
109
+ }
110
+ end
111
+ end
112
+
113
+
114
+ end
115
+ end
@@ -0,0 +1,127 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+ module Logger
20
+
21
+
22
+ class SyslogLogger < TextLogger
23
+ def initialize(ident=$0, level=:info)
24
+ super()
25
+ require 'syslog'
26
+
27
+ @ident = ident
28
+ self.level = level
29
+ #self.facility = facility
30
+ Syslog.open(@ident)
31
+ end
32
+
33
+ attr_reader :level
34
+
35
+ def level=(level)
36
+ level = level.to_sym if level.is_a?(String)
37
+ @level = case level
38
+ when :emerg, Syslog::LOG_EMERG
39
+ Syslog::LOG_EMERG
40
+ when :alert, Syslog::LOG_ALERT
41
+ Syslog::LOG_ALERT
42
+ when :crit, Syslog::LOG_CRIT
43
+ Syslog::LOG_CRIT
44
+ when :err, :error, Syslog::LOG_ERR
45
+ Syslog::LOG_ERR
46
+ when :warning, :warn, Syslog::LOG_WARNING
47
+ Syslog::LOG_WARNING
48
+ when :notice, Syslog::LOG_NOTICE
49
+ Syslog::LOG_NOTICE
50
+ when :info, Syslog::LOG_INFO
51
+ Syslog::LOG_INFO
52
+ when :debug, Syslog::LOG_DEBUG
53
+ Syslog::LOG_DEBUG
54
+ else
55
+ raise "Unknown level description #{level.inspect}"
56
+ end
57
+ end
58
+
59
+ #def facility=(facility)
60
+ # facility = facility.to_sym if facility.is_a?(String)
61
+ # @facility = case facility
62
+ # when :auth, Syslog::LOG_AUTH
63
+ # Syslog::LOG_AUTH
64
+ # when :authpriv, Syslog::LOG_AUTHPRIV
65
+ # Syslog::LOG_AUTHPRIV
66
+ # when :console, Syslog::LOG_CONSOLE
67
+ # Syslog::LOG_CONSOLE
68
+ # when :cron, Syslog::LOG_CRON
69
+ # Syslog::LOG_CRON
70
+ # when :daemon, Syslog::LOG_DAEMON
71
+ # Syslog::LOG_DAEMON
72
+ # when :ftp, Syslog::LOG_FTP
73
+ # Syslog::LOG_FTP
74
+ # when :kern, Syslog::LOG_KERN
75
+ # Syslog::LOG_KERN
76
+ # when :lpr, Syslog::LOG_LPR
77
+ # Syslog::LOG_LPR
78
+ # when :mail, Syslog::LOG_MAIL
79
+ # Syslog::LOG_MAIL
80
+ # when :news, Syslog::LOG_NEWS
81
+ # Syslog::LOG_NEWS
82
+ # when :ntp, Syslog::LOG_NTP
83
+ # Syslog::LOG_NTP
84
+ # when :security, Syslog::LOG_SECURITY
85
+ # Syslog::LOG_SECURITY
86
+ # when :syslog, Syslog::LOG_SYSLOG
87
+ # Syslog::LOG_SYSLOG
88
+ # when :user, Syslog::LOG_USER
89
+ # Syslog::LOG_USER
90
+ # when :uucp, Syslog::LOG_UUCP
91
+ # Syslog::LOG_UUCP
92
+ # when :local0, Syslog::LOG_LOCAL0
93
+ # Syslog::LOG_LOCAL0
94
+ # when :local1, Syslog::LOG_LOCAL1
95
+ # Syslog::LOG_LOCAL1
96
+ # when :local2, Syslog::LOG_LOCAL2
97
+ # Syslog::LOG_LOCAL2
98
+ # when :local3, Syslog::LOG_LOCAL3
99
+ # Syslog::LOG_LOCAL3
100
+ # when :local4, Syslog::LOG_LOCAL4
101
+ # Syslog::LOG_LOCAL4
102
+ # when :local5, Syslog::LOG_LOCAL5
103
+ # Syslog::LOG_LOCAL5
104
+ # when :local6, Syslog::LOG_LOCAL6
105
+ # Syslog::LOG_LOCAL6
106
+ # when :local7, Syslog::LOG_LOCAL7
107
+ # Syslog::LOG_LOCAL7
108
+ # else
109
+ # raise "Unknown facility description #{facility.inspect}"
110
+ # end
111
+ # Syslog.reopen(@ident, Syslog::LOG_PID|Syslog::LOG_CONS, @facility)
112
+ # facility
113
+ #end
114
+
115
+ def post_text(text)
116
+ Syslog.log(@level, "%s", text)
117
+ end
118
+
119
+ def close
120
+ Syslog.close
121
+ self
122
+ end
123
+ end
124
+
125
+
126
+ end
127
+ end
@@ -0,0 +1,55 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under 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
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
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
+ #
18
+ module Fluent
19
+ module Logger
20
+
21
+
22
+ class TestLogger < LoggerBase
23
+ def initialize(queue=[])
24
+ @queue = queue
25
+ @max = 1024
26
+ @close_called = 0
27
+ end
28
+
29
+ attr_accessor :max
30
+ attr_reader :queue
31
+ attr_reader :close_called
32
+
33
+ def post(tag, map)
34
+ while @queue.size > @max
35
+ @queue.shift
36
+ end
37
+ (class<<map;self;end).module_eval do
38
+ define_method(:tag) { tag }
39
+ end
40
+ @queue << map
41
+ end
42
+
43
+ def close
44
+ @close_called += 1
45
+ end
46
+
47
+ def closed?
48
+ @close_called > 0
49
+ end
50
+ end
51
+
52
+
53
+ end
54
+ end
55
+
@@ -0,0 +1,7 @@
1
+ module Fluent
2
+ module Logger
3
+
4
+ VERSION = '0.3.0'
5
+
6
+ end
7
+ end
@@ -0,0 +1,183 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class EventTest < Test::Unit::TestCase
4
+ it 'keys' do
5
+ g = Fluent::Logger::TestLogger.new
6
+
7
+ assert_nothing_raised do
8
+ e1 = g.create_event('e1', :k1)
9
+ e1.k1('v1')
10
+ end
11
+
12
+ assert_raise(NoMethodError) do
13
+ e2 = g.create_event('e2')
14
+ e2.k1('v1')
15
+ end
16
+
17
+ assert_raise(NoMethodError) do
18
+ e3 = g.create_event('e3', :k1)
19
+ e3.k2('v2')
20
+ end
21
+ end
22
+
23
+ it 'set_value' do
24
+ g = Fluent::Logger::TestLogger.new
25
+
26
+ e1 = g.create_event('e1', :k1)
27
+ e1.k1('v1').post!
28
+ assert_equal g.queue.last, {:k1=>'v1'}
29
+
30
+ e2 = g.create_event('e2', :k1, :k2)
31
+ e2.k1('v1').k2('v2').post!
32
+ assert_equal g.queue.last, {:k1=>'v1', :k2=>'v2'}
33
+
34
+ e3 = g.create_event('e3', :k1, :k2)
35
+ e3.k1('v1').post!
36
+ assert_equal g.queue.last, {:k1=>'v1'}
37
+ end
38
+
39
+ it 'default_value' do
40
+ g = Fluent::Logger::TestLogger.new
41
+
42
+ e1 = g.create_event('e1', :k1)
43
+ e1.post!
44
+ assert_equal g.queue.last, {}
45
+
46
+ e2 = g.create_event('e2', :k1=>'v1')
47
+ e2.post!
48
+ assert_equal g.queue.last, {:k1=>'v1'}
49
+
50
+ e3 = g.create_event('e3', :k1=>'v1', :k2=>'v2')
51
+ e3.post!
52
+ assert_equal g.queue.last, {:k1=>'v1', :k2=>'v2'}
53
+
54
+ e4 = g.create_event('e4', :k1=>'v1', :k2=>'v2')
55
+ e4.k2('v3').post!
56
+ assert_equal g.queue.last, {:k1=>'v1', :k2=>'v3'}
57
+ end
58
+
59
+ it 'modify' do
60
+ g = Fluent::Logger::TestLogger.new
61
+
62
+ e1 = g.create_event('e1', :k1)
63
+ e1.k1!('v1')
64
+ e1.post!
65
+ assert_equal g.queue.last, {:k1=>'v1'}
66
+
67
+ e1.k1!('v2')
68
+ e1.post!
69
+ assert_equal g.queue.last, {:k1=>'v2'}
70
+
71
+ e2 = g.create_event('e2', :k1=>'v1')
72
+ e2.k1!('v2')
73
+ e2.post!
74
+ assert_equal g.queue.last, {:k1=>'v2'}
75
+ end
76
+
77
+ it 'no_modify' do
78
+ g = Fluent::Logger::TestLogger.new
79
+
80
+ e1 = g.create_event('e1', :k1)
81
+ e1.k1('v1')
82
+ e1.post!
83
+ assert_equal g.queue.last, {}
84
+
85
+ e1.k1('v2')
86
+ e1.post!
87
+ assert_equal g.queue.last, {}
88
+
89
+ e2 = g.create_event('e1', :k1=>'v1')
90
+ e2.k1('v2')
91
+ e2.post!
92
+ assert_equal g.queue.last, {:k1=>'v1'}
93
+ end
94
+
95
+ it 'with_map' do
96
+ g = Fluent::Logger::TestLogger.new
97
+
98
+ e1 = g.create_event('e1')
99
+ e1.with(:k1=>'v1').post!
100
+ assert_equal g.queue.last, {:k1=>'v1'}
101
+
102
+ e2 = g.create_event('e2', :k1=>'v1')
103
+ e2.with(:k1=>'v2').post!
104
+ assert_equal g.queue.last, {:k1=>'v2'}
105
+
106
+ e3 = g.create_event('e3', :k1=>'v1')
107
+ e3.with(:k1=>'v2', :k2=>'v3').post!
108
+ assert_equal g.queue.last, {:k1=>'v2', :k2=>'v3'}
109
+ end
110
+
111
+ it 'with_map_modify' do
112
+ g = Fluent::Logger::TestLogger.new
113
+
114
+ e1 = g.create_event('e2', :k1)
115
+ e1.with!(:k1=>'v1')
116
+ e1.post!
117
+ assert_equal g.queue.last, {:k1=>'v1'}
118
+
119
+ e1.with!(:k1=>'v2')
120
+ e1.post!
121
+ assert_equal g.queue.last, {:k1=>'v2'}
122
+
123
+ e2 = g.create_event('e2')
124
+ e2.with!(:k1=>'v1', :k2=>'v2')
125
+ e2.post!
126
+ assert_equal g.queue.last, {:k1=>'v1', :k2=>'v2'}
127
+
128
+ e2.with!(:k1=>'v3')
129
+ e2.post!
130
+ assert_equal g.queue.last, {:k1=>'v3', :k2=>'v2'}
131
+ end
132
+
133
+ it 'with_event_keys' do
134
+ g = Fluent::Logger::TestLogger.new
135
+
136
+ assert_nothing_raised do
137
+ e1 = g.create_event('e1', :k1)
138
+ e2 = g.create_event('e2', :k2)
139
+ e3 = e1.with(e2)
140
+ e3.k1('v1').k2('v2')
141
+ end
142
+
143
+ assert_nothing_raised do
144
+ e1 = g.create_event('e1', :k1)
145
+ e2 = g.create_event('e2', :k1, :k2)
146
+ e3 = e1.with(e2)
147
+ e3.k1('v1').k2('v2')
148
+ end
149
+
150
+ assert_nothing_raised do
151
+ e1 = g.create_event('e1', :k1)
152
+ e2 = g.create_event('e2', :k2)
153
+ e1.with!(e2)
154
+ e1.k1('v1').k2('v2')
155
+ end
156
+
157
+ assert_raise(NoMethodError) do
158
+ e1 = g.create_event('e1', :k1)
159
+ e2 = g.create_event('e2', :k2)
160
+ e3 = e1.with(e2)
161
+ e1.k2('v1')
162
+ end
163
+
164
+ assert_raise(NoMethodError) do
165
+ e1 = g.create_event('e1', :k1)
166
+ e2 = g.create_event('e2', :k2)
167
+ e1.with!(e2)
168
+ e2.k1('v1')
169
+ end
170
+ end
171
+
172
+ it 'tag' do
173
+ g = Fluent::Logger::TestLogger.new
174
+
175
+ e1 = g.create_event('e1')
176
+ e1.post!
177
+ assert_equal g.queue.last.tag, 'e1'
178
+
179
+ e1.post!('e2')
180
+ assert_equal g.queue.last.tag, 'e2'
181
+ end
182
+ end
183
+
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class InstanceTest < Test::Unit::TestCase
4
+ it 'default' do
5
+ g1 = Fluent::Logger::TestLogger.open
6
+ assert_equal g1.object_id, Fluent::Logger.default.object_id
7
+
8
+ assert_equal false, g1.closed?
9
+
10
+ g2 = Fluent::Logger::TestLogger.open
11
+ assert_equal g2.object_id, Fluent::Logger.default.object_id
12
+
13
+ assert_equal true, g1.closed?
14
+
15
+ g3 = Fluent::Logger::TestLogger.new
16
+ assert_equal g2.object_id, Fluent::Logger.default.object_id
17
+
18
+ assert_equal false, g2.closed?
19
+ Fluent::Logger.close
20
+ assert_equal true, g2.closed?
21
+ end
22
+
23
+ it 'post' do
24
+ g1 = Fluent::Logger::TestLogger.new
25
+
26
+ g1.post :k1=>'v1'
27
+ assert_equal g1.queue.last, {:k1=>'v1'}
28
+
29
+ g2 = Fluent::Logger::TestLogger.open
30
+
31
+ Fluent::Logger.post :k2=>'v2'
32
+ assert_equal g2.queue.last, {:k2=>'v2'}
33
+ end
34
+ end
@@ -0,0 +1,78 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class SimpleTest < Test::Unit::TestCase
4
+ it 'singleton' do
5
+ Fluent::Logger::ConsoleLogger.open(STDOUT)
6
+
7
+ AccessEvent = Fluent::Logger.create_event('e1', :agent, :action=>'access')
8
+ LoginEvent = Fluent::Logger.create_event('e2', :user, :action=>'login')
9
+
10
+ #=> action="access" agent="foo"
11
+ AccessEvent.agent('foo').post!
12
+
13
+ #=> action="login" user="bar"
14
+ LoginEvent.user('bar').post!
15
+ end
16
+
17
+ it 'local' do
18
+ E2_LOG = Fluent::Logger::ConsoleLogger.new(STDOUT)
19
+
20
+ E2_AccessEvent = E2_LOG.create_event('e1', :agent, :action=>'access')
21
+ E2_LoginEvent = E2_LOG.create_event('e2', :user, :action=>'login')
22
+
23
+ #=> action="access" agent="foo"
24
+ E2_AccessEvent.agent('foo').post!
25
+
26
+ #=> action="login" user="bar"
27
+ E2_LoginEvent.user('bar').post!
28
+ end
29
+
30
+ it 'combine' do
31
+ E3_LOG = Fluent::Logger::ConsoleLogger.new(STDOUT)
32
+
33
+ E3_User = E3_LOG.create_event('e1', :name, :age)
34
+ E3_LoginEvent = E3_LOG.create_event('e2', :action=>'login')
35
+ E3_BuyEvent = E3_LOG.create_event('e3', :item, :action=>'login')
36
+
37
+ e_user = E3_User.name('me').age(24)
38
+
39
+ #=> action="login" name="me" age=24
40
+ E3_LoginEvent.with(e_user).post!
41
+
42
+ #=> action="login" name="me" age=24 item="item01"
43
+ E3_BuyEvent.with(e_user).item("item01").post!
44
+ end
45
+
46
+ it 'update' do
47
+ E4_LOG = Fluent::Logger::ConsoleLogger.new(STDOUT)
48
+
49
+ E4_User = E4_LOG.create_event('e1', :name, :age)
50
+ E4_AgeChangeEvent = E4_LOG.create_event('e2', :changed_age, :action=>'age_change')
51
+ E4_BuyEvent = E4_LOG.create_event('e3', :item, :action=>'buy')
52
+
53
+ e_user = E4_User.name('me').age(24)
54
+
55
+ #=> action="age_change" name="me" age=24 changed_age=25
56
+ E4_AgeChangeEvent.with(e_user).changed_age(25).post!
57
+ e_user.age!(25)
58
+
59
+ #=> action="buy" name="me" age=25 item="item01"
60
+ E4_BuyEvent.with(e_user).item("item01").post!
61
+ end
62
+
63
+ it 'combine_update' do
64
+ E5_LOG = Fluent::Logger::ConsoleLogger.new(STDOUT)
65
+
66
+ E5_User = E5_LOG.create_event('e1', :name, :age)
67
+ E5_Browser = E5_LOG.create_event('e2', :host, :agent)
68
+ E5_LoginEvent = E5_LOG.create_event('e3', :action=>'login')
69
+
70
+ e_user = E5_User.name('me').age(24)
71
+ e_browser = E5_Browser.host('remoteip').agent('firefox')
72
+ e_user.with!(e_browser)
73
+
74
+ #=> action="login" name="me" age=24 host="remoteip" agent="firefox"
75
+ E5_LoginEvent.with(e_user).post!
76
+ end
77
+ end
78
+
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+ $LOAD_PATH << File.dirname(__FILE__)+"/../lib"
3
+ require 'fluent/logger'
4
+ require 'fileutils'
5
+
6
+ class Test::Unit::TestCase
7
+ #class << self
8
+ # alias_method :it, :test
9
+ #end
10
+ def self.it(name, &block)
11
+ define_method("test_#{name}", &block)
12
+ end
13
+ end
14
+
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-logger
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
+ platform: ruby
12
+ authors:
13
+ - Sadayuki Furuhashi
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-21 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: msgpack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 0
32
+ - 4
33
+ - 4
34
+ version: 0.4.4
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: json
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 1
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 3
50
+ version: 1.4.3
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description:
54
+ email: frsyuki@gmail.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files:
60
+ - ChangeLog
61
+ - README.rdoc
62
+ files:
63
+ - lib/fluent-logger.rb
64
+ - lib/fluent/logger.rb
65
+ - lib/fluent/logger/base.rb
66
+ - lib/fluent/logger/console.rb
67
+ - lib/fluent/logger/event.rb
68
+ - lib/fluent/logger/fluent.rb
69
+ - lib/fluent/logger/syslog.rb
70
+ - lib/fluent/logger/test.rb
71
+ - lib/fluent/logger/version.rb
72
+ - test/event_test.rb
73
+ - test/instance_test.rb
74
+ - test/simple_test.rb
75
+ - test/test_helper.rb
76
+ - ChangeLog
77
+ - README.rdoc
78
+ has_rdoc: true
79
+ homepage: http://fluent.github.com/
80
+ licenses: []
81
+
82
+ post_install_message:
83
+ rdoc_options:
84
+ - --charset=UTF-8
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project:
108
+ rubygems_version: 1.3.7
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: Structured event logger
112
+ test_files:
113
+ - test/event_test.rb
114
+ - test/instance_test.rb
115
+ - test/simple_test.rb
116
+ - test/test_helper.rb