s3_log 0.0.2
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 +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
|