s3_log 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +8 -0
- data/Gemfile +3 -0
- data/HISTORY.md +4 -0
- data/LICENSE +20 -0
- data/README.md +57 -0
- data/Rakefile +4 -0
- data/lib/s3_log/exceptions.rb +15 -0
- data/lib/s3_log/version.rb +3 -0
- data/lib/s3_log.rb +63 -0
- data/s3_log.gemspec +23 -0
- data/spec/s3_log_spec.rb +131 -0
- data/spec/spec_helper.rb +9 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MDMwNzBmNzcyYWQ1MDAyZDRkNGMzMmMxYjQ3YzczZDI3NDQ1MjdiNQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZjEyZGI2Y2NhMzNjYTJlODUyYjZmZGI3NTBlYTM2MjM1NDhhMzI3NQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OTFlNDY4ZmE2Y2M0MTY0ZDhkNjljNDY3Mzk0NmUxNWIzMTQ3ZWM1ZTY5ZTU3
|
10
|
+
M2IxMDEwZWRmZTk2YmMzNTdlMDcyYTZlZmVjMDI1ZWUxMTZmODQ2YzZlNzRj
|
11
|
+
OWQzYjA2NzI3MzlkOTAyYjc0MjI1NDRkODY1ZGVjZjU5NGJlYjY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MWZkNjY1Mjg0NDRiYzVhYzZhMjhjNDdhMGVmYjU4NWM3MDJmNzE5ZmVkMWY2
|
14
|
+
OTBkODJiOTVjZTNjM2M4ODFiNTE1MTU4ZGUyMWM0YTU3YjYyMmJiNWI1MDRl
|
15
|
+
NjI4MDM0ZWQ4MTVlN2JhNzQ1ZDQwOTkyZTlkN2E5ZWQyZTcxOWE=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/HISTORY.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Dennis Walters
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
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, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
## S3Logger ##
|
2
|
+
|
3
|
+
Naively log events to a file on S3
|
4
|
+
|
5
|
+
## Gem Setup ##
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem install s3_logger
|
9
|
+
|
10
|
+
# Gemfile
|
11
|
+
gem 's3_logger'
|
12
|
+
```
|
13
|
+
|
14
|
+
## Configuration ##
|
15
|
+
|
16
|
+
S3Logger requires an AWS access key id, AWS secret access key, and a S3 bucket (preferably created in advance) name to function. It can be configured (in a Rails initializer or what have you) like so:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
S3Logger.configure(
|
20
|
+
access_key_id: 'YOUR AWS ACCESS KEY ID',
|
21
|
+
secret_access_key: 'YOUR AWS SECRET ACCESS KEY',
|
22
|
+
bucket: 'YOUR S3 BUCKET'
|
23
|
+
)
|
24
|
+
```
|
25
|
+
|
26
|
+
## Usage ##
|
27
|
+
|
28
|
+
Basically, logging an event is a matter of using S3Logger.write to write content to a given file location on S3. The file does not have to exist prior to writing, and a write always appends to an existing file.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
S3Logger.write('path/to/file', 'Some content')
|
32
|
+
```
|
33
|
+
|
34
|
+
## Caveats ##
|
35
|
+
|
36
|
+
There is no locking in this process, and an existing file will always be read and appended rather than blindly replaced. That being the case, near-simultaneous writes are won by the most recent write, and you would do well to do one of the following to avoid data loss:
|
37
|
+
|
38
|
+
* Ensure that only one process writes to a given file at a time
|
39
|
+
* Use a new file path for each write (ie models/user/1/TIMESTAMP.log rather than models/user/1.log)
|
40
|
+
|
41
|
+
## Formal Documentation ##
|
42
|
+
|
43
|
+
The actual library docs can be read
|
44
|
+
[over on rubydoc](http://rubydoc.info/gems/s3_logger/frames).
|
45
|
+
|
46
|
+
## Contributing ##
|
47
|
+
|
48
|
+
Do you use git-flow? I sure do. Please base anything you do off of
|
49
|
+
[the develop branch](https://github.com/ess/s3_logger/tree/develop).
|
50
|
+
|
51
|
+
1. Fork it.
|
52
|
+
2. Perform some BDD magic. Seriously. Be testing.
|
53
|
+
3. Submit a pull request.
|
54
|
+
|
55
|
+
## License ##
|
56
|
+
|
57
|
+
MIT License. Copyright 2015 Dennis Walters
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module S3Log
|
2
|
+
class Error < StandardError ; end
|
3
|
+
|
4
|
+
class InvalidConfigError < Error
|
5
|
+
def initialize(missing)
|
6
|
+
super("Missing configuration keys (#{missing.join(', ')})")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Unconfigured < Error
|
11
|
+
def initialize(garbage = nil)
|
12
|
+
super("You must first run S3Logger.configure")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/s3_log.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'fog/aws/storage'
|
2
|
+
require 's3_log/exceptions'
|
3
|
+
|
4
|
+
module S3Log
|
5
|
+
RequiredOptions = [:access_key_id, :secret_access_key, :bucket]
|
6
|
+
|
7
|
+
def self.storage
|
8
|
+
@storage
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.bucket
|
12
|
+
@bucket
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configured?
|
16
|
+
storage && bucket
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure(options = {})
|
20
|
+
missing = RequiredOptions - options.keys
|
21
|
+
raise InvalidConfigError.new(missing) unless missing.empty?
|
22
|
+
|
23
|
+
clear_configuration
|
24
|
+
|
25
|
+
@storage = Fog::Storage::AWS.new(
|
26
|
+
aws_access_key_id: options[:access_key_id],
|
27
|
+
aws_secret_access_key: options[:secret_access_key]
|
28
|
+
)
|
29
|
+
|
30
|
+
@bucket = @storage.directories.create(
|
31
|
+
key: options[:bucket],
|
32
|
+
public: false
|
33
|
+
)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.write(path, content)
|
38
|
+
unless storage && bucket
|
39
|
+
raise Unconfigured
|
40
|
+
end
|
41
|
+
|
42
|
+
bucket.files.create(
|
43
|
+
key: path,
|
44
|
+
body: read(path).split("\n").push(content).join("\n"),
|
45
|
+
public: false
|
46
|
+
)
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.read(path)
|
52
|
+
unless storage && bucket
|
53
|
+
raise Unconfigured
|
54
|
+
end
|
55
|
+
|
56
|
+
file = bucket.files.get(path)
|
57
|
+
file.nil? ? '' : file.body.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.clear_configuration
|
61
|
+
@bucket = @storage = nil
|
62
|
+
end
|
63
|
+
end
|
data/s3_log.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/s3_log/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Dennis Walters"]
|
6
|
+
gem.email = ["dennis@elevatorup.com"]
|
7
|
+
gem.summary = %q{Log misc events to Amazon S3}
|
8
|
+
gem.description = <<-EOD
|
9
|
+
Log misc events to Amazon S3
|
10
|
+
EOD
|
11
|
+
gem.homepage = "http://github.com/ess/s3_log"
|
12
|
+
gem.license = 'MIT'
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($\)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.name = "s3_log"
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.version = S3Log::VERSION
|
20
|
+
|
21
|
+
gem.add_dependency 'fog-aws', '~> 0.1.1'
|
22
|
+
gem.add_development_dependency 'rspec', '~> 3.2.0'
|
23
|
+
end
|
data/spec/s3_log_spec.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 's3_log'
|
3
|
+
|
4
|
+
describe S3Log do
|
5
|
+
let(:access_key_id) {'ACCESS_KEY_ID'}
|
6
|
+
let(:secret_access_key) {'SECRET_ACCESS_KEY'}
|
7
|
+
let(:bucket) {'bucket'}
|
8
|
+
let(:path) {'path/to/a/file'}
|
9
|
+
let(:content) {'line 1'}
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
Fog::Mock.reset
|
13
|
+
Fog.mock!
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.configure' do
|
17
|
+
let(:good_options) {{
|
18
|
+
access_key_id: access_key_id,
|
19
|
+
secret_access_key: secret_access_key,
|
20
|
+
bucket: bucket
|
21
|
+
}}
|
22
|
+
|
23
|
+
it 'requires an aws access key id' do
|
24
|
+
expect{described_class.configure(good_options)}.
|
25
|
+
not_to raise_error
|
26
|
+
|
27
|
+
good_options.delete(:access_key_id)
|
28
|
+
|
29
|
+
expect{described_class.configure(good_options)}.
|
30
|
+
to raise_error(S3Log::InvalidConfigError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'requires an aws secret access key' do
|
34
|
+
expect{described_class.configure(good_options)}.
|
35
|
+
not_to raise_error
|
36
|
+
|
37
|
+
good_options.delete(:secret_access_key)
|
38
|
+
|
39
|
+
expect{described_class.configure(good_options)}.
|
40
|
+
to raise_error(S3Log::InvalidConfigError)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'requires a bucket name' do
|
45
|
+
expect{described_class.configure(good_options)}.
|
46
|
+
not_to raise_error
|
47
|
+
|
48
|
+
good_options.delete(:bucket)
|
49
|
+
|
50
|
+
expect{described_class.configure(good_options)}.
|
51
|
+
to raise_error(S3Log::InvalidConfigError)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.read' do
|
56
|
+
before(:each) do
|
57
|
+
described_class.configure(
|
58
|
+
access_key_id: 'ACCESS_KEY_ID',
|
59
|
+
secret_access_key: 'SECRET_ACCESS_KEY',
|
60
|
+
bucket: 'bucket'
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'requires that the module be configured' do
|
65
|
+
described_class.clear_configuration
|
66
|
+
expect {described_class.read(path)}.
|
67
|
+
to raise_error(described_class::Unconfigured)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'is a string' do
|
71
|
+
expect(described_class.read(path)).to be_a(String)
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'for a non-existent path' do
|
75
|
+
it 'is an empty string' do
|
76
|
+
expect(described_class.read(path)).to eql('')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'for an existing path' do
|
81
|
+
it 'is the content of the file' do
|
82
|
+
described_class.write(path, content)
|
83
|
+
expect(described_class.read(path)).to eql(content)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '.write' do
|
89
|
+
before(:each) do
|
90
|
+
described_class.configure(
|
91
|
+
access_key_id: 'ACCESS_KEY_ID',
|
92
|
+
secret_access_key: 'SECRET_ACCESS_KEY',
|
93
|
+
bucket: 'bucket'
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'requires that the module be configured' do
|
98
|
+
described_class.clear_configuration
|
99
|
+
expect {described_class.write(path, content)}.
|
100
|
+
to raise_error(described_class::Unconfigured)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'reads the file' do
|
104
|
+
expect(described_class).
|
105
|
+
to receive(:read).with(path).and_call_original
|
106
|
+
|
107
|
+
described_class.write(path, content)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'creates the file on s3' do
|
111
|
+
expect(described_class.read(path)).to eql('')
|
112
|
+
|
113
|
+
described_class.write(path, content)
|
114
|
+
|
115
|
+
expect(described_class.read(path)).to eql(content)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'appends to an exsiting s3 file' do
|
119
|
+
more_content = 'more content'
|
120
|
+
described_class.write(path, content)
|
121
|
+
expect(described_class.read(path)).to eql(content)
|
122
|
+
|
123
|
+
described_class.write(path, "more content")
|
124
|
+
expect(described_class.read(path)).to eql("#{content}\n#{more_content}")
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'returns the logger itself' do
|
128
|
+
expect(described_class.write(path, content)).to eql(described_class)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: s3_log
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dennis Walters
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fog-aws
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.2.0
|
41
|
+
description: ! ' Log misc events to Amazon S3
|
42
|
+
|
43
|
+
'
|
44
|
+
email:
|
45
|
+
- dennis@elevatorup.com
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- .gitignore
|
51
|
+
- Gemfile
|
52
|
+
- HISTORY.md
|
53
|
+
- LICENSE
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- lib/s3_log.rb
|
57
|
+
- lib/s3_log/exceptions.rb
|
58
|
+
- lib/s3_log/version.rb
|
59
|
+
- s3_log.gemspec
|
60
|
+
- spec/s3_log_spec.rb
|
61
|
+
- spec/spec_helper.rb
|
62
|
+
homepage: http://github.com/ess/s3_log
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.4.5
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: Log misc events to Amazon S3
|
86
|
+
test_files:
|
87
|
+
- spec/s3_log_spec.rb
|
88
|
+
- spec/spec_helper.rb
|