loga 1.4.0 → 2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -9
- data/CHANGELOG.md +50 -0
- data/Guardfile +45 -0
- data/LICENSE.txt +29 -0
- data/README.md +149 -81
- data/circle.yml +5 -5
- data/lib/loga.rb +12 -8
- data/lib/loga/configuration.rb +97 -46
- data/lib/loga/event.rb +11 -0
- data/lib/loga/rack/logger.rb +21 -16
- data/lib/loga/rack/request.rb +18 -6
- data/lib/loga/railtie.rb +74 -33
- data/lib/loga/service_version_strategies.rb +19 -0
- data/lib/loga/version.rb +1 -1
- data/loga.gemspec +5 -1
- data/spec/fixtures/rails32/config/application.rb +6 -6
- data/spec/fixtures/rails40/config/application.rb +6 -6
- data/spec/fixtures/rails50/config/application.rb +6 -6
- data/spec/integration/rails/railtie_spec.rb +69 -61
- data/spec/integration/rails/request_spec.rb +17 -18
- data/spec/integration/sinatra_spec.rb +53 -14
- data/spec/support/request_spec.rb +11 -10
- data/spec/unit/loga/configuration_spec.rb +163 -57
- data/spec/unit/loga/event_spec.rb +31 -1
- data/spec/unit/loga/rack/logger_spec.rb +22 -10
- data/spec/unit/loga/rack/request_spec.rb +19 -26
- data/spec/unit/loga/service_version_strategies_spec.rb +37 -0
- data/spec/unit/loga_spec.rb +52 -15
- metadata +53 -8
- data/.rubocop_todo.yml +0 -33
- data/lib/loga/revision_strategy.rb +0 -32
- data/spec/unit/loga/revision_strategy_spec.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58717f46fed6f5a99834472829baef870624e67d
|
4
|
+
data.tar.gz: efbaf0fcdb8c50a0d5193ecd1be1afcc03d4fa19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62433f9172394016bc78a9b49a6c42f90827e925e1b5b5e9704367782705f821c69ff43afc5feb7a25f1eb87ff4a9e4084ad4d5b1e264d19a0c0a4e3feb1b9d7
|
7
|
+
data.tar.gz: fe2281a9a05f805402aab31da3add62067a718e58c0cc7c28bd6731e587301b7cd9dd5f4d86672303b5e93d332ec9a6acc1e11ff38db7ff288774dfd76b668b4
|
data/.rubocop.yml
CHANGED
@@ -1,17 +1,24 @@
|
|
1
|
-
inherit_from: .rubocop_todo.yml
|
2
|
-
|
3
1
|
AllCops:
|
4
2
|
Exclude:
|
5
3
|
- 'spec/fixtures/**/*'
|
6
4
|
- '*.gemspec'
|
7
5
|
|
8
|
-
|
6
|
+
Documentation:
|
7
|
+
Enabled: false
|
8
|
+
|
9
|
+
Metrics/AbcSize:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Metrics/LineLength:
|
9
13
|
Enabled: true
|
10
|
-
|
14
|
+
Max: 90
|
11
15
|
|
12
|
-
|
16
|
+
Metrics/MethodLength:
|
13
17
|
Enabled: true
|
14
|
-
|
18
|
+
Max: 15
|
19
|
+
|
20
|
+
Style/ExtraSpacing:
|
21
|
+
Enabled: false
|
15
22
|
|
16
23
|
Style/BlockDelimiters:
|
17
24
|
Enabled: false
|
@@ -22,8 +29,13 @@ Style/FormatString:
|
|
22
29
|
Style/PerlBackrefs:
|
23
30
|
Enabled: false
|
24
31
|
|
25
|
-
Style/ExtraSpacing:
|
26
|
-
Enabled: false
|
27
|
-
|
28
32
|
Style/SpaceAroundOperators:
|
29
33
|
Enabled: false
|
34
|
+
|
35
|
+
Style/TrailingCommaInLiteral:
|
36
|
+
Enabled: true
|
37
|
+
EnforcedStyleForMultiline: comma
|
38
|
+
|
39
|
+
Style/TrailingCommaInArguments:
|
40
|
+
Enabled: true
|
41
|
+
EnforcedStyleForMultiline: comma
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
|
+
|
7
|
+
## [2.0.0]
|
8
|
+
## [2.0.0.pre.3]
|
9
|
+
## [2.0.0.pre.2]
|
10
|
+
## [2.0.0.pre1]
|
11
|
+
### Added
|
12
|
+
- Human readable formatter `SimpleFormatter`
|
13
|
+
- `LOGA_FORMAT` environment variable to switch between (gelf|simple) formatters
|
14
|
+
- Added `format` and `filter_exceptions` configuration options
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
#### Configuration interface
|
18
|
+
- Configure via Hash instead of Block
|
19
|
+
- String only `service_version` configuration option
|
20
|
+
|
21
|
+
#### Rails
|
22
|
+
- Use Loga everywhere with environment based configuration
|
23
|
+
- Added `ActiveRecord::RecordNotFound` to default `filter_exceptions`
|
24
|
+
- Removed `enabled` and `silence_rails_rack_logger` configure options
|
25
|
+
- Enforce Rails configuration options over Loga where possible
|
26
|
+
|
27
|
+
#### Sinatra
|
28
|
+
- Removed logger and tags parameters in `Loga::Rack::Logger`
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
- Uninitialized `Loga.logger` in Rails
|
32
|
+
|
33
|
+
## [1.4.0] - 2016-09-13
|
34
|
+
### Added
|
35
|
+
- Rails 5 support
|
36
|
+
- Silence ActionController::LogSubscriber
|
37
|
+
|
38
|
+
### Changed
|
39
|
+
- Update GELF payload to include `_request.controller` when available (Rails Controller/Action)
|
40
|
+
|
41
|
+
## [1.3.0] - 2016-09-07
|
42
|
+
### Changed
|
43
|
+
- Silence ActionDispatch::DebugExceptions' logger
|
44
|
+
|
45
|
+
[2.0.0]: https://github.com/FundingCircle/loga/compare/v2.0.0.pre.3...v2.0.0
|
46
|
+
[2.0.0.pre.3]: https://github.com/FundingCircle/loga/compare/v2.0.0.pre.2...v2.0.0.pre.3
|
47
|
+
[2.0.0.pre.2]: https://github.com/FundingCircle/loga/compare/v2.0.0.pre1...v2.0.0.pre.2
|
48
|
+
[2.0.0.pre1]: https://github.com/FundingCircle/loga/compare/v1.4.0...v2.0.0.pre1
|
49
|
+
[1.4.0]: https://github.com/FundingCircle/loga/compare/v1.3.0...v1.4.0
|
50
|
+
[1.3.0]: https://github.com/FundingCircle/loga/compare/v1.2.1...v1.3.0
|
data/Guardfile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
guard :rubocop do
|
2
|
+
watch(%r{^lib/.+\.rb$})
|
3
|
+
watch(%r{^spec/.+\.rb$})
|
4
|
+
end
|
5
|
+
|
6
|
+
group :sinatra do
|
7
|
+
%w(production development).each do |env|
|
8
|
+
guard :rspec,
|
9
|
+
all_on_start: true,
|
10
|
+
cmd: "RACK_ENV=#{env} bundle exec appraisal sinatra14 rspec" do
|
11
|
+
watch(%r{^spec/integration/sinatra_spec.rb$})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
group :rails do
|
17
|
+
%w(production development).each do |env|
|
18
|
+
%w(rails32 rails40 rails50).each do |appraisal|
|
19
|
+
guard :rspec,
|
20
|
+
all_on_start: true,
|
21
|
+
cmd: "RACK_ENV=#{env} bundle exec appraisal #{appraisal} rspec" do
|
22
|
+
watch('lib/loga/railtie.rb') do
|
23
|
+
[
|
24
|
+
'spec/integration/rails/request_spec.rb',
|
25
|
+
'spec/integration/rails/railtie_spec.rb',
|
26
|
+
]
|
27
|
+
end
|
28
|
+
watch(%r{^spec/fixtures/rails\d{2}/.+\.rb$}) do
|
29
|
+
[
|
30
|
+
'spec/integration/rails/request_spec.rb',
|
31
|
+
'spec/integration/rails/railtie_spec.rb',
|
32
|
+
]
|
33
|
+
end
|
34
|
+
watch(%r{^spec/integration/rails/.+_spec\.rb$})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
group :unit do
|
41
|
+
guard :rspec, cmd: 'bundle exec appraisal unit rspec' do
|
42
|
+
watch(%r{^spec/unit/.+_spec\.rb$})
|
43
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
44
|
+
end
|
45
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Copyright (c) 2015, Funding Circle Ltd.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
3. Neither the name of the copyright holder nor the names of its
|
15
|
+
contributors may be used to endorse or promote products derived from
|
16
|
+
this software without specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
19
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
20
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
21
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22
|
+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
24
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
25
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
27
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
28
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
|
data/README.md
CHANGED
@@ -2,146 +2,214 @@
|
|
2
2
|
|
3
3
|
## Description
|
4
4
|
|
5
|
-
Loga
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
-
|
10
|
-
-
|
5
|
+
Loga provides consistent logging across frameworks and environments.
|
6
|
+
|
7
|
+
Includes:
|
8
|
+
- One logger for all environments
|
9
|
+
- Human readable logs for development
|
10
|
+
- Structured logs for production ([GELF](http://docs.graylog.org/en/2.1/pages/gelf.html))
|
11
|
+
- One Rack logger for all Rack based applications
|
12
|
+
|
13
|
+
## TOC
|
14
|
+
|
15
|
+
- [Installation](#installation)
|
16
|
+
- [Rails](#rails)
|
17
|
+
- [Reduced logs](#reduced-logs)
|
18
|
+
- [Request log tags](#request-log-tags)
|
19
|
+
- [Sinatra](#sinatra)
|
20
|
+
- [GELF Output example](#gelf-output-example)
|
21
|
+
- [Road map](#road-map)
|
22
|
+
- [Contributing](#contributing)
|
23
|
+
- [Running tests](#running-tests)
|
24
|
+
- [Credits](#credits)
|
25
|
+
- [License](#license)
|
11
26
|
|
12
27
|
## Installation
|
13
28
|
|
14
29
|
Add this line to your application's Gemfile:
|
15
30
|
|
16
|
-
|
31
|
+
```
|
32
|
+
gem 'loga', git: 'git@github.com:FundingCircle/loga.git'
|
33
|
+
```
|
34
|
+
|
35
|
+
### Rails
|
17
36
|
|
18
|
-
|
37
|
+
Let Loga know what your application name is and Loga will do the rest.
|
19
38
|
|
20
|
-
|
39
|
+
```ruby
|
40
|
+
# config/application.rb
|
41
|
+
class MyApp::Application < Rails::Application
|
42
|
+
config.loga = { service_name: 'MyApp' }
|
43
|
+
end
|
44
|
+
```
|
21
45
|
|
22
|
-
|
46
|
+
Loga hooks into the Rails logger initialization process and defines its own logger for all environments.
|
23
47
|
|
24
|
-
|
25
|
-
using plain Ruby.
|
48
|
+
The logger configuration adjusts based on the environment:
|
26
49
|
|
27
|
-
|
50
|
+
| | Production | Test | Development | Others |
|
51
|
+
|--------|------------|--------------|-------------|--------|
|
52
|
+
| Output | STDOUT | log/test.log | STDOUT | STDOUT |
|
53
|
+
| Format | gelf | simple | simple | simple |
|
28
54
|
|
29
|
-
|
30
|
-
the Railtie.
|
55
|
+
You can customize the configuration to your liking:
|
31
56
|
|
32
57
|
```ruby
|
33
|
-
# config/
|
34
|
-
|
35
|
-
config.loga
|
36
|
-
|
58
|
+
# config/application.rb
|
59
|
+
class MyApp::Application < Rails::Application
|
60
|
+
config.loga = {
|
61
|
+
device: File.open("log/application.log", 'a'),
|
62
|
+
format: :gelf,
|
63
|
+
service_name: 'MyApp',
|
64
|
+
}
|
37
65
|
end
|
38
|
-
...
|
39
66
|
```
|
40
67
|
|
41
|
-
|
68
|
+
Loga leverages existing Rails configuration options:
|
42
69
|
|
43
|
-
|
70
|
+
- `config.filter_parameters`
|
71
|
+
- `config.log_level`
|
72
|
+
- `config.log_tags`
|
44
73
|
|
45
|
-
|
46
|
-
# .../initializers/loga.rb
|
47
|
-
require 'loga'
|
74
|
+
Use these options to customize Loga instead of the Loga options hash.
|
48
75
|
|
49
|
-
Loga.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
```
|
54
|
-
Log requests in Rack applications with Loga middleware.
|
76
|
+
Inside your application use `Rails.logger` instead of `Loga.logger`, even though
|
77
|
+
they are equivalent, to prevent lock-in.
|
78
|
+
|
79
|
+
#### Reduced logs
|
55
80
|
|
56
|
-
|
81
|
+
When the format set to `gelf` requests logs are reduced to a single log entry, which
|
82
|
+
could include an exception.
|
83
|
+
|
84
|
+
This is made possible by silencing these loggers:
|
85
|
+
|
86
|
+
- `Rack::Request::Logger`
|
87
|
+
- `ActionDispatch::DebugExceptions`
|
88
|
+
- `ActionController::LogSubscriber`
|
89
|
+
- `ActionView::LogSubscriber`
|
90
|
+
|
91
|
+
#### Request log tags
|
92
|
+
|
93
|
+
To provide consistency between Rails and other Rack frameworks, tags (e.i `config.log_tags`)
|
94
|
+
are computed with a [Loga::Rack::Request](lib/loga/rack/request.rb) as
|
95
|
+
opposed to a `ActionDispatch::Request`.
|
96
|
+
|
97
|
+
### Sinatra
|
98
|
+
|
99
|
+
With Sinatra Loga needs to be configured manually:
|
57
100
|
|
58
101
|
```ruby
|
59
|
-
|
102
|
+
require 'loga'
|
103
|
+
|
104
|
+
Loga.configure(
|
105
|
+
filter_parameters: [:password],
|
106
|
+
format: :gelf,
|
107
|
+
service_name: 'my_app',
|
108
|
+
tags: [:uuid],
|
109
|
+
)
|
110
|
+
|
60
111
|
use Loga::Rack::RequestId
|
61
|
-
use Loga::Rack::Logger
|
112
|
+
use Loga::Rack::Logger
|
62
113
|
|
63
|
-
|
114
|
+
use MyApp
|
64
115
|
run Sinatra::Application
|
65
116
|
```
|
66
117
|
|
67
|
-
|
118
|
+
You can now use `Loga.logger` or assign it to your existing logger.
|
119
|
+
The above configuration also inserts two middleware:
|
68
120
|
|
69
|
-
|
70
|
-
|
71
|
-
| host | String | nil | Service hostname. When nil the hostname is computed with `Socket.gethostname` |
|
72
|
-
| service_version | String/Symbol | :git | Service version is embedded in every message. When Symbol the version is computed with a strategy. |
|
73
|
-
| service_name | String | nil | Service name is embedded in every message |
|
74
|
-
| device | IO | nil | The device the logger writes to |
|
75
|
-
| sync | Boolean | true | Sync IO |
|
76
|
-
| level | Symbol | :info | The level to logger logs at |
|
77
|
-
| enabled | Boolean | true | Enable/Disable Loga in Rails |
|
121
|
+
- `Loga::Rack::RequestId` makes the request id available to the request logger
|
122
|
+
- `Loga::Rack::Logger` logs requests
|
78
123
|
|
79
|
-
##
|
124
|
+
## GELF Output Example
|
125
|
+
|
126
|
+
Rails request logger: (includes controller/action name):
|
127
|
+
|
128
|
+
`GET /ok`
|
80
129
|
|
81
|
-
```ruby
|
82
|
-
# Anywhere in your application
|
83
|
-
Loga.logger.info('Hello World')
|
84
|
-
```
|
85
130
|
```json
|
86
|
-
//GELF Output
|
87
131
|
{
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
132
|
+
"_request.status": 200,
|
133
|
+
"_request.method": "GET",
|
134
|
+
"_request.path": "/ok",
|
135
|
+
"_request.params": {},
|
136
|
+
"_request.request_id": "2b99e3d3-3ee2-4781-972b-782682f57648",
|
137
|
+
"_request.request_ip": "127.0.0.1",
|
138
|
+
"_request.user_agent": null,
|
139
|
+
"_request.controller": "ApplicationController#ok",
|
140
|
+
"_request.duration": 0,
|
141
|
+
"_type": "request",
|
142
|
+
"_service.name": "my_app",
|
143
|
+
"_service.version": "1.0",
|
144
|
+
"_tags": "2b99e3d3-3ee2-4781-972b-782682f57648",
|
145
|
+
"short_message": "GET /ok 200 in 0ms",
|
146
|
+
"timestamp": 1450150205.123,
|
147
|
+
"host": "example.com",
|
148
|
+
"level": 6,
|
149
|
+
"version": "1.1"
|
96
150
|
}
|
97
151
|
```
|
98
152
|
|
99
|
-
|
153
|
+
Sinatra request output is identical to Rails but without the `_request.controller` key.
|
100
154
|
|
101
|
-
|
155
|
+
Logger output:
|
102
156
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
- Loga formats timestamps in seconds since UNIX epoch with 3 decimal places
|
110
|
-
for milliseconds. Which is in accordance with GELF 1.1 specification.
|
157
|
+
```ruby
|
158
|
+
Rails.logger.info('I love Loga')
|
159
|
+
# or
|
160
|
+
Loga.logger.info('I love Loga')
|
161
|
+
```
|
111
162
|
|
163
|
+
```json
|
164
|
+
{
|
165
|
+
"_service.name": "my_app",
|
166
|
+
"_service.version": "v1.0.0",
|
167
|
+
"_tags": "",
|
168
|
+
"host": "example.com",
|
169
|
+
"level": 6,
|
170
|
+
"short_message": "I love Loga",
|
171
|
+
"timestamp": 1450150205.123,
|
172
|
+
"version": "1.1"
|
173
|
+
}
|
174
|
+
```
|
112
175
|
|
113
|
-
## Road
|
176
|
+
## Road map
|
114
177
|
|
115
178
|
Consult the [milestones](https://github.com/FundingCircle/loga/milestones).
|
116
179
|
|
117
180
|
## Contributing
|
118
181
|
|
119
|
-
|
120
|
-
|
121
|
-
1. Fork it ( https://github.com/FundingCircle/loga/fork )
|
122
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
123
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
124
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
125
|
-
5. Create a new Pull Request
|
182
|
+
Loga is in active development, feedback and contributions are welcomed.
|
126
183
|
|
127
184
|
### Running tests
|
128
185
|
|
129
|
-
This project uses [`appraisal`](https://github.com/thoughtbot/appraisal/tree/v2.0.2)
|
186
|
+
This project uses [`appraisal`](https://github.com/thoughtbot/appraisal/tree/v2.0.2)
|
187
|
+
to run tests against different versions of dependencies (e.g. Rails, Sinatra).
|
130
188
|
|
131
|
-
|
189
|
+
Install Loga dependencies with `bundle install` and then appraisals
|
190
|
+
with `bundle exec appraisal install`.
|
132
191
|
|
133
192
|
Run all tests with `bundle exec appraisal rspec`.
|
134
193
|
|
135
194
|
You can run tests for one appraisal with `bundle exec appraisal appraisal-name rspec`.
|
195
|
+
Refer to the [Appraisals](Appraisals) file for a complete lists of appraisals.
|
196
|
+
|
197
|
+
Prefix test command with RACK\_ENV to switch between environments for Rack based tests
|
198
|
+
`RACK_ENV=production bundle exec appraisal rspec`.
|
136
199
|
|
137
|
-
|
200
|
+
Experiment Guard support introduced to ease running tests locally `bundle exec guard`.
|
138
201
|
|
139
|
-
|
202
|
+
[CI](https://circleci.com/gh/FundingCircle/loga) results are the source of truth.
|
140
203
|
|
141
204
|
## Credits
|
142
205
|
|
206
|
+
- [Lograge](https://github.com/roidrage/lograge)
|
143
207
|
- [LogStashLogger](https://github.com/dwbutler/logstash-logger)
|
144
208
|
- [Rails](https://github.com/rails/rails)
|
145
209
|
- [RackLogstasher](https://github.com/alphagov/rack-logstasher)
|
146
210
|
|
211
|
+
## License
|
212
|
+
|
147
213
|
Copyright (c) 2015 Funding Circle. All rights reserved.
|
214
|
+
|
215
|
+
Distributed under the BSD 3-Clause License.
|