acception-subscriber 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 77f56d09784b6c9d77a986455b5f18f8a0ae55e7
4
+ data.tar.gz: 46026ce3b88d330b1aaf6d89027ba948365f71e3
5
+ SHA512:
6
+ metadata.gz: caa67f69a4f6f13b3dfd5904e2aada8ebb9adfb5c38f0959df561871128c1d7012ea37aa4eb3cb6f2e172293132945ac914537aa1834ecbed0373ef3c61cb034
7
+ data.tar.gz: b6d0c9e860e241b3c7c08f275a7460b1547500e5aaea1412087b58ebb130fe2223d7860e8f8650be9c5be676890f58305303f4d335edc75fc12f28ed3489c6b6
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
@@ -0,0 +1 @@
1
+ acception-subscriber
@@ -0,0 +1 @@
1
+ 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+ source 'http://dev.staging.iberon.com/gemserver'
3
+
4
+ # Specify your gem's dependencies in replication-subscriber.gemspec
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'rake-iberon', '~> 1', require: false
9
+ end
10
+
11
+ #gem 'acception-client', path: '../acception-client'
@@ -0,0 +1,3 @@
1
+ Copyright (c) 2014 Iberon, LLC
2
+
3
+ No license granted
@@ -0,0 +1,21 @@
1
+ # Acception::Subscriber
2
+
3
+ A RabbitMQ subscriber that pushes messages to Acception's API.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'acception-subscriber'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install acception-subscriber
19
+
20
+ ## Usage
21
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'acception/subscriber/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "acception-subscriber"
8
+ spec.version = Acception::Subscriber::VERSION
9
+ spec.authors = ["C. Jason Harrelson"]
10
+ spec.email = ["cjharrelson@iberon.com"]
11
+ spec.summary = %q{A RabbitMQ subscriber that pushes messages to Acception's API.}
12
+ spec.description = %q{A RabbitMQ subscriber that pushes messages to Acception's API. See README for more details.}
13
+ spec.homepage = "https://gitlab.staging.iberon.com/common/acception-subscriber"
14
+ spec.license = ""
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency "acception-client", ">= 1.2"
25
+ spec.add_dependency "bunny", "~> 1"
26
+ spec.add_dependency "celluloid", "~> 0"
27
+ spec.add_dependency "multi_json", "~> 1"
28
+ spec.add_dependency "oj", "~> 2"
29
+ spec.add_dependency "trollop", "~> 2"
30
+ spec.add_dependency "yell", "~> 1"
31
+
32
+ end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'acception/subscriber/cli'
3
+ $0 = Acception::Subscriber::APP_ID
4
+ Acception::Subscriber::Cli.new( ARGV ).run
@@ -0,0 +1 @@
1
+ require 'acception/subscriber'
@@ -0,0 +1,39 @@
1
+ require 'ansi'
2
+ require "acception/client"
3
+ require "acception/subscriber/version"
4
+
5
+ module Acception
6
+ module Subscriber
7
+
8
+ autoload :Configuration, 'acception/subscriber/configuration'
9
+ autoload :Logging, 'acception/subscriber/logging'
10
+ autoload :MessageHandler, 'acception/subscriber/message_handler'
11
+ autoload :Server, 'acception/subscriber/server'
12
+ autoload :ServerDaemon, 'acception/subscriber/server_daemon'
13
+ autoload :ServerLogging, 'acception/subscriber/server_logging'
14
+
15
+ APP_ID = "acception-sub"
16
+ APP_NAME = "Acception Subscriber"
17
+ COMPANY = "Iberon, LLC"
18
+ INT = "INT"
19
+ TERM = "TERM"
20
+ VERSION_COPYRIGHT = "v#{VERSION} \u00A9#{Time.now.year} #{COMPANY}"
21
+
22
+ def self.configuration
23
+ @configuration ||= Configuration.new
24
+ end
25
+
26
+ def self.configuration=( configuration )
27
+ @configuration = configuration
28
+ end
29
+
30
+ def self.configure
31
+ yield( configuration ) if block_given?
32
+ end
33
+
34
+ class << self
35
+ attr_accessor :logger
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,132 @@
1
+ require 'rubygems'
2
+ require 'acception/subscriber'
3
+ require 'trollop'
4
+ require 'yell'
5
+
6
+ module Acception
7
+ module Subscriber
8
+ class Cli
9
+
10
+ attr_reader :cmd,
11
+ :options
12
+
13
+ SUB_COMMANDS = %w(
14
+ restart
15
+ start
16
+ status
17
+ stop
18
+ )
19
+
20
+ DEFAULT_CONFIG_PATH = "/etc/ncite/#{APP_ID}.conf"
21
+ DEFAULT_LOG_PATH = "/var/log/ncite/#{APP_ID}.log"
22
+ DEFAULT_PID_PATH = "/var/run/ncite/#{APP_ID}.pid"
23
+
24
+ DEFAULT_NUMBER_OF_THREADS = 1
25
+
26
+ def initialize( args )
27
+ Trollop::options do
28
+ version VERSION_COPYRIGHT
29
+ banner <<-EOS
30
+ #{APP_NAME} #{VERSION_COPYRIGHT}
31
+
32
+ Usage:
33
+ #{APP_ID} [command] [options]
34
+
35
+ commands:
36
+ #{SUB_COMMANDS.map { |sub_cmd| " #{sub_cmd}" }.join( "\n" )}
37
+
38
+ (For help with a command: #{APP_ID} [command] -h)
39
+
40
+ options:
41
+ EOS
42
+ stop_on SUB_COMMANDS
43
+ end
44
+
45
+ # Get the sub-command and its options
46
+ #
47
+ @cmd = ARGV.shift || ''
48
+ @options = case( cmd )
49
+ when "restart"
50
+ Trollop::options do
51
+ opt :config, "The path for the config file", :type => String, :short => '-c', :default => DEFAULT_CONFIG_PATH
52
+ opt :log_level, "The log level", :type => String, :default => 'info'
53
+ opt :log_level, "The log level", :type => String, :default => 'info', :short => '-o'
54
+ opt :log, "The path for the log file", :type => String, :short => '-l', :default => DEFAULT_LOG_PATH
55
+ opt :pid, "The path for the PID file", :type => String, :default => DEFAULT_PID_PATH
56
+ opt :threads, "The number of threads", :type => Integer, :default => DEFAULT_NUMBER_OF_THREADS, :short => '-t'
57
+ end
58
+ when "start"
59
+ Trollop::options do
60
+ opt :config, "The path for the config file", :type => String, :short => '-c', :default => DEFAULT_CONFIG_PATH
61
+ opt :interactive, "Execute the server in interactive mode", :short => '-i'
62
+ opt :log_level, "The log level", :type => String, :default => 'info', :short => '-o'
63
+ opt :log, "The path for the log file", :type => String, :short => '-l', :default => DEFAULT_LOG_PATH
64
+ opt :pid, "The path for the PID file", :type => String, :default => DEFAULT_PID_PATH
65
+ opt :threads, "The number of threads", :type => Integer, :default => DEFAULT_NUMBER_OF_THREADS, :short => '-t'
66
+ end
67
+ when "status"
68
+ Trollop::options do
69
+ opt :pid, "The path for the PID file", :type => String, :default => DEFAULT_PID_PATH
70
+ end
71
+ when "stop"
72
+ Trollop::options do
73
+ opt :pid, "The path for the PID file", :type => String, :default => DEFAULT_PID_PATH
74
+ end
75
+ else
76
+ Trollop::die "unknown command #{cmd.inspect}"
77
+ end
78
+
79
+ if cmd == 'start'
80
+ unless options[:interactive]
81
+ Trollop::die( :config, "is required when running as daemon" ) unless options[:config]
82
+ Trollop::die( :log, "is required when running as daemon" ) unless options[:log]
83
+ Trollop::die( :pid, "is required when running as daemon" ) unless options[:pid]
84
+ end
85
+ end
86
+
87
+ if %w(restart status stop).include?( cmd )
88
+ Trollop::die( :pid, "is required" ) unless options[:pid]
89
+ end
90
+ end
91
+
92
+ def run
93
+ send( cmd )
94
+ end
95
+
96
+ protected
97
+
98
+ def start
99
+ if options[:interactive]
100
+ start_interactive
101
+ else
102
+ start_daemon
103
+ end
104
+ end
105
+
106
+ def start_interactive
107
+ server = Acception::Subscriber::Server.new( options.merge( log: nil ))
108
+ server.start
109
+ end
110
+
111
+ def start_daemon
112
+ server = Acception::Subscriber::ServerDaemon.new( options )
113
+ server.start
114
+ end
115
+
116
+ def stop
117
+ server = Acception::Subscriber::ServerDaemon.new( options )
118
+ server.stop
119
+ end
120
+
121
+ def restart
122
+ stop
123
+ start_daemon
124
+ end
125
+
126
+ def status
127
+ Acception::Subscriber::ServerDaemon.new( options ).status
128
+ end
129
+
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,48 @@
1
+ require 'oj'
2
+
3
+ module Acception
4
+ module Subscriber
5
+ class Configuration
6
+
7
+ def self.attributes
8
+ %w(
9
+ acception_auth_token
10
+ acception_url
11
+ host_uri
12
+ queue
13
+ )
14
+ end
15
+
16
+ attr_accessor( *attributes )
17
+
18
+ def self.from_file( file_path )
19
+ options = Oj.load( File.read( file_path ))
20
+ Acception::Subscriber.configuration = Configuration.new
21
+
22
+ attributes.each do |c|
23
+ if options[c]
24
+ Acception::Subscriber.configuration.send( :"#{c}=", options[c] )
25
+ end
26
+ end
27
+ end
28
+
29
+ def acception_auth_token
30
+ @acception_auth_token || "00-6TKIMQF4NZA"
31
+ end
32
+
33
+ def acception_url
34
+ @acception_url || "http://localhost:3004"
35
+ end
36
+
37
+ def host_uri
38
+ @host_uri || "amqp://guest:guest@127.0.0.1:5672"
39
+ end
40
+
41
+ def queue
42
+ #@queue || "error-repo"
43
+ @queue || "error"
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module Acception
2
+ module Subscriber
3
+ module Logging
4
+
5
+ %w(
6
+ debug
7
+ error
8
+ fatal
9
+ info
10
+ warn
11
+ ).each do |level|
12
+
13
+ define_method level do |*messages|
14
+ messages.each do |message|
15
+ Acception::Subscriber.logger.send level, message
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,119 @@
1
+ require 'celluloid/autostart'
2
+ require 'oj'
3
+
4
+ module Acception
5
+ module Subscriber
6
+ class MessageHandler
7
+
8
+ include Celluloid
9
+ include Logging
10
+
11
+ BLANK = '<<blank>>'
12
+ ERROR = 'error'
13
+ LICENSE_VIOLATION = 'license-violation'
14
+ REQUEUE = true
15
+
16
+ def call( options )
17
+ channel = options[:channel]
18
+ delivery_info = options[:delivery_info]
19
+ payload = options[:payload]
20
+ metadata = options[:metadata]
21
+ headers = metadata[:headers]
22
+
23
+ debug ANSI.cyan { 'HEADERS' } + " #{headers}"
24
+ debug ANSI.yellow { 'PAYLOAD' } + " #{payload}"
25
+
26
+ case resolve_type( payload )
27
+ when ERROR
28
+ handle_error( headers )
29
+ when LICENSE_VIOLATION
30
+ handle_license_violation( headers )
31
+ else
32
+ end
33
+
34
+ channel.acknowledge delivery_info.delivery_tag
35
+ rescue => e
36
+ debug ANSI.red { "NACK" } + " #{e.message}"
37
+ debug ANSI.red { "NACK" } + " #{e.backtrace}"
38
+ #channel.nack delivery_info.delivery_tag
39
+ end
40
+
41
+ protected
42
+
43
+ def handle_error( headers )
44
+ exception = headers['exception']
45
+ acception = Acception::Client::OpenMessages::Create.new( message_type: Acception::MessageType::ERROR,
46
+ application: (headers['application'] || BLANK),
47
+ environment: (headers['environment'] || BLANK),
48
+ occurred_at: (headers['occurred_at'] || BLANK),
49
+ message: (exception['message'] || BLANK),
50
+ request_headers: (headers['request_headers'] || BLANK),
51
+ request_parameters: (headers['request_parameters'] || BLANK),
52
+ session: (headers['session'] || BLANK),
53
+ type: (exception['class'] || BLANK),
54
+ stack: (exception['backtrace'] || BLANK) )
55
+ acception.call
56
+ end
57
+
58
+ def handle_license_violation( headers )
59
+ acception = Acception::Client::OpenMessages::Create.new( message_type: Acception::MessageType::LICENSE_VIOLATION,
60
+ application: headers['application'],
61
+ occurred_at: headers['occurred_at'],
62
+ variables: [
63
+ {
64
+ name: 'license-violation-type',
65
+ content: (headers['type'] || BLANK),
66
+ content_type: 'text/plain'
67
+ },
68
+ {
69
+ name: 'license-content',
70
+ content: (headers['content'] || BLANK),
71
+ content_type: 'application/base64'
72
+ },
73
+ {
74
+ name: 'nonce',
75
+ content: (headers['nonce'] || BLANK),
76
+ content_type: 'application/base64'
77
+ },
78
+ {
79
+ name: 'site-private-key',
80
+ content: (headers['site_private_key'] || BLANK),
81
+ content_type: 'application/base64'
82
+ },
83
+ {
84
+ name: 'iberon-public-key',
85
+ content: (headers['iiberon_public_key'] || BLANK),
86
+ content_type: 'application/base64'
87
+ }
88
+ ])
89
+ acception.call
90
+ end
91
+
92
+ def resolve_type( payload )
93
+ return ERROR if payload == ERROR
94
+ return LICENSE_VIOLATION if payload == LICENSE_VIOLATION
95
+ return nil
96
+ end
97
+
98
+ #def handle_error( channel, payload, e )
99
+ #error( ANSI.red { e.message + " | " + e.backtrace.inspect } )
100
+ #error_queue( channel ).publish( payload, headers: { application: Acception::Subscriber::APP_ID,
101
+ #exception_message: e.message,
102
+ #exception_class: e.class.name,
103
+ #exception_backtrace: e.backtrace } )
104
+ #rescue => ex
105
+ #error( ANSI.red { ex.message + " | " + ex.backtrace.inspect } )
106
+ #end
107
+
108
+ #def requeue( channel, delivery_info, e=nil )
109
+ #debug ANSI.yellow { 'REQUEUE ' + e.message }
110
+ #channel.reject delivery_info.delivery_tag, REQUEUE
111
+ #end
112
+
113
+ def config
114
+ Acception::Subscriber.configuration
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,7 @@
1
+ module Acception
2
+ module Subscriber
3
+ class PublishError < RuntimeError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,118 @@
1
+ require 'bunny'
2
+ require 'celluloid'
3
+
4
+ module Acception
5
+ module Subscriber
6
+ class Server
7
+
8
+ include ServerLogging
9
+ include Logging
10
+
11
+ attr_reader :message_consumer,
12
+ :options
13
+
14
+ def initialize( options )
15
+ @options = options
16
+
17
+ configure_server
18
+ end
19
+
20
+ def start
21
+ log_startup
22
+ run
23
+
24
+ trap( INT ) { finalize; exit }
25
+ sleep
26
+ end
27
+
28
+ protected
29
+
30
+ def finalize
31
+ info "SHUTTING DOWN"
32
+ message_consumer.cancel
33
+ mq.close
34
+ end
35
+
36
+ def mq
37
+ @mq ||= Bunny.new( host_uri ).tap do |bunny|
38
+ bunny.start
39
+ end
40
+ end
41
+
42
+ def channel
43
+ @channel ||= mq.create_channel
44
+ end
45
+
46
+ def queue
47
+ @queue ||= channel.queue( config.queue,
48
+ durable: true )
49
+ end
50
+
51
+ def pool
52
+ @pool ||= MessageHandler.pool( size: options[:threads] )
53
+ end
54
+
55
+ def run
56
+ if options[:threads] == 1
57
+ Celluloid::Actor[:message_handler] = MessageHandler.new
58
+ end
59
+
60
+ @message_consumer = queue.subscribe( manual_ack: true ) do |delivery_info, metadata, payload|
61
+ debug ANSI.magenta { "LISTENER RECEIVED #{payload}" }
62
+
63
+ if options[:threads] > 1
64
+ pool.async.call( payload: payload,
65
+ delivery_info: delivery_info,
66
+ metadata: metadata,
67
+ channel: channel )
68
+ else
69
+ message_handler.call( payload: payload,
70
+ delivery_info: delivery_info,
71
+ metadata: metadata,
72
+ channel: channel )
73
+ end
74
+ end
75
+ end
76
+
77
+ def message_handler
78
+ Celluloid::Actor[:message_handler]
79
+ end
80
+
81
+ def host_uri
82
+ config.host_uri
83
+ end
84
+
85
+ def config
86
+ Acception::Subscriber.configuration
87
+ end
88
+
89
+ def configure_server
90
+ load_configuration
91
+ configure_acception
92
+ initialize_loggers
93
+ end
94
+
95
+ def load_configuration
96
+ if File.exists?( options[:config] )
97
+ options[:config_loaded] = true
98
+ Configuration.from_file( options[:config] )
99
+ end
100
+ end
101
+
102
+ def configure_acception
103
+ Acception::Client.configure do |c|
104
+ c.authentication_token = config.acception_auth_token
105
+ c.base_url = config.acception_url
106
+ #c.graceful_errors_map = ServiceErrorHandling::GRACEFUL_ERRORS_MAP
107
+ c.logger = Acception::Subscriber.logger
108
+ #c.log_level = options.fetch( :log_level, :info ).to_sym
109
+ c.open_timeout_in_seconds = 10
110
+ c.read_timeout_in_seconds = 20
111
+ #c.retry_attempts = configatron.iols.retry_attempts.to_i || 1
112
+ #c.retry_sleep = configatron.iols.retry_sleep || false
113
+ end
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,146 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'timeout'
4
+
5
+ module Acception
6
+ module Subscriber
7
+ class ServerDaemon
8
+
9
+ attr_reader :name,
10
+ :options,
11
+ :pid,
12
+ :pid_path,
13
+ :script,
14
+ :timeout
15
+
16
+ def initialize( options )
17
+ @options = options
18
+ @name = options[:name] || APP_NAME
19
+ @pid_path = options[:pid] || '.'
20
+ @pid = get_pid
21
+ @timeout = options[:timeout] || 10
22
+ end
23
+
24
+ def start
25
+ abort "Process already running!" if process_exists?
26
+
27
+ pid = fork do
28
+ exit if fork
29
+ Process.setsid
30
+ exit if fork
31
+ store_pid( Process.pid )
32
+ File.umask 0000
33
+ redirect_output!
34
+ run
35
+ end
36
+
37
+ Process.waitpid( pid )
38
+ end
39
+
40
+ def run
41
+ Server.new( options ).start
42
+ end
43
+
44
+ def stop
45
+ kill_process
46
+ FileUtils.rm pid_path
47
+ end
48
+
49
+ def status
50
+ out = "#{APP_NAME} "
51
+ if process_exists?
52
+ out << "process running with PID: #{pid}"
53
+ else
54
+ out << "process does not exist"
55
+ end
56
+ $stdout.puts out
57
+ end
58
+
59
+ protected
60
+
61
+ #def create_pid( pid )
62
+ def store_pid( pid )
63
+ File.open( pid_path, 'w' ) do |f|
64
+ f.puts pid
65
+ end
66
+ rescue => e
67
+ $stderr.puts "Unable to open #{pid_path} for writing:\n\t(#{e.class}) #{e.message}"
68
+ exit!
69
+ end
70
+
71
+ def get_pid
72
+ return nil unless File.exists?( pid_path )
73
+ pid = nil
74
+ File.open( @pid_path, 'r' ) do |f|
75
+ pid = f.readline.to_s.gsub( /[^0-9]/, '' )
76
+ end
77
+ pid.to_i
78
+ rescue Errno::ENOENT
79
+ nil
80
+ end
81
+
82
+ def remove_pidfile
83
+ File.unlink( pid_path )
84
+ rescue => e
85
+ $stderr.puts "Unable to unlink #{pid_path}:\n\t(#{e.class}) #{e.message}"
86
+ exit
87
+ end
88
+
89
+ def kill_process
90
+ abort "#{APP_NAME} process is not running" unless process_exists?
91
+ $stdout.write "Attempting to stop #{APP_NAME} process #{pid}..."
92
+ Process.kill INT, pid
93
+ iteration_num = 0
94
+ while process_exists? && iteration_num < 10
95
+ sleep 1
96
+ $stdout.write "."
97
+ iteration_num += 1
98
+ end
99
+ if process_exists?
100
+ $stderr.puts "\nFailed to stop #{APP_NAME} process #{pid}"
101
+ else
102
+ $stdout.puts "\nSuccessfuly stopped #{APP_NAME} process #{pid}"
103
+ end
104
+ rescue Errno::EPERM
105
+ $stderr.puts "No permission to query #{pid}!";
106
+ end
107
+
108
+ def process_exists?
109
+ return false unless pid
110
+ Process.kill( 0, pid )
111
+ true
112
+ rescue Errno::ESRCH, TypeError # "PID is NOT running or is zombied
113
+ false
114
+ rescue Errno::EPERM
115
+ $stderr.puts "No permission to query #{pid}!";
116
+ false
117
+ end
118
+
119
+ def redirect_output!
120
+ if log_path = options[:log]
121
+ #puts "redirecting to log"
122
+ # if the log directory doesn't exist, create it
123
+ FileUtils.mkdir_p( File.dirname( log_path ), :mode => 0755 )
124
+ # touch the log file to create it
125
+ FileUtils.touch( log_path )
126
+ # Set permissions on the log file
127
+ File.chmod( 0644, log_path )
128
+ # Reopen $stdout (NOT +STDOUT+) to start writing to the log file
129
+ $stdout.reopen( log_path, 'a' )
130
+ # Redirect $stderr to $stdout
131
+ $stderr.reopen $stdout
132
+ $stdout.sync = true
133
+ else
134
+ #puts "redirecting to /dev/null"
135
+ # We're not bothering to sync if we're dumping to /dev/null
136
+ # because /dev/null doesn't care about buffered output
137
+ $stdin.reopen '/dev/null'
138
+ $stdout.reopen '/dev/null', 'a'
139
+ $stderr.reopen $stdout
140
+ end
141
+ log_path = options[:log] ? options[:log] : '/dev/null'
142
+ end
143
+
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,81 @@
1
+ require 'yell'
2
+
3
+ # Provides logging services for the base server.
4
+ #
5
+ module Acception
6
+ module Subscriber
7
+ module ServerLogging
8
+
9
+ protected
10
+
11
+ def initialize_loggers
12
+ Acception::Subscriber.logger = Yell.new do |l|
13
+ l.level = log_level
14
+ l.adapter $stdout, :level => [:debug, :info, :warn]
15
+ l.adapter $stderr, :level => [:error, :fatal]
16
+ end
17
+
18
+ #Celluloid.logger = Yell.new do |l|
19
+ #l.level = :info
20
+ #l.adapter :file, File.join( File.dirname( options[:log] ), "#{APP_ID}-celluloid.log" )
21
+ #end
22
+ end
23
+
24
+ def log_startup
25
+ start_banner( options ).each do |line|
26
+ Acception::Subscriber.logger.info line
27
+ end
28
+ end
29
+
30
+ def start_banner( options )
31
+ [
32
+ "",
33
+ "***",
34
+ "* #{APP_NAME} started",
35
+ "*",
36
+ "* #{VERSION_COPYRIGHT}",
37
+ "*",
38
+ "* Configuration:",
39
+ (options[:config_loaded] ? "* file: #{options[:config]}" : nil),
40
+ Acception::Subscriber::Configuration.attributes.map { |a| "* #{a}: #{config_value( a )}" },
41
+ "*",
42
+ "***",
43
+ ].flatten.reject( &:nil? )
44
+ end
45
+
46
+ def log_level
47
+ options.fetch( :log_level, :info ).to_sym
48
+ end
49
+
50
+
51
+ def config_value( key )
52
+ value = Acception::Subscriber.configuration.send( key )
53
+
54
+ return value unless value.is_a?( Hash )
55
+
56
+ return redacted_hash( value )
57
+ end
58
+
59
+ def redacted_hash( hash )
60
+ redacted_hash = {}
61
+
62
+ hash.keys.
63
+ collect( &:to_s ).
64
+ grep( /#{redacted_keys}/i ).
65
+ each do |blacklisted_key|
66
+ value = hash[blacklisted_key]
67
+ redacted_hash[blacklisted_key] = value.nil? ? nil : '[REDACTED]'
68
+ end
69
+
70
+ hash.merge( redacted_hash )
71
+ end
72
+
73
+ def redacted_keys
74
+ %w(
75
+ password
76
+ ).join( '|' )
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,7 @@
1
+ module Acception
2
+ module Subscriber
3
+
4
+ VERSION = "1.0.0"
5
+
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acception-subscriber
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - C. Jason Harrelson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: acception-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bunny
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: celluloid
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: multi_json
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: oj
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: trollop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2'
125
+ - !ruby/object:Gem::Dependency
126
+ name: yell
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1'
139
+ description: A RabbitMQ subscriber that pushes messages to Acception's API. See README
140
+ for more details.
141
+ email:
142
+ - cjharrelson@iberon.com
143
+ executables:
144
+ - acception-sub
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - ".gitignore"
149
+ - ".ruby-gemset"
150
+ - ".ruby-version"
151
+ - Gemfile
152
+ - LICENSE.txt
153
+ - README.md
154
+ - Rakefile
155
+ - acception-subscriber.gemspec
156
+ - bin/acception-sub
157
+ - lib/acception-subscriber.rb
158
+ - lib/acception/subscriber.rb
159
+ - lib/acception/subscriber/cli.rb
160
+ - lib/acception/subscriber/configuration.rb
161
+ - lib/acception/subscriber/logging.rb
162
+ - lib/acception/subscriber/message_handler.rb
163
+ - lib/acception/subscriber/publish_error.rb
164
+ - lib/acception/subscriber/server.rb
165
+ - lib/acception/subscriber/server_daemon.rb
166
+ - lib/acception/subscriber/server_logging.rb
167
+ - lib/acception/subscriber/version.rb
168
+ homepage: https://gitlab.staging.iberon.com/common/acception-subscriber
169
+ licenses:
170
+ - ''
171
+ metadata: {}
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.2.1
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: A RabbitMQ subscriber that pushes messages to Acception's API.
192
+ test_files: []