Class: AddyLambda::Common

Inherits:
Object
  • Object
show all
Defined in:
lib/addy_lambda/common.rb

Overview

Generic methods such as logging, error handling HTTP requests etc.

Constant Summary collapse

VARIABLE_DIRECT =
'direct'.freeze
VARIABLE_QUERYSTRING =
'querystring'.freeze

Class Method Summary collapse

Class Method Details

.delete_request(url, headers = nil) ⇒ Object



130
131
132
133
134
# File 'lib/addy_lambda/common.rb', line 130

def self.delete_request(url, headers = nil)
  uri = URI(url)
  request = Net::HTTP::Delete.new(uri.request_uri)
  http_request(request, uri, headers)
end

.enable_scout_apmObject



116
117
118
119
120
121
# File 'lib/addy_lambda/common.rb', line 116

def self.enable_scout_apm
  return unless ENV['SCOUT_MONITOR'] == 'true'

  require 'scout_apm'
  ScoutApm::Agent.instance.install
end

.generic_log(logger, event, context, safe_to_log_override = {}) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/addy_lambda/common.rb', line 10

def self.generic_log(logger, event, context, safe_to_log_override = {})
  # Dictionary to allow certain keys to be logged
  # safe_to_log["key"] = True

  safe_to_log = {}

  # Override the dictionar (add or change allowed items)
  safe_to_log.update(safe_to_log_override)

  # logger.info('## ENVIRONMENT VARIABLES\r' +
  #             jsonpickle.encode(dict(**os.environ)))
  #
  # logger = self.logger
  logged_event = recoursive_clean(event, nil, safe_to_log)
  logger.debug('## EVENT')
  logger.debug(logged_event.to_json)
  logger.debug('## CONTEXT')
  logger.debug(context.inspect.to_json)
  # logger.info("## EVENT\r#{logged_event.to_json}")
  # logger.info("## CONTEXT\r#{context.to_json}")
end

.get_body_as_object(event) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/addy_lambda/common.rb', line 60

def self.get_body_as_object(event)
  if event.key?('body') and event['body'].is_a? String
    JSON.parse(event['body'])
  elsif event.key?('body')
    event['body']
  else
    event
  end
end

.get_error_json(context, error) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/addy_lambda/common.rb', line 100

def self.get_error_json(context, error)
  {
    "function_name": context.function_name,
    "errorType": error.class,
    "errorMessage": error.message,
    "stackTrace": error.backtrace,
    "log_group_name": context.log_group_name,
    "log_stream_name": context.log_stream_name,
    "request id": context.aws_request_id
  }.to_json
end

.get_parameter(event, parameter, type, default_value = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/addy_lambda/common.rb', line 70

def self.get_parameter(event, parameter, type, default_value = nil)
  event_body = get_body_as_object(event)

  case type
  when VARIABLE_DIRECT
    event_body.fetch(parameter, default_value)
  when VARIABLE_QUERYSTRING
    event['queryStringParameters'].fetch(parameter, default_value)
  else
    default_value
  end
end

.get_request(url, params = nil, headers = nil) ⇒ Object



123
124
125
126
127
128
# File 'lib/addy_lambda/common.rb', line 123

def self.get_request(url, params = nil, headers = nil)
  uri = URI(url)
  uri.query = URI.encode_www_form(params) if params
  request = Net::HTTP::Get.new(uri.request_uri)
  http_request(request, uri, headers)
end

.handle_error(sns, logger, error, context) ⇒ Object

sns = Aws::SNS::Resource.new(region: region)



84
85
86
87
88
89
90
91
92
93
# File 'lib/addy_lambda/common.rb', line 84

def self.handle_error(sns, logger, error, context)
  region = context.invoked_function_arn.split(':')[3]
   = context.invoked_function_arn.split(':')[4]

  err_msg = get_error_json(context, error)
  logger.error(err_msg)

  topic = sns.topic("arn:aws:sns:#{region}:#{}:system-errors")
  topic.publish(message: err_msg)
end

.handle_error_and_raise(sns, logger, error, context) ⇒ Object



95
96
97
98
# File 'lib/addy_lambda/common.rb', line 95

def self.handle_error_and_raise(sns, logger, error, context)
  handle_error(sns, logger, error, context)
  raise error
end

.http_request(request, uri, headers) ⇒ Object



143
144
145
146
147
148
149
150
# File 'lib/addy_lambda/common.rb', line 143

def self.http_request(request, uri, headers)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  headers&.each { |header, value| request[header] = value }
  response = http.request(request)
  parse_response(response)
end

.loggerObject



161
162
163
# File 'lib/addy_lambda/common.rb', line 161

def self.logger
  @logger ||= Logger.new($stdout).tap { |logger| logger.level = ENV['LOG_LEVEL'].to_i }
end

.parse_response(response) ⇒ Object



152
153
154
155
156
157
158
159
# File 'lib/addy_lambda/common.rb', line 152

def self.parse_response(response)
  response_body = valid_json?(response.body) ? JSON.parse(response.body) : response.body
  return response_body if response.is_a?(Net::HTTPSuccess)

  raise_error_description(response_body['error_description'])
rescue JSON::ParserError => e
  raise_error_description(e.message)
end

.post_request(url, params = nil, headers = nil) ⇒ Object



136
137
138
139
140
141
# File 'lib/addy_lambda/common.rb', line 136

def self.post_request(url, params = nil, headers = nil)
  uri = URI(url)
  request = Net::HTTP::Post.new(uri.request_uri)
  request.set_form_data(params) if params
  http_request(request, uri, headers)
end

.raise_error_description(description) ⇒ Object

Raises:

  • (StandardError)


112
113
114
# File 'lib/addy_lambda/common.rb', line 112

def self.raise_error_description(description)
  raise StandardError, description
end

.recoursive_clean(obj, key, safe_to_log) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/addy_lambda/common.rb', line 32

def self.recoursive_clean(obj, key, safe_to_log)
  if obj.is_a?(Hash)
    # Recoursively run for dictionary objects
    # return {k: recoursive_clean(v, k, safe_to_log) for k, v in obj.items()}
    obj.map { |k, v| { k => recoursive_clean(v, k, safe_to_log) } }
  elsif obj.is_a?(Array)
    # Recoursively run for arrays
    # return [recoursive_clean(v, None, safe_to_log) for v in obj]
    obj.map { |v| [recoursive_clean(v, key, safe_to_log)] }
  elsif !!safe_to_log[key] || (key.to_s.strip.downcase.end_with?('id') && !safe_to_log.key?(key))
    # If the key is safe to log, and is specified as True, or if it's not specified but ends with "id"
    obj
  elsif !obj.nil? && (!!obj == obj || obj.is_a?(String) && %w[yes no].include?(obj.strip.downcase))
    # If it's "yes" / "no" or a boolean, it's safe to log.
    obj
  elsif obj.nil?
    # Null can be logged
    nil
  elsif obj.is_a?(String) && obj.strip.empty?
    # An empty string can be logged
    ''
  else
    # Anything else becomes a "?"
    # Note: This means that a number will become a "?" string.
    '?'
  end
end

.valid_json?(json) ⇒ Boolean

Returns:

  • (Boolean)


165
166
167
168
169
170
# File 'lib/addy_lambda/common.rb', line 165

def self.valid_json?(json)
  JSON.parse(json)
  true
rescue JSON::ParserError
  false
end