ocular 0.1.8 → 0.1.9
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 +4 -4
- data/bin/ocular +30 -3
- data/lib/ocular/dsl/fog.rb +12 -0
- data/lib/ocular/dsl/logging.rb +13 -86
- data/lib/ocular/dsl/runcontext.rb +5 -4
- data/lib/ocular/event/eventbase.rb +13 -6
- data/lib/ocular/event/eventfactory.rb +5 -4
- data/lib/ocular/inputs/cron_input.rb +15 -14
- data/lib/ocular/inputs/http_input.rb +15 -5
- data/lib/ocular/inputs/trigger_input.rb +55 -0
- data/lib/ocular/logging/console_logger.rb +97 -0
- data/lib/ocular/logging/kafka_logger.rb +112 -0
- data/lib/ocular/logging/logging.rb +4 -0
- data/lib/ocular/logging/multilogger.rb +52 -0
- data/lib/ocular/logging/severity.rb +23 -0
- data/lib/ocular/ocular.rb +1 -0
- data/lib/ocular/version.rb +1 -1
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3121ebd021fce075c9b4232f8980fa3bec3bde96
|
4
|
+
data.tar.gz: ecaf0bb7bbf9ae725f1f29ea179c786a3a3d40b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afdd0c1d5d190f029099fe21572c2bbd9d755c908b64f8d704955c2b2544ffcfb41fc885f4bfa7aade66350398907a172d134ee1ccbce78695d1bebd1f472ad3
|
7
|
+
data.tar.gz: 5b826d61d4609aa6e26b6d56eed01db1c64c38898ce72ce3ff87ca9f5b625f51cf1f1a998ea70fe2904d64eeb1061134d0ee6ac048d13d1b08e16a4c46af850c
|
data/bin/ocular
CHANGED
@@ -23,6 +23,7 @@ class OptparseExample
|
|
23
23
|
options.server = false
|
24
24
|
options.settings = nil
|
25
25
|
options.root = nil
|
26
|
+
options.check = nil
|
26
27
|
|
27
28
|
opt_parser = OptionParser.new do |opts|
|
28
29
|
opts.banner = "Usage in shell mode: \"ocular [options] <script file>\" or server mode: \"ocular --server [options]\""
|
@@ -59,6 +60,10 @@ class OptparseExample
|
|
59
60
|
options.settings = path
|
60
61
|
end
|
61
62
|
|
63
|
+
opts.on("--check", "Do only syntax check") do
|
64
|
+
options.check = true
|
65
|
+
end
|
66
|
+
|
62
67
|
end
|
63
68
|
|
64
69
|
opt_parser.parse!(args)
|
@@ -95,7 +100,24 @@ inputs:
|
|
95
100
|
exit -1
|
96
101
|
end
|
97
102
|
|
98
|
-
|
103
|
+
logger = Ocular::Logging::MultiLogger.new
|
104
|
+
|
105
|
+
if Ocular::Settings.get(:loggers)
|
106
|
+
Ocular::Settings.get(:loggers).each do |name, settings|
|
107
|
+
name = name.to_s
|
108
|
+
if name == "console"
|
109
|
+
logger.add_logger(Ocular::Logging::ConsoleLogger.new(settings))
|
110
|
+
elsif name == "kafka"
|
111
|
+
logger.add_logger(Ocular::Logging::KafkaLogger.new(settings))
|
112
|
+
else
|
113
|
+
puts "Unknown logging engine #{name}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
else
|
117
|
+
logger.add_logger(Ocular::Logging::ConsoleLogger.new)
|
118
|
+
end
|
119
|
+
|
120
|
+
if options.server or options.syntax
|
99
121
|
if !options.root && !Ocular::Settings.get(:script_root)
|
100
122
|
puts "Please specify --root or set script_root in the settings.yaml"
|
101
123
|
exit
|
@@ -103,6 +125,11 @@ if options.server
|
|
103
125
|
|
104
126
|
daemon = Ocular::Daemon.new(options.root || Ocular::Settings.get(:script_root))
|
105
127
|
daemon.load_script_files()
|
128
|
+
|
129
|
+
if options.syntax
|
130
|
+
exit 0
|
131
|
+
end
|
132
|
+
|
106
133
|
daemon.start_input_handlers()
|
107
134
|
|
108
135
|
puts "server started"
|
@@ -151,7 +178,7 @@ else
|
|
151
178
|
|
152
179
|
ef = Ocular::Event::EventFactory.new
|
153
180
|
|
154
|
-
context = Ocular::DSL::REPLRunContext.new(ef.handlers)
|
181
|
+
context = Ocular::DSL::REPLRunContext.new(ef.handlers, logger)
|
155
182
|
|
156
183
|
irb = IRB::Irb.new(IRB::WorkSpace.new(context))
|
157
184
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
@@ -174,7 +201,7 @@ else
|
|
174
201
|
ef = Ocular::Event::EventFactory.new
|
175
202
|
proxy = ef.load_from_file(ARGV.shift)
|
176
203
|
|
177
|
-
context = Ocular::DSL::RunContext.new
|
204
|
+
context = Ocular::DSL::RunContext.new(logger)
|
178
205
|
eventbase = proxy.events["onEvent"]["cli"]
|
179
206
|
eventbase.exec(context)
|
180
207
|
|
data/lib/ocular/dsl/fog.rb
CHANGED
@@ -44,6 +44,18 @@ class Ocular
|
|
44
44
|
return instances
|
45
45
|
end
|
46
46
|
|
47
|
+
add_help "find_server_by_ip", "Returns Fog::Compute::AWS::Server or nil"
|
48
|
+
def find_server_by_ip(ip)
|
49
|
+
ret = aws().servers.all("private-ip-address" => ip)
|
50
|
+
if ret.length > 1
|
51
|
+
raise "Too many matching servers by just one ip #{ip}"
|
52
|
+
end
|
53
|
+
if ret.length == 0
|
54
|
+
return nil
|
55
|
+
end
|
56
|
+
return ret.first
|
57
|
+
end
|
58
|
+
|
47
59
|
end
|
48
60
|
|
49
61
|
end
|
data/lib/ocular/dsl/logging.rb
CHANGED
@@ -5,112 +5,39 @@ class Ocular
|
|
5
5
|
module Logging
|
6
6
|
|
7
7
|
def debug(message = nil, &block)
|
8
|
-
@logger.add(
|
8
|
+
@logger.add(::Ocular::Logging::Severity::DEBUG, message, @run_id, &block)
|
9
9
|
end
|
10
10
|
alias log debug
|
11
11
|
|
12
12
|
def info(message = nil, &block)
|
13
|
-
@logger.add(
|
13
|
+
@logger.add(::Ocular::Logging::Severity::INFO, message, @run_id, &block)
|
14
14
|
end
|
15
15
|
|
16
16
|
def warn(message = nil, &block)
|
17
|
-
@logger.add(
|
17
|
+
@logger.add(::Ocular::Logging::Severity::WARN, message, @run_id, &block)
|
18
18
|
end
|
19
19
|
|
20
20
|
def error(message = nil, &block)
|
21
|
-
@logger.add(
|
21
|
+
@logger.add(::Ocular::Logging::Severity::ERROR, message, @run_id, &block)
|
22
22
|
end
|
23
23
|
|
24
24
|
def fatal(message = nil, &block)
|
25
|
-
@logger.add(
|
25
|
+
@logger.add(::Ocular::Logging::Severity::FATAL, message, @run_id, &block)
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# Most of the Logger class is copied from the Ruby Logger class source code.
|
32
|
-
class Logger
|
33
|
-
|
34
|
-
# Logging severity.
|
35
|
-
module Severity
|
36
|
-
# Low-level information, mostly for developers.
|
37
|
-
DEBUG = 0
|
38
|
-
# Generic (useful) information about system operation.
|
39
|
-
INFO = 1
|
40
|
-
# A warning.
|
41
|
-
WARN = 2
|
42
|
-
# A handleable error condition.
|
43
|
-
ERROR = 3
|
44
|
-
# An unhandleable error that results in a program crash.
|
45
|
-
FATAL = 4
|
46
|
-
# An unknown message that should always be logged.
|
47
|
-
UNKNOWN = 5
|
28
|
+
def log_event(property, value)
|
29
|
+
@logger.log_event(property, value, @run_id)
|
48
30
|
end
|
49
31
|
|
50
|
-
def
|
51
|
-
@
|
52
|
-
@formatter = Logger::Formatter.new
|
53
|
-
end
|
54
|
-
|
55
|
-
def add(severity, message = nil, run_id = nil, &block)
|
56
|
-
severity ||= Severity::UNKNOWN
|
57
|
-
if severity < @level
|
58
|
-
return true
|
59
|
-
end
|
60
|
-
|
61
|
-
if message.nil?
|
62
|
-
if block_given?
|
63
|
-
message = yield
|
64
|
-
else
|
65
|
-
message = progname
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
puts format_message(format_severity(severity), Time.now, run_id, message)
|
70
|
-
true
|
32
|
+
def log_cause(type, environment)
|
33
|
+
@logger.log_cause(type, environment, @run_id)
|
71
34
|
end
|
72
35
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
SEV_LABEL[severity] || 'ANY'
|
77
|
-
end
|
78
|
-
|
79
|
-
def format_message(severity, datetime, progname, msg)
|
80
|
-
@formatter.call(severity, datetime, progname, msg)
|
81
|
-
end
|
82
|
-
|
83
|
-
# Default formatter for log messages.
|
84
|
-
class Formatter
|
85
|
-
Format = "%s, [%s#%d] %5s -- %s: %s\n".freeze
|
86
|
-
|
87
|
-
attr_accessor :datetime_format
|
88
|
-
|
89
|
-
def initialize
|
90
|
-
@datetime_format = nil
|
91
|
-
end
|
92
|
-
|
93
|
-
def call(severity, time, progname, msg)
|
94
|
-
Format % [severity[0..0], format_datetime(time), $$, severity, progname, msg2str(msg)]
|
95
|
-
end
|
96
|
-
|
97
|
-
private
|
98
|
-
|
99
|
-
def format_datetime(time)
|
100
|
-
time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
|
101
|
-
end
|
102
|
-
|
103
|
-
def msg2str(msg)
|
104
|
-
case msg
|
105
|
-
when ::String
|
106
|
-
msg
|
107
|
-
when ::Exception
|
108
|
-
"#{ msg.message } (#{ msg.class })\n" <<
|
109
|
-
(msg.backtrace || []).join("\n")
|
110
|
-
else
|
111
|
-
msg.inspect
|
112
|
-
end
|
36
|
+
def log_timing(name, value)
|
37
|
+
if value.is_a? Time
|
38
|
+
value = (Time.now - value) * 1000 # report in milliseconds
|
113
39
|
end
|
40
|
+
@logger.log_timing(name, value, @run_id)
|
114
41
|
end
|
115
42
|
end
|
116
43
|
end
|
@@ -18,9 +18,9 @@ class Ocular
|
|
18
18
|
|
19
19
|
include Ocular::Inputs::Cron::DSL
|
20
20
|
|
21
|
-
def initialize
|
21
|
+
def initialize(logger)
|
22
22
|
@run_id = SecureRandom.uuid()
|
23
|
-
@logger =
|
23
|
+
@logger = logger
|
24
24
|
@cleanups = []
|
25
25
|
end
|
26
26
|
|
@@ -47,9 +47,10 @@ class Ocular
|
|
47
47
|
attr_reader :handlers
|
48
48
|
attr_reader :events
|
49
49
|
attr_reader :do_fork
|
50
|
+
attr_reader :logger
|
50
51
|
|
51
|
-
def initialize(handlers)
|
52
|
-
super()
|
52
|
+
def initialize(handlers, logger)
|
53
|
+
super(logger)
|
53
54
|
@events = {}
|
54
55
|
@handlers = handlers
|
55
56
|
@do_fork = false
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'ocular/mixin/from_file'
|
2
2
|
require 'ocular/dsl/logging'
|
3
|
+
require 'time'
|
3
4
|
|
4
5
|
class Ocular
|
5
6
|
module DSL
|
@@ -13,16 +14,22 @@ class Ocular
|
|
13
14
|
|
14
15
|
attr_accessor :proxy
|
15
16
|
|
16
|
-
def initialize(&block)
|
17
|
+
def initialize(proxy, &block)
|
17
18
|
@callback = block
|
19
|
+
@proxy = proxy
|
18
20
|
end
|
19
21
|
|
20
22
|
def exec(context, do_fork = self.proxy.do_fork)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
start = Time.now
|
24
|
+
begin
|
25
|
+
context.proxy = self.proxy
|
26
|
+
if do_fork
|
27
|
+
return exec_fork(context)
|
28
|
+
else
|
29
|
+
return exec_nofork(context)
|
30
|
+
end
|
31
|
+
ensure
|
32
|
+
context.log_timing("execution_time", start)
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
@@ -2,18 +2,19 @@ require 'ocular/inputs/handlers.rb'
|
|
2
2
|
require 'ocular/event/eventbase.rb'
|
3
3
|
require 'ocular/inputs/http_input.rb'
|
4
4
|
require 'ocular/inputs/cron_input.rb'
|
5
|
+
require 'ocular/inputs/trigger_input.rb'
|
5
6
|
|
6
7
|
class Ocular
|
7
8
|
module Event
|
8
9
|
class DefinitionProxy
|
9
10
|
attr_accessor :events
|
10
|
-
attr_reader :script_name, :do_fork
|
11
|
+
attr_reader :script_name, :do_fork, :logger
|
11
12
|
attr_accessor :handlers, :events
|
12
13
|
|
13
14
|
def initialize(script_name, handlers)
|
14
15
|
@script_name = script_name
|
15
16
|
@events = {}
|
16
|
-
@logger = Ocular::
|
17
|
+
@logger = Ocular::Logging::ConsoleLogger.new
|
17
18
|
@handlers = handlers
|
18
19
|
@do_fork = true
|
19
20
|
end
|
@@ -26,14 +27,14 @@ class Ocular
|
|
26
27
|
|
27
28
|
include Ocular::Inputs::HTTP::DSL
|
28
29
|
include Ocular::Inputs::Cron::DSL
|
30
|
+
include Ocular::Inputs::Trigger::DSL
|
29
31
|
|
30
32
|
def fork(value)
|
31
33
|
@do_fork = value
|
32
34
|
end
|
33
35
|
|
34
36
|
def onEvent(type, &block)
|
35
|
-
eventbase = Ocular::DSL::EventBase.new(&block)
|
36
|
-
eventbase.proxy = self
|
37
|
+
eventbase = Ocular::DSL::EventBase.new(self, &block)
|
37
38
|
(@events["onEvent"] ||= {})[type] = eventbase
|
38
39
|
end
|
39
40
|
end
|
@@ -17,7 +17,7 @@ class Ocular
|
|
17
17
|
add_event_help "cron.cron(rule)", "Schedule event with cron syntax. eg: '5 0 * * *'"
|
18
18
|
def cron()
|
19
19
|
handler = handlers.get(::Ocular::Inputs::Cron::Input)
|
20
|
-
return Input::DSLProxy.new(self, handler)
|
20
|
+
return Input::DSLProxy.new(self, handler, logger)
|
21
21
|
end
|
22
22
|
|
23
23
|
end
|
@@ -43,17 +43,18 @@ class Ocular
|
|
43
43
|
end
|
44
44
|
|
45
45
|
class DSLProxy
|
46
|
-
def initialize(proxy, handler)
|
46
|
+
def initialize(proxy, handler, logger)
|
47
47
|
@proxy = proxy
|
48
48
|
@handler = handler
|
49
|
+
@logger = logger
|
49
50
|
end
|
50
51
|
|
51
52
|
def in(rule, &block)
|
52
|
-
eventbase = Ocular::DSL::EventBase.new(&block)
|
53
|
-
eventbase.proxy = @proxy
|
53
|
+
eventbase = Ocular::DSL::EventBase.new(@proxy, &block)
|
54
54
|
|
55
55
|
id = @handler.scheduler.in(rule) do
|
56
|
-
context = ::Ocular::DSL::RunContext.new
|
56
|
+
context = ::Ocular::DSL::RunContext.new(@logger)
|
57
|
+
context.log_cause("cron.in", {:rule => rule})
|
57
58
|
eventbase.exec(context)
|
58
59
|
end
|
59
60
|
|
@@ -63,11 +64,11 @@ class Ocular
|
|
63
64
|
end
|
64
65
|
|
65
66
|
def at(rule, &block)
|
66
|
-
eventbase = Ocular::DSL::EventBase.new(&block)
|
67
|
-
eventbase.proxy = @proxy
|
67
|
+
eventbase = Ocular::DSL::EventBase.new(@proxy, &block)
|
68
68
|
|
69
69
|
id = @handler.scheduler.at(rule) do
|
70
|
-
context = ::Ocular::DSL::RunContext.new
|
70
|
+
context = ::Ocular::DSL::RunContext.new(@logger)
|
71
|
+
context.log_cause("cron.at", {:rule => rule})
|
71
72
|
eventbase.exec(context)
|
72
73
|
end
|
73
74
|
|
@@ -77,11 +78,11 @@ class Ocular
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def every(rule, &block)
|
80
|
-
eventbase = Ocular::DSL::EventBase.new(&block)
|
81
|
-
eventbase.proxy = @proxy
|
81
|
+
eventbase = Ocular::DSL::EventBase.new(@proxy, &block)
|
82
82
|
|
83
83
|
id = @handler.scheduler.every(rule) do
|
84
|
-
context = ::Ocular::DSL::RunContext.new
|
84
|
+
context = ::Ocular::DSL::RunContext.new(@logger)
|
85
|
+
context.log_cause("cron.every", {:rule => rule})
|
85
86
|
eventbase.exec(context)
|
86
87
|
end
|
87
88
|
|
@@ -91,11 +92,11 @@ class Ocular
|
|
91
92
|
end
|
92
93
|
|
93
94
|
def cron(rule, &block)
|
94
|
-
eventbase = Ocular::DSL::EventBase.new(&block)
|
95
|
-
eventbase.proxy = @proxy
|
95
|
+
eventbase = Ocular::DSL::EventBase.new(@proxy, &block)
|
96
96
|
|
97
97
|
id = @handler.scheduler.cron(rule) do
|
98
|
-
context = ::Ocular::DSL::RunContext.new
|
98
|
+
context = ::Ocular::DSL::RunContext.new(@logger)
|
99
|
+
context.log_cause("cron.cron", {:rule => rule})
|
99
100
|
eventbase.exec(context)
|
100
101
|
end
|
101
102
|
|
@@ -43,7 +43,7 @@ class Ocular
|
|
43
43
|
attr_accessor :request, :response, :params, :env
|
44
44
|
|
45
45
|
def initialize()
|
46
|
-
super()
|
46
|
+
super(Ocular::Logging::ConsoleLogger.new)
|
47
47
|
@headers = {}
|
48
48
|
end
|
49
49
|
|
@@ -268,15 +268,25 @@ class Ocular
|
|
268
268
|
end
|
269
269
|
|
270
270
|
def route(verb, path, options, proxy, &block)
|
271
|
-
eventbase = Ocular::DSL::EventBase.new(&block)
|
272
|
-
eventbase.proxy = proxy
|
271
|
+
eventbase = Ocular::DSL::EventBase.new(proxy, &block)
|
273
272
|
(proxy.events[verb] ||= {})[path] = eventbase
|
274
273
|
|
275
274
|
pattern, keys = compile(path)
|
276
275
|
|
277
276
|
(@routes[verb] ||= []) << build_signature(pattern, keys) do |context|
|
278
|
-
context.event_signature = [verb, path]
|
279
|
-
eventbase.exec(context)
|
277
|
+
context.event_signature = [verb, path]
|
278
|
+
response = eventbase.exec(context)
|
279
|
+
environment = {
|
280
|
+
:path => path,
|
281
|
+
:options => options,
|
282
|
+
:request => context.request,
|
283
|
+
:params => context.params,
|
284
|
+
:env => context.env,
|
285
|
+
:response => response
|
286
|
+
}
|
287
|
+
context.log_cause("on#{verb}", environment)
|
288
|
+
|
289
|
+
response
|
280
290
|
end
|
281
291
|
end
|
282
292
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
require 'ocular/inputs/base.rb'
|
3
|
+
require 'ocular/dsl/dsl.rb'
|
4
|
+
require 'ocular/dsl/runcontext.rb'
|
5
|
+
require 'rufus/scheduler'
|
6
|
+
|
7
|
+
class Ocular
|
8
|
+
module Inputs
|
9
|
+
|
10
|
+
module Trigger
|
11
|
+
|
12
|
+
module DSL
|
13
|
+
|
14
|
+
def onTrigger(evaluator, &block)
|
15
|
+
handler = handlers.get(::Ocular::Inputs::Trigger::Input)
|
16
|
+
|
17
|
+
eventbase = Ocular::DSL::EventBase.new(@proxy, &block)
|
18
|
+
|
19
|
+
id = handler.add_evaluator(evaluator) do
|
20
|
+
context = ::Ocular::DSL::RunContext.new(@logger)
|
21
|
+
eventbase.exec(context)
|
22
|
+
end
|
23
|
+
|
24
|
+
@proxy.events[id] = eventbase
|
25
|
+
|
26
|
+
return id
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class Input < ::Ocular::Inputs::Base
|
32
|
+
|
33
|
+
attr_reader :routes
|
34
|
+
attr_reader :scheduler
|
35
|
+
|
36
|
+
def initialize(settings_factory)
|
37
|
+
settings = settings_factory[:http]
|
38
|
+
@scheduler = ::Rufus::Scheduler.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def start()
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_evaluator(evaluator, &block)
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def stop()
|
50
|
+
@scheduler.shutdown
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
|
2
|
+
class Ocular
|
3
|
+
module Logging
|
4
|
+
|
5
|
+
# Most of the Logger class is copied from the Ruby Logger class source code.
|
6
|
+
class ConsoleLogger
|
7
|
+
|
8
|
+
def initialize(settings=nil)
|
9
|
+
@level = Severity::INFO
|
10
|
+
@formatter = Formatter.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(severity, message = nil, run_id = nil, &block)
|
14
|
+
severity ||= Severity::UNKNOWN
|
15
|
+
if severity < @level
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
if message.nil?
|
20
|
+
if block_given?
|
21
|
+
message = yield
|
22
|
+
else
|
23
|
+
message = progname
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
puts @formatter.format_message(severity, Time.now, message)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def log_event(property, value, run_id = nil)
|
32
|
+
puts @formatter.format_event(property, value, Time.now)
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def log_cause(type, environment, run_id = nil)
|
37
|
+
if @level == Severity::DEBUG
|
38
|
+
puts @formatter.format_cause(type, environment, Time.now)
|
39
|
+
end
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def log_timing(key, value, run_id = nil)
|
44
|
+
puts @formatter.format_timing(key, value, Time.now)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
# Default formatter for log messages.
|
49
|
+
class Formatter
|
50
|
+
Format = "[%s#%d] %s -- %s\n".freeze
|
51
|
+
EventFormat = "[%s#%d] -- %s: %s\n".freeze
|
52
|
+
CauseFormat = "[%s#%d] -- %s triggered processing with environment: %s\n".freeze
|
53
|
+
TimingFormat = "[%s#%d] -- %s took %s ms\n".freeze
|
54
|
+
|
55
|
+
attr_accessor :datetime_format
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@datetime_format = nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def format_message(severity, time, msg)
|
62
|
+
Format % [format_datetime(time), $$, Ocular::Logging::Severity::LABELS[severity], msg2str(msg)]
|
63
|
+
end
|
64
|
+
|
65
|
+
def format_event(property, value, time)
|
66
|
+
EventFormat % [format_datetime(time), $$, property, value]
|
67
|
+
end
|
68
|
+
|
69
|
+
def format_cause(type, environment, time)
|
70
|
+
CauseFormat % [format_datetime(time), $$, type, environment.to_json]
|
71
|
+
end
|
72
|
+
|
73
|
+
def format_timing(key, value, time)
|
74
|
+
TimingFormat % [format_datetime(time), $$, key, value]
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def format_datetime(time)
|
80
|
+
time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
|
81
|
+
end
|
82
|
+
|
83
|
+
def msg2str(msg)
|
84
|
+
case msg
|
85
|
+
when ::String
|
86
|
+
msg
|
87
|
+
when ::Exception
|
88
|
+
"#{ msg.message } (#{ msg.class })\n" <<
|
89
|
+
(msg.backtrace || []).join("\n")
|
90
|
+
else
|
91
|
+
msg.inspect
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "kafka"
|
2
|
+
|
3
|
+
class Ocular
|
4
|
+
module Logging
|
5
|
+
|
6
|
+
# Most of the Logger class is copied from the Ruby Logger class source code.
|
7
|
+
class KafkaLogger
|
8
|
+
|
9
|
+
def initialize(settings=nil, kafka=nil)
|
10
|
+
@level = Severity::DEBUG
|
11
|
+
@formatter = Formatter.new
|
12
|
+
|
13
|
+
if kafka != nil
|
14
|
+
@kafka = kafka
|
15
|
+
else
|
16
|
+
@kafka = Kafka.new(settings)
|
17
|
+
end
|
18
|
+
@settings = settings
|
19
|
+
|
20
|
+
@producer = @kafka.producer
|
21
|
+
end
|
22
|
+
|
23
|
+
def add(severity, message = nil, run_id = nil, &block)
|
24
|
+
severity ||= Severity::UNKNOWN
|
25
|
+
if severity < @level
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
|
29
|
+
if message.nil?
|
30
|
+
if block_given?
|
31
|
+
message = yield
|
32
|
+
else
|
33
|
+
message = progname
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
@producer.produce(@formatter.format_message(severity, Time.now, run_id, message), topic: @settings[:topic], partition_key: run_id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def log_event(property, value, run_id = nil)
|
41
|
+
@producer.produce(@formatter.format_event(property, value, Time.now, run_id), topic: @settings[:topic], partition_key: run_id)
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_cause(type, environment, run_id = nil)
|
45
|
+
@producer.produce(@formatter.format_cause(type, environment, Time.now, run_id), topic: @settings[:topic], partition_key: run_id)
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_timing(key, value, run_id = nil)
|
49
|
+
@producer.produce(@formatter.format_event("timing:" + key, value, Time.now, run_id), topic: @settings[:topic], partition_key: run_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Default formatter for log messages.
|
53
|
+
class Formatter
|
54
|
+
Format = "%s, [%s#%d] %5s -- %s: %s\n".freeze
|
55
|
+
|
56
|
+
attr_accessor :datetime_format
|
57
|
+
|
58
|
+
def initialize
|
59
|
+
@datetime_format = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def format_message(severity, time, progname, msg)
|
63
|
+
data = {
|
64
|
+
"level" => Ocular::Logging::Severity::LABELS[severity],
|
65
|
+
"ts" => format_datetime(time),
|
66
|
+
"run_id" => progname,
|
67
|
+
"msg" => msg2str(msg)
|
68
|
+
}
|
69
|
+
return data.to_json
|
70
|
+
end
|
71
|
+
|
72
|
+
def format_event(property, value, time, progname)
|
73
|
+
data = {
|
74
|
+
"ts" => format_datetime(time),
|
75
|
+
"run_id" => progname,
|
76
|
+
}
|
77
|
+
data[property] = value
|
78
|
+
return data.to_json
|
79
|
+
end
|
80
|
+
|
81
|
+
def format_cause(type, environment, time, progname)
|
82
|
+
data = {
|
83
|
+
"ts" => format_datetime(time),
|
84
|
+
"run_id" => progname,
|
85
|
+
"triggered_by" => type,
|
86
|
+
"environment" => environment
|
87
|
+
}
|
88
|
+
|
89
|
+
return data.to_json
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def format_datetime(time)
|
95
|
+
time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
|
96
|
+
end
|
97
|
+
|
98
|
+
def msg2str(msg)
|
99
|
+
case msg
|
100
|
+
when ::String
|
101
|
+
msg
|
102
|
+
when ::Exception
|
103
|
+
"#{ msg.message } (#{ msg.class })\n" <<
|
104
|
+
(msg.backtrace || []).join("\n")
|
105
|
+
else
|
106
|
+
msg.inspect
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
class Ocular
|
5
|
+
module Logging
|
6
|
+
class MultiLogger
|
7
|
+
attr_reader :loggers
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@loggers = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_logger(logger)
|
14
|
+
@loggers << logger
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(severity, message = nil, run_id = nil, &block)
|
18
|
+
|
19
|
+
if message.nil?
|
20
|
+
if block_given?
|
21
|
+
message = yield
|
22
|
+
else
|
23
|
+
message = "N/A"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@loggers.each do |logger|
|
28
|
+
logger.add(severity, message, run_id)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def log_event(property, value, run_id)
|
34
|
+
@loggers.each do |logger|
|
35
|
+
logger.log_event(property, value, run_id)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def log_cause(type, environment, run_id)
|
40
|
+
@loggers.each do |logger|
|
41
|
+
logger.log_cause(type, environment, run_id)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def log_timing(key, value, run_id)
|
46
|
+
@loggers.each do |logger|
|
47
|
+
logger.log_timing(key, value, run_id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class Ocular
|
4
|
+
module Logging
|
5
|
+
# Logging severity.
|
6
|
+
module Severity
|
7
|
+
LABELS = %w(DEBUG INFO WARN ERROR FATAL ANY).each(&:freeze).freeze
|
8
|
+
|
9
|
+
# Low-level information, mostly for developers.
|
10
|
+
DEBUG = 0
|
11
|
+
# Generic (useful) information about system operation.
|
12
|
+
INFO = 1
|
13
|
+
# A warning.
|
14
|
+
WARN = 2
|
15
|
+
# A handleable error condition.
|
16
|
+
ERROR = 3
|
17
|
+
# An unhandleable error that results in a program crash.
|
18
|
+
FATAL = 4
|
19
|
+
# An unknown message that should always be logged.
|
20
|
+
UNKNOWN = 5
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ocular/ocular.rb
CHANGED
data/lib/ocular/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ocular
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juho Mäkinen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rye
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 3.2.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: ruby-kafka
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.3.2
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.3.2
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: rspec
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -169,6 +183,12 @@ files:
|
|
169
183
|
- lib/ocular/inputs/cron_input.rb
|
170
184
|
- lib/ocular/inputs/handlers.rb
|
171
185
|
- lib/ocular/inputs/http_input.rb
|
186
|
+
- lib/ocular/inputs/trigger_input.rb
|
187
|
+
- lib/ocular/logging/console_logger.rb
|
188
|
+
- lib/ocular/logging/kafka_logger.rb
|
189
|
+
- lib/ocular/logging/logging.rb
|
190
|
+
- lib/ocular/logging/multilogger.rb
|
191
|
+
- lib/ocular/logging/severity.rb
|
172
192
|
- lib/ocular/mixin/from_file.rb
|
173
193
|
- lib/ocular/ocular.rb
|
174
194
|
- lib/ocular/settings.rb
|