startback 0.11.0 → 0.11.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe59e5315c100c9f8c83a100e0a9f538d50946dabdd504db2b5d17ba41738a23
4
- data.tar.gz: 8e12f2e1571e80afe5acc8049e719fb8a06aecfdcb2ba9ed2b1a05fe0941244d
3
+ metadata.gz: fa9e440ddba682a1c59c98a5635b0febafe08222e9cee2de68d3262c6da6d8d4
4
+ data.tar.gz: '09a4748015aa374687c4016341d7f6a699d80718da7f9b4a6449294d69cf7897'
5
5
  SHA512:
6
- metadata.gz: 7f7e1f0aa41d8ca9a1fcdd11a3fcca551b061bbe8dd7bff1dfe03ecad9b3e39f43a6be3abcd3f3915a98ee101979092e376c076d98e6d87e5ce402373d0c9867
7
- data.tar.gz: d06499ef6a32fd68fce71a240649b32e991d8c0b704a6f848ad126f8577a1d707411d781620790cdc3943694ad79153eb364cd96a988184480cc339878df7bf4
6
+ metadata.gz: 6f832ba94f865dfd66c372fcf19623c68f43c76019623fd49da96e88fa2c7355bc78916ae98f3ae32de7e4deb0f08d9ade5d7eb2b3fa9f9bebb5544c0de698d4
7
+ data.tar.gz: 6ec4e88b7f2bc2ffd58d6e0cddb5bfffc5411149b71a97d1a51e7195105bd907568b45afec40f47916c17dbc45dfe81a5e6432781fa821dbdb2b1ba47f614c86
@@ -1,3 +1,4 @@
1
+ require_relative 'shared'
1
2
  require 'prometheus/client'
2
3
 
3
4
  module Startback
@@ -23,6 +24,7 @@ module Startback
23
24
  # input at construction time.
24
25
  #
25
26
  class Prometheus
27
+ include Shared
26
28
 
27
29
  def initialize(options = {})
28
30
  @prefix = options[:prefix] || "startback"
@@ -62,7 +64,6 @@ module Startback
62
64
  def ignore_safely
63
65
  yield
64
66
  rescue => ex
65
- puts ex.class.to_s + "\n" + ex.message + "\n" + ex.backtrace.join("\n")
66
67
  nil
67
68
  end
68
69
 
@@ -81,14 +82,6 @@ module Startback
81
82
  Startback::VERSION
82
83
  end
83
84
 
84
- def op_name(op)
85
- case op
86
- when String then op
87
- when Class then op.name
88
- else op.class.name
89
- end
90
- end
91
-
92
85
  end # class Prometheus
93
86
  end # module Audit
94
87
  end # module Startback
@@ -0,0 +1,17 @@
1
+ module Startback
2
+ module Audit
3
+ module Shared
4
+
5
+ def op_name(op)
6
+ return op.op_name if op.respond_to?(:op_name)
7
+
8
+ case op
9
+ when String then op
10
+ when Class then op.name
11
+ else op.class.name
12
+ end
13
+ end
14
+
15
+ end # module Shared
16
+ end # module Audit
17
+ end # module Startback
@@ -1,3 +1,4 @@
1
+ require_relative 'shared'
1
2
  require 'forwardable'
2
3
  module Startback
3
4
  module Audit
@@ -45,6 +46,7 @@ module Startback
45
46
  # input at construction time.
46
47
  #
47
48
  class Trailer
49
+ include Shared
48
50
  extend Forwardable
49
51
  def_delegators :@logger, :debug, :info, :warn, :error, :fatal
50
52
 
@@ -85,20 +87,14 @@ module Startback
85
87
  log_msg
86
88
  end
87
89
 
88
- def op_name(op)
89
- case op
90
- when String then op
91
- when Class then op.name
92
- else op.class.name
93
- end
94
- end
95
-
96
90
  def op_context(op)
97
91
  sanitize(op.respond_to?(:context, false) ? op.context.to_h : {})
98
92
  end
99
93
 
100
94
  def op_data(op)
101
- data = if op.respond_to?(:to_trail, false)
95
+ data = if op.respond_to?(:op_data, false)
96
+ op.op_data
97
+ elsif op.respond_to?(:to_trail, false)
102
98
  op.to_trail
103
99
  elsif op.respond_to?(:input, false)
104
100
  op.input
