mn_utils_gem 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 419e0bfbbf1a78e1c98adcfbb2a9bfac214572f1cfd6c3f7f3b3a261e3e58e2d
4
+ data.tar.gz: bc949046b18e79169aeb93231177fbbcb518fb920d45391a90900e781c7695b6
5
+ SHA512:
6
+ metadata.gz: f6d4f8e1121c6667735824ed70cdd2f5069dcadd8f7fa2cb01c75c6c008d1187a8a507c79c58a15e573e52891163975206ce226e2c9c15f6217f8f998d550086
7
+ data.tar.gz: d9e34a791f3d3c392d23d6ed3fe0f3da90f6413ba2d1da9ff26a898e6d8798629409f252e0384d3753a63f65e1e88fb49044f4fd59517b05dc75df57fd7c4223
@@ -0,0 +1,144 @@
1
+ require 'gelf'
2
+ require 'aws-sdk-cloudwatch'
3
+ require 'request_store'
4
+ require 'singleton'
5
+
6
+ # SiteAction class to log important site actions to Graylog
7
+ # and send a matching metric to Cloudwatch
8
+ #
9
+ # usage: MnUtils::SiteAction.instance.log(message, site_action, optional_payload)
10
+ #
11
+ # eg: MnUtils::SiteAction.instance.log(
12
+ # "Login attempted with non-existent email",
13
+ # :login_attempt_nonexistent_email,
14
+ # {_email: "fish@banana.com", _request_ip: "123.123.123.123"}
15
+ # )
16
+ # This logs all the details in Graylog and records a count of 1
17
+ # against a Cloudwatch metric called login_attempt_nonexistent_email in namespace mn/auth
18
+ #
19
+ # The optional payload should be a simple flat hash with all keys starting
20
+ # with an underscore _ and all values being strings
21
+
22
+ module MnUtils
23
+ class SiteAction
24
+
25
+ include Singleton
26
+
27
+ def initialize
28
+ # add new site actions here under the relevant group
29
+ # NO DUPLICATES please - a site action can only exist under one group
30
+ @_site_actions_and_groups = {
31
+ test: [
32
+ :test_event_1,
33
+ :test_event_2
34
+ ],
35
+ reg: [
36
+ :reg_success_via_email,
37
+ :reg_success_via_google,
38
+ :reg_success_via_facebook,
39
+ :reg_attempt_invalid_email,
40
+ :reg_attempt_invalid_password,
41
+ :reg_attempt_invalid_username,
42
+ ],
43
+ auth: [
44
+ :login_success_via_email,
45
+ :login_success_via_google,
46
+ :login_success_via_facebook,
47
+ :login_attempt_invalid_email,
48
+ :login_attempt_nonexistent_email,
49
+ :login_attempt_invalid_password,
50
+ :login_attempt_incorrect_password,
51
+ ],
52
+ }.freeze
53
+
54
+ # this creates a reverse map of all site actions and their corresponding group
55
+ # for quick lookups by the code
56
+ @_site_action_group_map = Hash[*(@_site_actions_and_groups.map {|k,v| v.map {|x| [x, k]}}.flatten)].freeze
57
+ end
58
+
59
+ def log(message, site_action, payload = {})
60
+
61
+ # validate the parameters
62
+ raise ArgumentError, 'message cannot be blank' \
63
+ if message.blank?
64
+ raise ArgumentError, 'site_action must be a symbol' \
65
+ unless site_action.is_a?(Symbol)
66
+ raise ArgumentError, 'payload must be a hash' \
67
+ unless payload.is_a?(Hash)
68
+ raise ArgumentError, 'site_action value is not in allowed list' \
69
+ unless @_site_action_group_map.key? site_action
70
+
71
+ # validate the payload hash
72
+ payload.each do |key, value|
73
+ raise ArgumentError, "payload key #{key} must be a symbol" \
74
+ unless key.is_a?(Symbol)
75
+ key_string = key.to_s
76
+ raise ArgumentError, "payload key #{key} must begin with an underscore" \
77
+ unless key_string.chars.first == '_'
78
+ raise ArgumentError, "payload key #{key} must be at least 2 characters long" \
79
+ unless key_string.length >= 2
80
+ raise ArgumentError, "payload key cannot be _id" \
81
+ if key_string == '_id'
82
+ raise ArgumentError, "payload value for key #{key} must be a string" \
83
+ unless value.is_a?(String)
84
+ end
85
+
86
+ # validate the environment variables we need
87
+ raise ArgumentError, "ENV['SRV_CODE'] cannot be blank" \
88
+ unless ENV.key? 'SRV_CODE'
89
+
90
+ # setup the full payload
91
+ full_payload = payload.dup
92
+ full_payload[:short_message] = message
93
+ full_payload[:_site_action_group] = @_site_action_group_map[site_action]
94
+ full_payload[:_site_action] = site_action
95
+ full_payload[:_srv_code] = ENV['SRV_CODE']
96
+
97
+ # add the request ID if available
98
+ if RequestStore.store[:request_id]
99
+ full_payload[:_request_id] = RequestStore.store[:request_id]
100
+ end
101
+
102
+ # send it off
103
+ send_to_graylog full_payload
104
+ send_to_cloudwatch full_payload
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def send_to_graylog(payload)
111
+ if ENV.key?('GRAYLOG_GELF_UDP_HOST') && ENV.key?('GRAYLOG_GELF_UDP_PORT')
112
+ n = GELF::Notifier.new(ENV['GRAYLOG_GELF_UDP_HOST'], ENV['GRAYLOG_GELF_UDP_PORT'])
113
+ n.notify! payload
114
+ else
115
+ Rails.logger.debug("Payload for Graylog: #{payload}")
116
+ end
117
+ rescue Exception => e
118
+ Rails.logger.error e
119
+ end
120
+
121
+ def send_to_cloudwatch(payload)
122
+ metric_name = payload[:_site_action]
123
+ metric_data = [{
124
+ metric_name: metric_name,
125
+ value: 1,
126
+ unit: "Count"
127
+ }]
128
+ if ENV.key?'CLOUDWATCH_ROOT_NAMESPACE'
129
+ root_namespace = ENV['CLOUDWATCH_ROOT_NAMESPACE']
130
+ second_namespace = payload[:_site_action_group]
131
+ namespace = "#{root_namespace}/#{second_namespace}"
132
+ cw = Aws::CloudWatch::Client.new
133
+ cw.put_metric_data({
134
+ namespace: namespace,
135
+ metric_data: metric_data
136
+ })
137
+ else
138
+ Rails.logger.debug("Payload for Cloudwatch #{metric_data}")
139
+ end
140
+ rescue Exception => e
141
+ Rails.logger.error e
142
+ end
143
+
144
+ end
@@ -0,0 +1,3 @@
1
+ module MnUtilsGem
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "mn_utils_gem/version"
2
+
3
+ module MnUtilsGem
4
+ class Error < StandardError; end
5
+ # Your code goes here...
6
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mn_utils_gem
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Shamim Mirzai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gelf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk-cloudwatch
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: request_store
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.17'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.17'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description:
98
+ email:
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - lib/mn_utils_gem.rb
104
+ - lib/mn_utils_gem/site_action.rb
105
+ - lib/mn_utils_gem/version.rb
106
+ homepage: https://github.com/mumsnet/mn_utils_gem
107
+ licenses: []
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubygems_version: 3.0.3
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: Mumsnet utils gem for microservices
128
+ test_files: []