macmillan-utils 1.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.hound.yml +36 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +36 -0
  6. data/.travis.yml +15 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.rdoc +113 -0
  10. data/Rakefile +12 -0
  11. data/lib/macmillan/utils.rb +16 -0
  12. data/lib/macmillan/utils/bundler/gem_helper.rb +9 -0
  13. data/lib/macmillan/utils/cucumber/cucumber_defaults.rb +12 -0
  14. data/lib/macmillan/utils/cucumber/webmock_helper.rb +9 -0
  15. data/lib/macmillan/utils/logger.rb +11 -0
  16. data/lib/macmillan/utils/logger/factory.rb +77 -0
  17. data/lib/macmillan/utils/logger/formatter.rb +48 -0
  18. data/lib/macmillan/utils/middleware.rb +7 -0
  19. data/lib/macmillan/utils/middleware/weak_etags.rb +33 -0
  20. data/lib/macmillan/utils/rails/statsd_instrumentation.rb +64 -0
  21. data/lib/macmillan/utils/rspec/rack_test_helper.rb +12 -0
  22. data/lib/macmillan/utils/rspec/rspec_defaults.rb +44 -0
  23. data/lib/macmillan/utils/rspec/webmock_helper.rb +13 -0
  24. data/lib/macmillan/utils/settings.rb +33 -0
  25. data/lib/macmillan/utils/settings/app_yaml_backend.rb +44 -0
  26. data/lib/macmillan/utils/settings/env_vars_backend.rb +13 -0
  27. data/lib/macmillan/utils/settings/key_not_found.rb +13 -0
  28. data/lib/macmillan/utils/settings/lookup.rb +29 -0
  29. data/lib/macmillan/utils/settings/value.rb +16 -0
  30. data/lib/macmillan/utils/statsd_controller_helper.rb +81 -0
  31. data/lib/macmillan/utils/statsd_decorator.rb +98 -0
  32. data/lib/macmillan/utils/statsd_middleware.rb +87 -0
  33. data/lib/macmillan/utils/statsd_stub.rb +43 -0
  34. data/lib/macmillan/utils/test_helpers/codeclimate_helper.rb +4 -0
  35. data/lib/macmillan/utils/test_helpers/fixture_loading_helper.rb +24 -0
  36. data/lib/macmillan/utils/test_helpers/simplecov_helper.rb +27 -0
  37. data/macmillan-utils.gemspec +33 -0
  38. data/spec/fixtures/config/application.yml +1 -0
  39. data/spec/lib/macmillan/utils/logger/factory_spec.rb +53 -0
  40. data/spec/lib/macmillan/utils/logger/formatter_spec.rb +57 -0
  41. data/spec/lib/macmillan/utils/middleware/weak_etags_spec.rb +30 -0
  42. data/spec/lib/macmillan/utils/settings_spec.rb +44 -0
  43. data/spec/lib/macmillan/utils/statsd_controller_helper_spec.rb +43 -0
  44. data/spec/lib/macmillan/utils/statsd_decorator_spec.rb +93 -0
  45. data/spec/lib/macmillan/utils/statsd_middleware_spec.rb +51 -0
  46. data/spec/spec_helper.rb +13 -0
  47. metadata +296 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 618626d3f23f078df01d4ff82448a7fbb61510c2