@@ -1,2 +1,3 @@
1
+ require_relative 'audit/shared'
1
2
  require_relative 'audit/trailer'
2
3
  require_relative 'audit/prometheus'
@@ -0,0 +1,8 @@
1
+ module Startback
2
+ class Event
3
+ class Agent
4
+ include Support::OperationRunner
5
+
6
+ end # class Agent
7
+ end # class Event
8
+ end # module Starback
@@ -0,0 +1,100 @@
1
+ require 'rack'
2
+ require 'webrick'
3
+ require 'startback'
4
+ module Startback
5
+ class Event
6
+ #
7
+ # This class runs an infinite loop using ServerEngine.
8
+ # It is intended to be used to run jobs that listen to
9
+ # a Startback Bus instance without having the main process
10
+ # terminating immediately.
11
+ #
12
+ # The Engine automatically runs a Webrick small webapp
13
+ # with a /healthcheck webservice. The class can be extended
14
+ # and method `on_health_check` overriden to run specific
15
+ # checks.
16
+ #
17
+ # This class goes hand in hand with the `startback:engine`
18
+ # docker image.
19
+ #
20
+ # Example:
21
+ #
22
+ # # Dockerfile
23
+ # FROM enspirit/startback:engine-0.11
24
+ #
25
+ # # engine.rb
26
+ # require 'startback/event/engine'
27
+ # Startback::Event::Engine.run
28
+ #
29
+ class Engine
30
+
31
+ DEFAULT_OPTIONS = {
32
+ daemonize: false,
33
+ worker_type: 'process',
34
+ workers: 1
35
+ }
36
+
37
+ def initialize
38
+ require 'serverengine'
39
+ end
40
+
41
+ def on_health_check
42
+ "Ok"
43
+ end
44
+
45
+ def run(options = {})
46
+ options = DEFAULT_OPTIONS.merge(options)
47
+ health = Engine.build_health_check(self)
48
+ worker = Engine.build_worker(health)
49
+ se = ServerEngine.create(nil, worker, options)
50
+ se.run
51
+ se
52
+ end
53
+
54
+ class << self
55
+ def run(*args, &bl)
56
+ new.run(*args, &bl)
57
+ end
58
+
59
+ def build_health_check(engine)
60
+ Rack::Builder.new do
61
+ map '/health-check' do
62
+ health = Startback::Web::HealthCheck.new {
63
+ engine.on_health_check
64
+ }
65
+ run(health)
66
+ end
67
+ end
68
+ end
69
+
70
+ def build_worker(health)
71
+ Module.new do
72
+ include Support::Env
73
+
74
+ def initialize
75
+ @stop_flag = ServerEngine::BlockingFlag.new
76
+ end
77
+
78
+ define_method(:health) do
79
+ health
80
+ end
81
+
82
+ def run
83
+ until @stop_flag.set?
84
+ Rack::Handler::WEBrick.run(health, {
85
+ :Port => env('STARTBACK_ENGINE_PORT', '3000').to_i,
86
+ :Host => env('STARTBACK_ENGINE_LISTEN', '0.0.0.0')
87
+ })
88
+ end
89
+ end
90
+
91
+ def stop
92
+ @stop_flag.set!
93
+ Rack::Handler::WEBrick.shutdown
94
+ end
95
+ end
96
+ end
97
+ end # class << self
98
+ end # class Engine
99
+ end # class Event
100
+ end # module Startback
@@ -41,3 +41,5 @@ module Startback
41
41
 
42
42
  end # class Event
43
43
  end # module Startback
44
+ require_relative 'event/agent'
45
+ require_relative 'event/engine'
@@ -0,0 +1,41 @@
1
+ module Startback
2
+ module Support
3
+ # This method provides the `env` and `env!` methods that
4
+ # help querying environment variables easily.
5
+ module Env
6
+
7
+ # Returns an environment variable or raise an error if
8
+ # not set.
9
+ #
10
+ # The result is always a String with no leading/trailing
11
+ # spaces.
12
+ #
13
+ # If a block is given, the environment variable is yield
14
+ # and the result of the block returned.
15
+ def env!(key, default = nil, &bl)
16
+ v = ENV[key].to_s.strip
17
+ raise Startback::Error, "Missing ENV var `#{key}`" if v.empty?
18
+
19
+ env(key, default, &bl)
20
+ end
21
+ module_function :env!
22
+
23
+ # Returns an environment variable or the default value
24
+ # passed as second argument.
25
+ #
26
+ # The result is always a String with no leading/trailing
27
+ # spaces.
28
+ #
29
+ # If a block is given, the environment variable is yield
30
+ # and the result of the block returned.
31
+ def env(key, default = nil, &bl)
32
+ v = ENV[key].to_s.strip
33
+ v = v.empty? ? default : v
34
+ v = bl.call(v) if bl && v
35
+ v
36
+ end
37
+ module_function :env
38
+
39
+ end # module Env
40
+ end # module Support
41
+ end # module Startback
@@ -3,6 +3,8 @@ module Startback
3
3
  class LogFormatter
