logasm 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c1c109d32973a0fb0874162679d8c648790698ff
4
+ data.tar.gz: 4187e98a866d2ec61e4232febb84a6832a30c019
5
+ SHA512:
6
+ metadata.gz: da9efd6daf3d43b27e7a16b25c1d858c8d85f19291823cb4d57ba58c86aef7376559a5ea7ce8a9629c54492a0aafafbb5b00487c0f6bf53bbdf993148ebd9244
7
+ data.tar.gz: 0632bf09b2a4079a036ec8a53469b826a8e1a1a562972ed5300e48ce11babd1187cc5b9601bfdb811796c3c6d47d35fd666d1ef21001f325ac475ef9c65772b6
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ npm-debug.log
3
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ logasm
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.2
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :test, :development do
4
+ gem 'rspec'
5
+ gem 'pry'
6
+ end
7
+
8
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ logasm (0.1.0)
5
+ inflecto
6
+ logstash-event (~> 1.2)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ coderay (1.1.0)
12
+ diff-lcs (1.2.5)
13
+ inflecto (0.0.2)
14
+ logstash-event (1.2.02)
15
+ method_source (0.8.2)
16
+ pry (0.10.1)
17
+ coderay (~> 1.1.0)
18
+ method_source (~> 0.8.1)
19
+ slop (~> 3.4)
20
+ rake (10.3.2)
21
+ rspec (3.1.0)
22
+ rspec-core (~> 3.1.0)
23
+ rspec-expectations (~> 3.1.0)
24
+ rspec-mocks (~> 3.1.0)
25
+ rspec-core (3.1.2)
26
+ rspec-support (~> 3.1.0)
27
+ rspec-expectations (3.1.0)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.1.0)
30
+ rspec-mocks (3.1.0)
31
+ rspec-support (~> 3.1.0)
32
+ rspec-support (3.1.0)
33
+ slop (3.6.0)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bundler (~> 1.3)
40
+ logasm!
41
+ pry
42
+ rake
43
+ rspec
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ Logasm
2
+ ================
3
+
4
+ ## Usage
5
+
6
+ ### Creating a new Logasm logger in Ruby
7
+
8
+ ```ruby
9
+ Logasm.build(application_name, logger_config)
10
+ ```
11
+
12
+ <b>application_name</b> is the name of the application. Only logstash logger will use this.
13
+
14
+ <b>logger_config</b> is a hash with logger types and their configuration.
15
+
16
+ #### Configuration
17
+
18
+ ```
19
+ loggers:
20
+ stdout:
21
+ level: 'debug'
22
+ logstash:
23
+ level: 'info'
24
+ host: 'localhost'
25
+ port: 5228
26
+ ```
27
+ Supported log levels:
28
+
29
+ 1. fatal
30
+ 2. error
31
+ 3. warn
32
+ 4. info
33
+ 5. debug
34
+
35
+ For example level: 'warn' will log everything with warn and above.
36
+
37
+ #### Examples
38
+
39
+ Creating a new stdout logger
40
+
41
+ ```ruby
42
+ require 'logasm'
43
+
44
+ logasm = Logasm.build('myApp', stdout: nil)
45
+ ```
46
+
47
+ Creating a new logstash logger
48
+
49
+ ```ruby
50
+ require 'logasm'
51
+
52
+ logasm = Logasm.build('myApp', logstash: { host: "localhost", port: 5228 })
53
+ ```
54
+
55
+ Creating a new logger that logs into stdout and logstash at the same time
56
+
57
+ ```ruby
58
+ require 'logasm'
59
+
60
+ logasm = Logasm.build('myApp', { stdout: nil, logstash: { host: "localhost", port: 5228 }})
61
+ ```
62
+
63
+ When no loggers are specified, it creates a stdout logger by default.
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "rspec/core/rake_task"
2
+ RSpec::Core::RakeTask.new(:spec)
3
+
4
+ task ci: :spec
5
+ task default: :spec
@@ -0,0 +1,35 @@
1
+ class Logasm
2
+ module Adapters
3
+ class LogstashAdapter
4
+ class Formatter < ::Logger::Formatter
5
+ HOST = ::Socket.gethostname
6
+
7
+ def initialize(service_name)
8
+ @service_name = service_name
9
+ end
10
+
11
+ def call(severity, time, _progname, message)
12
+ event = build_event(message, severity, time)
13
+ "#{event.to_json}\n"
14
+ end
15
+
16
+ private
17
+
18
+ def build_event(metadata, level, time)
19
+ event = LogStash::Event.new(metadata.merge("@timestamp" => time))
20
+
21
+ event['application'] = @service_name if @service_name
22
+ event['level'] = level.downcase
23
+ event['host'] ||= HOST
24
+
25
+ # In case Time#to_json has been overridden
26
+ if event.timestamp.is_a?(Time)
27
+ event.timestamp = event.timestamp.iso8601(3)
28
+ end
29
+
30
+ event
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ require 'socket'
2
+ require 'logstash-event'
3
+
4
+ class Logasm
5
+ module Adapters
6
+ class LogstashAdapter
7
+ attr_reader :logger
8
+
9
+ def initialize(level, service, host:, port:, **)
10
+ device = UDPSocket.new.tap do |socket|
11
+ socket.connect(host, port)
12
+ end
13
+
14
+ @logger = Logger.new(device).tap do |logger|
15
+ logger.formatter = Formatter.new(service)
16
+ logger.level = level
17
+ end
18
+ end
19
+
20
+ def log(level, data)
21
+ @logger.public_send level, data
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ class Logasm
2
+ module Adapters
3
+ class StdoutAdapter
4
+ attr_reader :logger
5
+
6
+ def initialize(level, *)
7
+ @logger = Logger.new(STDOUT)
8
+ @logger.level = level
9
+ end
10
+
11
+ def log(level, message: nil, **metadata)
12
+ log_data = [message, metadata.empty? ? nil : metadata.to_json].compact.join(' ')
13
+
14
+ @logger.public_send level, log_data
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ class Logasm
2
+ module Adapters
3
+ LOG_LEVELS = %w(debug info warn error fatal unknown).freeze
4
+
5
+ def self.get(type, service_name, arguments)
6
+ adapter = const_get(Inflecto.camelize(type.to_s) + 'Adapter')
7
+ level = LOG_LEVELS.index(arguments.fetch(:level, 'debug'))
8
+ adapter.new(level, service_name, arguments)
9
+ end
10
+ end
11
+ end
data/lib/logasm.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'inflecto'
2
+ require 'logger'
3
+ require_relative 'logasm/adapters'
4
+ require_relative 'logasm/adapters/stdout_adapter'
5
+ require_relative 'logasm/adapters/logstash_adapter'
6
+ require_relative 'logasm/adapters/logstash_adapter/formatter'
7
+
8
+ class Logasm
9
+ def self.build(service_name, loggers_config)
10
+ loggers_config ||= {stdout: nil}
11
+ adapters = loggers_config.map do |type, arguments|
12
+ Adapters.get(type.to_s, service_name, arguments || {})
13
+ end
14
+ new(adapters)
15
+ end
16
+
17
+ def initialize(adapters)
18
+ @adapters = adapters
19
+ end
20
+
21
+ def debug(*args)
22
+ log :debug, *args
23
+ end
24
+
25
+ def info(*args)
26
+ log :info, *args
27
+ end
28
+
29
+ def warn(*args)
30
+ log :warn, *args
31
+ end
32
+
33
+ def error(*args)
34
+ log :error, *args
35
+ end
36
+
37
+ def fatal(*args)
38
+ log :fatal, *args
39
+ end
40
+
41
+ private
42
+
43
+ def log(level, *args)
44
+ data = parse_log_data(*args)
45
+
46
+ @adapters.each do |adapter|
47
+ adapter.log(level, data)
48
+ end
49
+ end
50
+
51
+ def parse_log_data(message, metadata = {})
52
+ return message if message.is_a?(Hash)
53
+
54
+ (metadata || {}).merge(message: message)
55
+ end
56
+ end
data/logasm.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "logasm"
7
+ gem.version = '0.1.0'
8
+ gem.authors = ["Salemove"]
9
+ gem.email = ["support@salemove.com"]
10
+ gem.description = %q{It's logasmic}
11
+ gem.summary = %q{What description said}
12
+ gem.license = "MIT"
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency 'logstash-event', '~> 1.2'
20
+ gem.add_dependency 'inflecto'
21
+
22
+ gem.add_development_dependency "bundler", "~> 1.3"
23
+ gem.add_development_dependency "rake"
24
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Logasm::Adapters::LogstashAdapter::Formatter do
4
+ subject(:event) { JSON.parse(formatter.call(severity, time, nil, message)) }
5
+
6
+ let(:formatter) { described_class.new(service_name) }
7
+ let(:service_name) { 'test_service' }
8
+ let(:severity) { 'INFO' }
9
+ let(:time) { Time.now }
10
+ let(:message) { {} }
11
+
12
+ context 'when service name is present' do
13
+ it 'includes it in the event as application' do
14
+ expect(event['application']).to eq('test_service')
15
+ end
16
+ end
17
+
18
+ context 'when service name is not present' do
19
+ let(:service_name) { nil }
20
+
21
+ it 'includes does not include the application key' do
22
+ expect(event).to_not have_key('application')
23
+ end
24
+ end
25
+
26
+ it 'includes severity as lowercase level' do
27
+ expect(event['level']).to eq('info')
28
+ end
29
+
30
+ it 'includes timestamp' do
31
+ expect(event['@timestamp']).to match(/\d{4}.*/)
32
+ end
33
+
34
+ it 'includes the host' do
35
+ expect(event['host']).to be_a(String)
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Logasm::Adapters::LogstashAdapter do
4
+ let(:logstash) { described_class.new(0, 'test_service', { host: 'localhost', port: '5228'}) }
5
+ let(:logger) { logstash.logger }
6
+
7
+ it 'delegates to the logger' do
8
+ expect(logger).to receive(:info).with(message: 'test')
9
+
10
+ logstash.log :info, message: 'test'
11
+ end
12
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'logasm'
3
+
4
+ describe Logasm::Adapters::StdoutAdapter do
5
+ it 'creates a stdout logger' do
6
+ io_logger = described_class.new(0)
7
+
8
+ logger = io_logger.instance_variable_get(:@logger)
9
+ expect(logger).to be_a Logger
10
+ end
11
+
12
+ describe '#log' do
13
+ let(:adapter) { described_class.new(0) }
14
+ let(:logger) { adapter.logger }
15
+
16
+ context 'with only a message' do
17
+ it 'stringifies it correctly' do
18
+ expect(logger).to receive(:info).with('test')
19
+
20
+ adapter.log :info, message: 'test'
21
+ end
22
+ end
23
+
24
+ context 'with an empty message' do
25
+ it 'stringifies it correctly' do
26
+ expect(logger).to receive(:info).with(' {"a":"b"}')
27
+
28
+ adapter.log :info, message: '', a: 'b'
29
+ end
30
+ end
31
+
32
+ context 'with no message' do
33
+ it 'stringifies it correctly' do
34
+ expect(logger).to receive(:info).with('{"a":"b"}')
35
+
36
+ adapter.log :info, a: 'b'
37
+ end
38
+ end
39
+
40
+ context 'with a message and metadata' do
41
+ it 'stringifies it correctly' do
42
+ expect(logger).to receive(:info).with('test {"a":"b"}')
43
+
44
+ adapter.log :info, message: 'test', a: 'b'
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Logasm do
4
+ describe '.build' do
5
+ it 'creates file logger' do
6
+ expect(described_class).to receive(:new) do |adapters|
7
+ expect(adapters.count).to be(1)
8
+ expect(adapters.first).to be_a(described_class::Adapters::StdoutAdapter)
9
+ end
10
+
11
+ described_class.build('test_service', stdout: nil)
12
+ end
13
+
14
+ it 'creates logstash logger' do
15
+ expect(described_class).to receive(:new) do |adapters|
16
+ expect(adapters.count).to be(1)
17
+ expect(adapters.first).to be_a(described_class::Adapters::LogstashAdapter)
18
+ end
19
+
20
+ described_class.build('test_service', logstash: {host: 'localhost', port: 5228})
21
+ end
22
+
23
+ it 'creates multiple loggers' do
24
+ expect(described_class).to receive(:new) do |adapters|
25
+ expect(adapters.count).to be(2)
26
+ expect(adapters.first).to be_a(described_class::Adapters::StdoutAdapter)
27
+ expect(adapters.last).to be_a(described_class::Adapters::LogstashAdapter)
28
+ end
29
+
30
+ described_class.build('test_service', stdout: nil, logstash: {host: 'localhost', port: 5228})
31
+ end
32
+
33
+ it 'creates file logger when no loggers are specified' do
34
+ expect(described_class).to receive(:new) do |adapters|
35
+ expect(adapters.count).to be(1)
36
+ expect(adapters.first).to be_a(described_class::Adapters::StdoutAdapter)
37
+ end
38
+
39
+ described_class.build('test_service', nil)
40
+ end
41
+ end
42
+
43
+ context 'when parsing log data' do
44
+ let(:logasm) { described_class.new([adapter]) }
45
+ let(:adapter) { double }
46
+
47
+ it 'parses empty string with nil metadata' do
48
+ expect(adapter).to receive(:log).with(:info, message: '')
49
+
50
+ logasm.info('', nil)
51
+ end
52
+
53
+ it 'parses nil as metadata' do
54
+ expect(adapter).to receive(:log).with(:info, message: nil)
55
+
56
+ logasm.info(nil)
57
+ end
58
+
59
+ it 'parses only message' do
60
+ expect(adapter).to receive(:log).with(:info, message: 'test message')
61
+
62
+ logasm.info 'test message'
63
+ end
64
+
65
+ it 'parses only metadata' do
66
+ expect(adapter).to receive(:log).with(:info, test: 'data')
67
+
68
+ logasm.info test: 'data'
69
+ end
70
+
71
+ it 'parses message and metadata' do
72
+ expect(adapter).to receive(:log).with(:info, message: 'test message', test: 'data')
73
+
74
+ logasm.info 'test message', test: 'data'
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ RSpec.configure do |config|
2
+ config.treat_symbols_as_metadata_keys_with_true_values = true
3
+ config.run_all_when_everything_filtered = true
4
+ config.filter_run :focus
5
+ config.order = 'random'
6
+ end
7
+
8
+ require 'pry'
9
+ require 'securerandom'
10
+
11
+ require 'logasm'
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logasm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Salemove
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash-event
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: inflecto
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: It's logasmic
70
+ email:
71
+ - support@salemove.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".ruby-gemset"
79
+ - ".ruby-version"
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - README.md
83
+ - Rakefile
84
+ - lib/logasm.rb
85
+ - lib/logasm/adapters.rb
86
+ - lib/logasm/adapters/logstash_adapter.rb
87
+ - lib/logasm/adapters/logstash_adapter/formatter.rb
88
+ - lib/logasm/adapters/stdout_adapter.rb
89
+ - logasm.gemspec
90
+ - spec/adapters/logstash_adapter/formatter_spec.rb
91
+ - spec/adapters/logstash_adapter_spec.rb
92
+ - spec/adapters/stdout_adapter_spec.rb
93
+ - spec/logasm_spec.rb
94
+ - spec/spec_helper.rb
95
+ homepage:
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.4.3
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: What description said
119
+ test_files:
120
+ - spec/adapters/logstash_adapter/formatter_spec.rb
121
+ - spec/adapters/logstash_adapter_spec.rb
122
+ - spec/adapters/stdout_adapter_spec.rb
123
+ - spec/logasm_spec.rb
124
+ - spec/spec_helper.rb