cm-cloudwatchlogger 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/LICENSE +21 -0
- data/README.md +91 -0
- data/cloudwatchlogger.gemspec +27 -0
- data/lib/cloudwatchlogger/client/aws_sdk/threaded.rb +118 -0
- data/lib/cloudwatchlogger/client/aws_sdk.rb +26 -0
- data/lib/cloudwatchlogger/client.rb +95 -0
- data/lib/cloudwatchlogger/version.rb +3 -0
- data/lib/cloudwatchlogger.rb +21 -0
- data/lib/cm-cloudwatchlogger.rb +1 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0fcfddd765a3ef7b8613f58504a1849fba5786a572ee3692432bc5985f56e023
|
4
|
+
data.tar.gz: a1197b067bdf6b6e86f62a8a505ca6a5f2beee8aa4e8f4b391ec1180a2014dd8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d3d28307ebf7aa1d3c5b51f5a3950ea11a4b85307289a5dcce229385a14fb527516f3ac288c2e745fddfb674e96defd9ad07aee15f40c9558c6d60787dad415d
|
7
|
+
data.tar.gz: 861e199cd13f9bc4b1fac54ca9f7ee33f1f9e09d3f5065673b5ea753769fe5f540061983ebea824becc5748770d82f2fa05d41266ec932a68ae9f2a1d2bd28e2
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Zane Shannon
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
Overview
|
2
|
+
--------
|
3
|
+
|
4
|
+
Send logged messages to [AWS CloudWatch Logs](http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/WhatIsCloudWatchLogs.html) using the ruby [AWS SDK](http://docs.aws.amazon.com/sdkforruby/api/index.html).
|
5
|
+
|
6
|
+
Can be used in place of Ruby's Logger
|
7
|
+
(<http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/>)
|
8
|
+
|
9
|
+
In fact, it (currently) returns an instance of Logger.
|
10
|
+
|
11
|
+
Forked from (<https://github.com/zshannon/cloudwatchlogger>).
|
12
|
+
|
13
|
+
Usage
|
14
|
+
-----
|
15
|
+
```ruby
|
16
|
+
require 'cloudwatchlogger'
|
17
|
+
|
18
|
+
log = CloudWatchLogger.new({access_key_id: 'YOUR_ACCESS_KEY_ID', secret_access_key: 'YOUR_SECRET_ACCESS_KEY'}, 'YOUR_CLOUDWATCH_LOG_GROUP')
|
19
|
+
|
20
|
+
log.info("Hello World from Ruby")
|
21
|
+
```
|
22
|
+
|
23
|
+
The region will default to the value of the environment variable `AWS_REGION`. In case you need to pass different region or group's different Log Stream name:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
log = CloudWatchLogger.new({
|
27
|
+
access_key_id: 'YOUR_ACCESS_KEY_ID',
|
28
|
+
secret_access_key: 'YOUR_SECRET_ACCESS_KEY'
|
29
|
+
}, 'YOUR_CLOUDWATCH_LOG_GROUP', 'YOUR_CLOUDWATCH_LOG_STREAM', region: 'YOUR_CLOUDWATCH_REGION' )
|
30
|
+
```
|
31
|
+
|
32
|
+
Provding an empty hash instead of credentials will cause the AWS SDK to search the default credential provider chain for credentials, namely:
|
33
|
+
|
34
|
+
1. Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
|
35
|
+
1. Amazon ECS container credentials (task role)
|
36
|
+
1. Instance profile credentials (IAM role)
|
37
|
+
|
38
|
+
### With Rails
|
39
|
+
|
40
|
+
config/environments/production.rb
|
41
|
+
```ruby
|
42
|
+
RailsApplication::Application.configure do
|
43
|
+
config.logger = CloudWatchLogger.new({access_key_id: 'YOUR_ACCESS_KEY_ID', secret_access_key: 'YOUR_SECRET_ACCESS_KEY'}, 'YOUR_CLOUDWATCH_LOG_GROUP', 'YOUR_CLOUDWATCH_LOG_STREAM', 'YOUR_CLOUDWATCH_REGION')
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
|
48
|
+
Logging
|
49
|
+
-------
|
50
|
+
|
51
|
+
CloudWatchLogger.new returns a ruby Logger object, so take a look at:
|
52
|
+
|
53
|
+
http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/
|
54
|
+
|
55
|
+
The Logger's logdev has some special format handling though.
|
56
|
+
|
57
|
+
### Logging a string
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
log.warn "test"
|
61
|
+
```
|
62
|
+
|
63
|
+
Will produce the following log message in CloudWatch Logs:
|
64
|
+
|
65
|
+
```
|
66
|
+
"<Date> severity=WARN, test"
|
67
|
+
```
|
68
|
+
|
69
|
+
### Logging a Hash
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
log.warn :boom => :box, :bar => :soap
|
73
|
+
```
|
74
|
+
|
75
|
+
Will produce the following log message in CloudWatch Logs:
|
76
|
+
|
77
|
+
```
|
78
|
+
"<Date> severity=WARN, boom=box, bar=soap"
|
79
|
+
```
|
80
|
+
|
81
|
+
Releasing
|
82
|
+
-----
|
83
|
+
|
84
|
+
`rake release`
|
85
|
+
|
86
|
+
Bugs
|
87
|
+
-----
|
88
|
+
|
89
|
+
https://github.com/commutatus/cloudwatchlogger/issues
|
90
|
+
|
91
|
+
Pull requests welcome.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require File.expand_path(File.join(dir, 'lib', 'cloudwatchlogger', 'version'))
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'cm-cloudwatchlogger'
|
6
|
+
s.version = CloudWatchLogger::VERSION
|
7
|
+
s.date = Time.now
|
8
|
+
s.summary = 'Amazon CloudWatch Logs compatiable logger for ruby.'
|
9
|
+
s.description = 'Logger => CloudWatchLogs'
|
10
|
+
|
11
|
+
s.license = "MIT"
|
12
|
+
|
13
|
+
s.authors = ["Zane Shannon", "Manikandan"]
|
14
|
+
s.email = ['z@zcs.me', 'manikandan0603@gmail.com']
|
15
|
+
s.homepage = 'http://github.com/commutatus/cloudwatchlogger'
|
16
|
+
|
17
|
+
s.files = %w{ README.md Gemfile LICENSE cloudwatchlogger.gemspec } + Dir["lib/**/*.rb"]
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
s.test_files = Dir["spec/**/*.rb"]
|
20
|
+
|
21
|
+
s.required_ruby_version = '>= 1.8.6'
|
22
|
+
s.required_rubygems_version = '>= 1.3.6'
|
23
|
+
|
24
|
+
s.add_runtime_dependency 'securerandom', '~> 0.1'
|
25
|
+
s.add_runtime_dependency 'multi_json', '~> 1'
|
26
|
+
s.add_runtime_dependency 'aws-sdk-cloudwatchlogs', '~> 1'
|
27
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'aws-sdk-cloudwatchlogs'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module CloudWatchLogger
|
5
|
+
module Client
|
6
|
+
class AWS_SDK
|
7
|
+
# Used by the Threaded client to manage the delivery thread
|
8
|
+
# recreating it if is lost due to a fork.
|
9
|
+
#
|
10
|
+
class DeliveryThreadManager
|
11
|
+
def initialize(credentials, log_group_name, log_stream_name, opts = {})
|
12
|
+
@credentials = credentials
|
13
|
+
@log_group_name = log_group_name
|
14
|
+
@log_stream_name = log_stream_name
|
15
|
+
@opts = opts
|
16
|
+
start_thread
|
17
|
+
end
|
18
|
+
|
19
|
+
# Pushes a message to the delivery thread, starting one if necessary
|
20
|
+
def deliver(message)
|
21
|
+
start_thread unless @thread.alive?
|
22
|
+
@thread.deliver(message)
|
23
|
+
# Race condition? Sometimes we need to rescue this and start a new thread
|
24
|
+
rescue NoMethodError
|
25
|
+
@thread.kill # Try not to leak threads, should already be dead anyway
|
26
|
+
start_thread
|
27
|
+
retry
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def start_thread
|
33
|
+
@thread = DeliveryThread.new(@credentials, @log_group_name, @log_stream_name, @opts)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class DeliveryThread < Thread
|
38
|
+
def initialize(credentials, log_group_name, log_stream_name, opts = {})
|
39
|
+
opts[:open_timeout] = opts[:open_timeout] || 120
|
40
|
+
opts[:read_timeout] = opts[:read_timeout] || 120
|
41
|
+
@credentials = credentials
|
42
|
+
@log_group_name = log_group_name
|
43
|
+
@log_stream_name = log_stream_name
|
44
|
+
@opts = opts
|
45
|
+
|
46
|
+
@queue = Queue.new
|
47
|
+
@exiting = false
|
48
|
+
|
49
|
+
super do
|
50
|
+
loop do
|
51
|
+
connect!(opts) if @client.nil?
|
52
|
+
|
53
|
+
message_object = @queue.pop
|
54
|
+
break if message_object == :__delivery_thread_exit_signal__
|
55
|
+
|
56
|
+
begin
|
57
|
+
event = {
|
58
|
+
log_group_name: @log_group_name,
|
59
|
+
log_stream_name: @log_stream_name,
|
60
|
+
log_events: [{
|
61
|
+
timestamp: message_object[:epoch_time],
|
62
|
+
message: message_object[:message]
|
63
|
+
}]
|
64
|
+
}
|
65
|
+
event[:sequence_token] = @sequence_token if @sequence_token
|
66
|
+
response = @client.put_log_events(event)
|
67
|
+
unless response.rejected_log_events_info.nil?
|
68
|
+
raise CloudWatchLogger::LogEventRejected
|
69
|
+
end
|
70
|
+
@sequence_token = response.next_sequence_token
|
71
|
+
rescue Aws::CloudWatchLogs::Errors::InvalidSequenceTokenException => err
|
72
|
+
@sequence_token = err.message.split(' ').last
|
73
|
+
retry
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
at_exit do
|
79
|
+
exit!
|
80
|
+
join
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Signals the queue that we're exiting
|
85
|
+
def exit!
|
86
|
+
@exiting = true
|
87
|
+
@queue.push :__delivery_thread_exit_signal__
|
88
|
+
end
|
89
|
+
|
90
|
+
# Pushes a message onto the internal queue
|
91
|
+
def deliver(message)
|
92
|
+
@queue.push(message)
|
93
|
+
end
|
94
|
+
|
95
|
+
def connect!(opts = {})
|
96
|
+
args = { http_open_timeout: opts[:open_timeout], http_read_timeout: opts[:read_timeout] }
|
97
|
+
args[:region] = @opts[:region] if @opts[:region]
|
98
|
+
args.merge!( @credentials.key?(:access_key_id) ? { access_key_id: @credentials[:access_key_id], secret_access_key: @credentials[:secret_access_key] } : {} )
|
99
|
+
|
100
|
+
@client = Aws::CloudWatchLogs::Client.new(args)
|
101
|
+
begin
|
102
|
+
@client.create_log_stream(
|
103
|
+
log_group_name: @log_group_name,
|
104
|
+
log_stream_name: @log_stream_name
|
105
|
+
)
|
106
|
+
rescue Aws::CloudWatchLogs::Errors::ResourceNotFoundException
|
107
|
+
@client.create_log_group(
|
108
|
+
log_group_name: @log_group_name
|
109
|
+
)
|
110
|
+
retry
|
111
|
+
rescue Aws::CloudWatchLogs::Errors::ResourceAlreadyExistsException,
|
112
|
+
Aws::CloudWatchLogs::Errors::AccessDeniedException
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'aws_sdk', 'threaded')
|
2
|
+
|
3
|
+
module CloudWatchLogger
|
4
|
+
module Client
|
5
|
+
class AWS_SDK
|
6
|
+
include CloudWatchLogger::Client::InstanceMethods
|
7
|
+
|
8
|
+
attr_reader :input_uri, :deliverer
|
9
|
+
|
10
|
+
def initialize(credentials, log_group_name, log_stream_name, opts = {})
|
11
|
+
setup_credentials(credentials)
|
12
|
+
setup_log_group_name(log_group_name)
|
13
|
+
setup_log_stream_name(log_stream_name)
|
14
|
+
@deliverer = CloudWatchLogger::Client::AWS_SDK::DeliveryThreadManager.new(@credentials, @log_group_name, @log_stream_name, opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(message)
|
18
|
+
@deliverer.deliver(message)
|
19
|
+
end
|
20
|
+
|
21
|
+
def close
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'socket'
|
3
|
+
require 'thread'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module CloudWatchLogger
|
7
|
+
module Client
|
8
|
+
def self.new(credentials, log_group_name, log_stream_name = nil, opts = {})
|
9
|
+
unless log_group_name
|
10
|
+
raise LogGroupNameRequired, 'log_group_name is required'
|
11
|
+
end
|
12
|
+
|
13
|
+
CloudWatchLogger::Client::AWS_SDK.new(credentials, log_group_name, log_stream_name, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
module InstanceMethods
|
17
|
+
def masherize_key(prefix, key)
|
18
|
+
[prefix, key.to_s].compact.join('.')
|
19
|
+
end
|
20
|
+
|
21
|
+
def masher(hash, prefix = nil)
|
22
|
+
hash.map do |v|
|
23
|
+
if v[1].is_a?(Hash)
|
24
|
+
masher(v[1], masherize_key(prefix, v[0]))
|
25
|
+
else
|
26
|
+
"#{masherize_key(prefix, v[0])}=" << case v[1]
|
27
|
+
when Symbol
|
28
|
+
v[1].to_s
|
29
|
+
else
|
30
|
+
v[1].inspect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end.join(', ')
|
34
|
+
end
|
35
|
+
|
36
|
+
def formatter(format=nil)
|
37
|
+
proc do |severity, datetime, progname, msg|
|
38
|
+
processid = Process.pid
|
39
|
+
if format == :json && msg.is_a?(Hash)
|
40
|
+
message = MultiJson.dump(msg.merge(severity: severity,
|
41
|
+
datetime: datetime,
|
42
|
+
progname: progname,
|
43
|
+
pid: processid))
|
44
|
+
else
|
45
|
+
message = "#{datetime} "
|
46
|
+
message << massage_message(msg, severity, processid)
|
47
|
+
end
|
48
|
+
|
49
|
+
{
|
50
|
+
message: message,
|
51
|
+
epoch_time: epoch_from(datetime)
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def massage_message(incoming_message, severity, processid)
|
57
|
+
outgoing_message = ''
|
58
|
+
|
59
|
+
outgoing_message << "pid=#{processid}, thread=#{Thread.current.object_id}, severity=#{severity}, "
|
60
|
+
|
61
|
+
outgoing_message << case incoming_message
|
62
|
+
when Hash
|
63
|
+
masher(incoming_message)
|
64
|
+
when String
|
65
|
+
incoming_message
|
66
|
+
else
|
67
|
+
incoming_message.inspect
|
68
|
+
end
|
69
|
+
outgoing_message
|
70
|
+
end
|
71
|
+
|
72
|
+
def setup_credentials(credentials)
|
73
|
+
@credentials = credentials
|
74
|
+
end
|
75
|
+
|
76
|
+
def setup_log_group_name(name)
|
77
|
+
@log_group_name = name
|
78
|
+
end
|
79
|
+
|
80
|
+
def setup_log_stream_name(name)
|
81
|
+
@log_stream_name = name || default_log_stream_name
|
82
|
+
end
|
83
|
+
|
84
|
+
def default_log_stream_name
|
85
|
+
@log_stream_name ||= "#{Socket.gethostname}-#{SecureRandom.uuid}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def epoch_from(datetime)
|
89
|
+
(datetime.utc.to_f.round(3) * 1000).to_i
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
require File.join(File.dirname(__FILE__), 'client', 'aws_sdk')
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'cloudwatchlogger', 'client')
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module CloudWatchLogger
|
6
|
+
class LogGroupNameRequired < ArgumentError; end
|
7
|
+
class LogEventRejected < ArgumentError; end
|
8
|
+
|
9
|
+
def self.new(credentials, log_group_name, log_stream_name = nil, opts = {})
|
10
|
+
client = CloudWatchLogger::Client.new(credentials, log_group_name, log_stream_name, opts)
|
11
|
+
logger = Logger.new(client)
|
12
|
+
|
13
|
+
if client.respond_to?(:formatter)
|
14
|
+
logger.formatter = client.formatter(opts[:format])
|
15
|
+
elsif client.respond_to?(:datetime_format)
|
16
|
+
logger.datetime_format = client.datetime_format
|
17
|
+
end
|
18
|
+
|
19
|
+
logger
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cloudwatchlogger'
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cm-cloudwatchlogger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zane Shannon
|
8
|
+
- Manikandan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-11-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: securerandom
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.1'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.1'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: multi_json
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: aws-sdk-cloudwatchlogs
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1'
|
56
|
+
description: Logger => CloudWatchLogs
|
57
|
+
email:
|
58
|
+
- z@zcs.me
|
59
|
+
- manikandan0603@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE
|
66
|
+
- README.md
|
67
|
+
- cloudwatchlogger.gemspec
|
68
|
+
- lib/cloudwatchlogger.rb
|
69
|
+
- lib/cloudwatchlogger/client.rb
|
70
|
+
- lib/cloudwatchlogger/client/aws_sdk.rb
|
71
|
+
- lib/cloudwatchlogger/client/aws_sdk/threaded.rb
|
72
|
+
- lib/cloudwatchlogger/version.rb
|
73
|
+
- lib/cm-cloudwatchlogger.rb
|
74
|
+
homepage: http://github.com/commutatus/cloudwatchlogger
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 1.8.6
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 1.3.6
|
92
|
+
requirements: []
|
93
|
+
rubygems_version: 3.3.4
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Amazon CloudWatch Logs compatiable logger for ruby.
|
97
|
+
test_files: []
|