4
4
 
5
5
  def call(severity, time, progname, msg)
6
+ msg = { message: msg } if msg.is_a?(String)
7
+ msg = { error: msg } if msg.is_a?(Exception)
6
8
  {
7
9
  severity: severity,
8
10
  time: time
@@ -43,7 +43,7 @@ module Startback
43
43
  @@default_logger ||= begin
44
44
  l = ::Logger.new(STDOUT)
45
45
  l.formatter = LogFormatter.new
46
- l.warn(op: "#{self}", op_data: { msg: "Using default logger", trace: caller })
46
+ l.warn(op: "#{self}", op_data: { msg: "Using default logger to STDOUT" })
47
47
  @@default_logger = l
48
48
  end
49
49
  @@default_logger
@@ -67,6 +67,8 @@ module Startback
67
67
  log_msg.dup
68
68
  elsif log_msg.is_a?(String)
69
69
  log_msg = { op: "#{log_msg}#{method.nil? ? '' : '#'+method.to_s}" }
70
+ elsif log_msg.is_a?(Exception)
71
+ log_msg = { error: log_msg }
70
72
  else
71
73
  log_msg = log_msg.class unless log_msg.is_a?(Module)
72
74
  log_msg = { op: "#{log_msg.name}##{method}" }
@@ -14,6 +14,7 @@ module Startback
14
14
 
15
15
  end # module Support
16
16
  end # module Startback
17
+ require_relative 'support/env'
17
18
  require_relative 'support/log_formatter'
18
19
  require_relative 'support/logger'
19
20
  require_relative 'support/robustness'
@@ -2,7 +2,7 @@ module Startback
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 11
5
- TINY = 0
5
+ TINY = 5
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -6,6 +6,7 @@ module Startback
6
6
 
7
7
  set :raise_errors, true
8
8
  set :show_exceptions, false
9
+ set :dump_errors, false
9
10
 
10
11
  protected
11
12
 
@@ -8,13 +8,30 @@ module Startback
8
8
  Trailer.new("/tmp/trail.log")
9
9
  }
10
10
 
11
+ describe "op_name" do
12
+
13
+ def op_name(op, trailer = self.trailer)
14
+ trailer.send(:op_name, op)
15
+ end
16
+
17
+ it 'uses op_name in priority if provided' do
18
+ op = OpenStruct.new(op_name: "foo")
19
+ expect(op_name(op)).to eql("foo")
20
+ end
21
+ end
22
+
11
23
  describe "op_data" do
12
24
 
13
25
  def op_data(op, trailer = self.trailer)
14
26
  trailer.send(:op_data, op)
15
27
  end
16
28
 
17
- it 'uses to_trail in priority if provided' do
29
+ it 'uses op_data in priority if provided' do
30
+ op = OpenStruct.new(op_data: { foo: "bar" }, input: 12, request: 13)
31
+ expect(op_data(op)).to eql({ foo: "bar" })
32
+ end
33
+
34
+ it 'uses to_trail then' do
18
35
  op = OpenStruct.new(to_trail: { foo: "bar" }, input: 12, request: 13)
19
36
  expect(op_data(op)).to eql({ foo: "bar" })
20
37
  end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ module Startback