4
+ data.tar.gz: 6849bec7f310b4e0b94882f5ce30385bd7ce0dcb
5
+ SHA512:
6
+ metadata.gz: bbc3d8a092c4eec621516f0280646d185451a2ce3caec1a1ba5833d51e9309ce66767c71001d7f0e4d4a25260d62ed36c557136164572ed6b1c910ab8456a6ac
7
+ data.tar.gz: e294f634ff213e82c1c400176d02255ac8b08a541a709b375293aeb61f8ef202d8f8fa0c2c108413cd7a2c68c6b5d01c1928fe007c8ef5fa224424d490f94410
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ *.bundle
18
+ *.so
19
+ *.o
20
+ *.a
21
+ mkmf.log
22
+ RBENV_VERSION*
23
+ Gemfile.lock
data/.hound.yml ADDED
@@ -0,0 +1,36 @@
1
+ Metrics/LineLength:
2
+ Description: 'Limit lines to 120 characters.'
3
+ Max: 120
4
+
5
+ Style/Documentation:
6
+ Enabled: false
7
+
8
+ Style/SingleSpaceBeforeFirstArg:
9
+ Enabled: false
10
+
11
+ Style/BracesAroundHashParameters:
12
+ Enabled: false
13
+
14
+ Style/IndentHash:
15
+ EnforcedStyle: consistent
16
+
17
+ Style/AlignHash:
18
+ EnforcedHashRocketStyle: table
19
+ EnforcedColonStyle: table
20
+
21
+ Style/AlignParameters:
22
+ EnforcedStyle: with_fixed_indentation
23
+
24
+ Style/StringLiterals:
25
+ EnforcedStyle: single_quotes
26
+
27
+ Style/CollectionMethods:
28
+ PreferredMethods:
29
+ collect: 'map'
30
+ collect!: 'map!'
31
+ inject: 'reduce'
32
+ detect: 'find'
33
+ find_all: 'select'
34
+
35
+ Style/DotPosition:
36
+ EnforcedStyle: leading
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --profile
3
+ --warnings
data/.rubocop.yml ADDED
@@ -0,0 +1,36 @@
1
+ Metrics/LineLength:
2
+ Description: 'Limit lines to 120 characters.'
3
+ Max: 120
4
+
5
+ Style/Documentation:
6
+ Enabled: false
7
+
8
+ Style/SingleSpaceBeforeFirstArg:
9
+ Enabled: false
10
+
11
+ Style/BracesAroundHashParameters:
12
+ Enabled: false
13
+
14
+ Style/IndentHash:
15
+ EnforcedStyle: consistent
16
+
17
+ Style/AlignHash:
18
+ EnforcedHashRocketStyle: table
19
+ EnforcedColonStyle: table
20
+
21
+ Style/AlignParameters:
22
+ EnforcedStyle: with_fixed_indentation
23
+
24
+ Style/StringLiterals:
25
+ EnforcedStyle: single_quotes
26
+
27
+ Style/CollectionMethods:
28
+ PreferredMethods:
29
+ collect: 'map'
30
+ collect!: 'map!'
31
+ inject: 'reduce'
32
+ detect: 'find'
33
+ find_all: 'select'
34
+
35
+ Style/DotPosition:
36
+ EnforcedStyle: leading
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+ - 2.1.1
8
+ - 2.1.2
9
+ - 2.1.3
10
+ - 2.1.4
11
+ - 2.1.5
12
+ - 2.2.0
13
+ - jruby-19mode
14
+ env:
15
+ - USE_SIMPLECOV=true CODECLIMATE_REPO_TOKEN=2175628fb41494d45b50b6938600a53c130e1f7ac3b81b072bb71e91073a5e4a
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in macmillan-utils.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Macmillan Science and Education
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,113 @@
1
+ = Macmillan::Utils
2
+
3
+ A collection of useful patterns we use in our Ruby applications.
4
+
5
+ {<img src="https://travis-ci.org/nature/macmillan-utils.svg?branch=log-formatter" alt="Build Status" />}[https://travis-ci.org/nature/macmillan-utils]
6
+ {<img src="https://codeclimate.com/github/nature/macmillan-utils.png" alt="CodeClimate Rating" />}[https://codeclimate.com/github/nature/macmillan-utils]
7
+ {<img src="https://codeclimate.com/github/nature/macmillan-utils/coverage.png" alt="Test Coverage" />}[https://codeclimate.com/github/nature/macmillan-utils]
8
+
9
+ == Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'macmillan-utils', require: false
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself with:
20
+
21
+ $ gem install macmillan-utils
22
+
23
+ == Usage
24
+
25
+ === Logger Objects
26
+
27
+ To build logger objects quickly and easily:
28
+
29
+ require 'macmillan/utils/logger'
30
+
31
+ logger = Macmillan::Utils::Logger::Factory.build_logger(:syslog, tag: 'myapp')
32
+
33
+ The logger will automatically use the {Macmillan::Utils::Logger::Formatter} formatter, and will log at the
34
+ {Logger::INFO} level.
35
+
36
+ See the class documentation for more information:
37
+
38
+ * {Macmillan::Utils::Logger::Factory}
39
+ * {Macmillan::Utils::Logger::Formatter}
40
+
41
+ === Settings
42
+
43
+ Easily store and lookup configuration values in either environment variables, or a `application.yml` file.
44
+
45
+ ENV['REDIS_URL'] = 'localhost'
46
+ $settings = Macmillan::Utils::Settings.instance
47
+ redis_url = $settings.lookup('redis_url') #=> 'localhost'
48
+
49
+ The default action is to support BOTH environment variables and a `application.yml` file for settings - if you would
50
+ prefer only one or the other, see the 'Switching Backends' section.
51
+
52
+ If a setting is requested and it has not been set (in any configured backend), a Macmillan::Utils::Settings::KeyNotFoundError
53
+ is raised.
54
+
55
+ ==== Evironment Variables
56
+
57
+ Set your environment variables as you would normally, using all caps for the key name, and you can then fetch the value
58
+ using `.lookup`. Simples.
59
+
60
+ ==== `application.yml` Files
61
+
62
+ If you prefer to use a YAML based config file, this is the option for you. The code will first look for a `application.yml`
63
+ file in a `config` directory (within the current working directory), if it doesn't find one, then it looks in the current
64
+ working directory, and keeps moving up the filesystem until it finds one. If it doesn't it raises an error.
65
+
66
+ ==== Switching Backends
67
+
68
+ By default both the environment variable and application yaml backends are used, if you'd like only one, you need to specify this
69
+ before building the settings instance, i.e.:
70
+
71
+ Macmillan::Utils::Settings.backends = [Macmillan::Utils::Settings::EnvVarsBackend]
72
+
73
+ would only look for environment variables, whereas
74
+
75
+ Macmillan::Utils::Settings.backends = [Macmillan::Utils::Settings::AppYamlBackendBackend]
76
+
77
+ would only look for settings in an `application.yml` file.
78
+
79
+ === RSpec Helpers
80
+
81
+ Add the following to the top of your `spec_helper.rb`:
82
+
83
+ require 'macmillan/utils/rspec/rspec_defaults'
84
+ require 'macmillan/utils/rspec/webmock_helper'
85
+ require 'macmillan/utils/test_helpers/codeclimate_helper'
86
+ require 'macmillan/utils/test_helpers/simplecov_helper'
87
+ require 'macmillan/utils/test_helpers/fixture_loading_helper'
88
+
89
+ === Cucumber Helpers
90
+
91
+ Add the following to the top of your `env.rb`:
92
+
93
+ require 'macmillan/utils/cucumber/cucumber_defaults'
94
+ require 'macmillan/utils/cucumber/webmock_helper'
95
+ require 'macmillan/utils/test_helpers/codeclimate_helper'
96
+ require 'macmillan/utils/test_helpers/simplecov_helper'
97
+ require 'macmillan/utils/test_helpers/fixture_loading_helper'
98
+
99
+ === StatsD
100
+
101
+ * {Macmillan::Utils::StatsdDecorator} - Logging and more for StatsD calls.
102
+ * {Macmillan::Utils::StatsdStub} - Stubbed StatsD class for use in test suites.
103
+ * {Macmillan::Utils::StatsdMiddleware} - Rack middleware for sending web application metrics to StatsD
104
+ * {Macmillan::Utils::StatsdControllerHelper} - Helper functions to send metrics to StatsD via {Macmillan::Utils::StatsdMiddleware}
105
+
106
+ == Contributing
107
+
108
+ 1. Fork it ( https://github.com/nature/macmillan-utils/fork )
109
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
110
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
111
+ 4. Push to the branch (`git push origin my-new-feature`)
112
+ 5. Create a new Pull Request
113
+
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
8
+ task test: :spec
9
+
10
+ YARD::Rake::YardocTask.new do |task|
11
+ task.files = ['lib/**/*.rb']
12
+ end
@@ -0,0 +1,16 @@
1
+ ##
2
+ # Namespace for Macmillan code...
3
+ #
4
+ module Macmillan
5
+ ##
6
+ # Utils module for use in Macmillan applications
7
+ #
8
+ module Utils
9
+ autoload :Logger, 'macmillan/utils/logger'
10
+ autoload :Middleware, 'macmillan/utils/middleware'
11
+ autoload :Settings, 'macmillan/utils/settings'
12
+ autoload :StatsdDecorator, 'macmillan/utils/statsd_decorator'
13
+ autoload :StatsdMiddleware, 'macmillan/utils/statsd_middleware'
14
+ autoload :StatsdControllerHelper, 'macmillan/utils/statsd_controller_helper'
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ module Bundler
2
+ class GemHelper
3
+ def rubygem_push(path)
4
+ gem_server_url = 'http://gems.npgsrv.com'
5
+ sh("gem inabox '#{path}' --host #{gem_server_url}")
6
+ Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_server_url}"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require 'cucumber'
2
+ require 'multi_test'
3
+
4
+ # control rogue test/unit/autorun requires
5
+ MultiTest.disable_autorun
6
+
7
+ # exit the suite after the first failure
8
+ if ENV['FAIL_FAST']
9
+ After do |scenario|
10
+ Cucumber.wants_to_quit = true if scenario.failed?
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ require 'webmock/cucumber'
2
+
3
+ Before do
4
+ WebMock.disable_net_connect!(allow_localhost: true, allow: [/capybara-local/, /codeclimate/])
5
+ end
6
+
7
+ After do
8
+ WebMock.reset!
9
+ end
@@ -0,0 +1,11 @@
1
+ module Macmillan
2
+ module Utils
3
+ ##
4
+ # Namespace for Logger utility classes
5
+ #
6
+ module Logger
7
+ autoload :Factory, 'macmillan/utils/logger/factory'
8
+ autoload :Formatter, 'macmillan/utils/logger/formatter'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,77 @@
1
+ require 'logger'
2
+ require_relative 'formatter'
3
+
4
+ module Macmillan
5
+ module Utils
6
+ module Logger
7
+ ##
8
+ # A factory class for building logger objects
9
+ #
10
+ # === Usage:
11
+ #
12
+ # require 'macmillan/utils/logger'
13
+ #
14
+ # Macmillan::Utils::Logger::Factory.build_logger(type, options)
15
+ #
16
+ class Factory
17
+ ##
18
+ # Builds a logger object
19
+ #
20
+ # Opts varies depending on the type of logger object you are creating:
21
+ #
22
+ # opts for :syslog
23
+ # :tag => [String] the name of the syslog tag to use
24
+ # :facility => [Integer] the 'LOG_LOCALx' syslog facility to use
25
+ #
26
+ # opts for :logger
27
+ # :target => [String, Object] the target for the Logger object
28
+ #
29
+ # opts for :null
30
+ # none
31
+ #
32
+ # @param type [Symbol] the logger type, `:logger`, `:syslog` or `:null`
33
+ # @param opts [Hash] options to pass to your logger object
34
+ # @return [Logger] the configured logger object
35
+ #
36
+ def self.build_logger(type = :logger, opts = {})
37
+ logger = case type
38
+ when :syslog then build_syslog_logger(opts)
39
+ when :null then build_normal_logger(target: '/dev/null')
40
+ else
41
+ build_normal_logger(opts)
42
+ end
43
+
44
+ logger.formatter = ::Macmillan::Utils::Logger::Formatter.new
45
+ logger.level = ::Logger::INFO
46
+
47
+ logger
48
+ end
49
+
50
+ def self.build_syslog_logger(opts)
51
+ require 'syslog-logger'
52
+
53
+ ::Logger::Syslog.class_eval do
54
+ alias_method :write, :info
55
+ alias_method :log, :info
56
+ end
57
+
58
+ tag = opts.fetch(:tag)
59
+ facility = Syslog.const_get("LOG_LOCAL#{opts.fetch(:facility, 0)}")
60
+
61
+ ::Logger::Syslog.new(tag, facility)
62
+ end
63
+ private_class_method :build_syslog_logger
64
+
65
+ def self.build_normal_logger(opts)
66
+ ::Logger.class_eval do
67
+ alias_method :write, :info
68
+ alias_method :log, :info
69
+ end
70
+
71
+ ::Logger.new(opts.fetch(:target, $stdout))
72
+ end
73
+ private_class_method :build_normal_logger
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,48 @@
1
+ module Macmillan
2
+ module Utils
3
+ module Logger
4
+ ##
5
+ # A log formatter class for Logger objects. This formatter is used automatically
6
+ # when you use the {Macmillan::Utils::Logger::Factory} class.
7
+ #
8
+ # === Usage:
9
+ #
10
+ # require 'macmillan/utils/logger'
11
+ #
12
+ # logger = Macmillan::Utils::Logger::Factory.build_logger(type, options)
13
+ #
14
+ class Formatter < ::Logger::Formatter
15
+ ##
16
+ # Builds a new instance of Formatter
17
+ #
18
+ # @param prefix [String] a string to prepend to all log lines
19
+ # @return [Formatter] the configured formatter object
20
+ #
21
+ def initialize(prefix = nil)
22
+ @format = "[%5s]: %s\n"
23
+ @format = "#{prefix} #{@format}" if prefix
24
+ end
25
+
26
+ ##
27
+ # Returns the log message formatted as desired
28
+ #
29
+ def call(severity, _time, _progname, msg)
30
+ @format % [severity, msg2str(msg)]
31
+ end
32
+
33
+ protected
34
+
35
+ def msg2str(msg)
36
+ case msg
37
+ when ::String
38
+ msg
39
+ when ::Exception
40
+ "#{ msg.message } (#{ msg.class })\n" << (msg.backtrace || []).join("\n")
41
+ else
42
+ msg.inspect
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end