3
+ module Support
4
+ describe Env do
5
+ include Env
6
+
7
+ before do
8
+ ENV['FOO'] = 'BAR'
9
+ ENV['FOOL'] = ''
10
+ ENV['FOOLISH'] = ' BAR '
11
+ end
12
+
13
+ after do
14
+ ENV.delete('FOO')
15
+ ENV.delete('FOOL')
16
+ end
17
+
18
+ describe "env" do
19
+ it 'returns an env variable' do
20
+ expect(env('FOO')).to eql('BAR')
21
+ end
22
+
23
+ it 'returns nil otherwise' do
24
+ expect(env('BAR')).to be_nil
25
+ end
26
+
27
+ it 'strips the value' do
28
+ expect(env('FOOLISH')).to eql('BAR')
29
+ end
30
+
31
+ it 'yields the block if any' do
32
+ expect(env('FOO'){|x| x.downcase }).to eql('bar')
33
+ end
34
+
35
+ it 'support a default value' do
36
+ expect(env('BAR', 'BAZ')).to eql('BAZ')
37
+ end
38
+
39
+ it 'yields the block with the default if any' do
40
+ expect(env('BAR', 'BAZ'){|x| x.downcase }).to eql('baz')
41
+ end
42
+
43
+ it 'returns nil when empty' do
44
+ expect(env('FOOL')).to be_nil
45
+ end
46
+
47
+ it 'yields the block with the default if empty' do
48
+ expect(env('FOOL', 'BAZ'){|x| x.downcase }).to eql('baz')
49
+ end
50
+ end
51
+
52
+ describe "env!" do
53
+ it 'returns an env variable' do
54
+ expect(env!('FOO')).to eql('BAR')
55
+ end
56
+
57
+ it 'strips the value' do
58
+ expect(env!('FOOLISH')).to eql('BAR')
59
+ end
60
+
61
+ it 'raise otherwise' do
62
+ expect{ env!('BAR') }.to raise_error(Startback::Errors::Error, /BAR/)
63
+ end
64
+
65
+ it 'raise on empty' do
66
+ expect{ env!('FOOL') }.to raise_error(Startback::Errors::Error, /FOOL/)
67
+ end
68
+
69
+ it 'yields the block if any' do
70
+ expect(env('FOO'){|x| x.downcase }).to eql('bar')
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -135,6 +135,16 @@ module Startback
135
135
  expect(logger).to be_a(::Logger)
136
136
  end
137
137
 
138
+ it 'works fine with a Exception only' do
139
+ exception = StandardError.new('hello')
140
+ expected = {
141
+ error: exception
142
+ }
143
+ log_msg, logger = parse_args(exception)
144
+ expect(log_msg).to eql(expected)
145
+ expect(logger).to be_a(::Logger)
146
+ end
147
+
138
148
  it 'works fine with a string and a context with logger' do
139
149
  expected = {
140
150
  op: "a message"
@@ -216,4 +226,4 @@ module Startback
216
226
 
217
227
  end
218
228
  end
219
- end
229
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: startback
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-21 00:00:00.000000000 Z
11
+ date: 2022-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -383,6 +383,7 @@ files:
383
383
  - lib/startback.rb
384
384
  - lib/startback/audit.rb
385
385
  - lib/startback/audit/prometheus.rb
386
+ - lib/startback/audit/shared.rb
386
387
  - lib/startback/audit/trailer.rb
387
388
  - lib/startback/bus.rb
388
389
  - lib/startback/bus/bunny.rb
@@ -397,6 +398,8 @@ files:
397
398
  - lib/startback/context/middleware.rb
398
399
  - lib/startback/errors.rb
399
400
  - lib/startback/event.rb
401
+ - lib/startback/event/agent.rb
402
+ - lib/startback/event/engine.rb
400
403
  - lib/startback/ext.rb
401
404
  - lib/startback/ext/date_time.rb
402
405
  - lib/startback/ext/time.rb
@@ -404,6 +407,7 @@ files:
404
407
  - lib/startback/operation/error_operation.rb
405
408
  - lib/startback/operation/multi_operation.rb
406
409
  - lib/startback/support.rb
410
+ - lib/startback/support/env.rb
407
411
  - lib/startback/support/fake_logger.rb
408
412
  - lib/startback/support/hooks.rb
409
413
  - lib/startback/support/log_formatter.rb
@@ -438,6 +442,7 @@ files:
438
442
  - spec/unit/support/hooks/test_before_hook.rb
439
443
  - spec/unit/support/operation_runner/test_around_run.rb
440
444
  - spec/unit/support/operation_runner/test_before_after_call.rb
445
+ - spec/unit/support/test_env.rb
441
446
  - spec/unit/support/test_robusteness.rb
442
447
  - spec/unit/support/test_transaction_manager.rb
443
448
  - spec/unit/test_event.rb