hoodoo 1.5.2 → 1.6.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 +8 -8
- data/lib/hoodoo/logger/logger.rb +44 -6
- data/lib/hoodoo/services/middleware/amqp_log_writer.rb +11 -14
- data/lib/hoodoo/services/middleware/middleware.rb +148 -76
- data/lib/hoodoo/services/services/session.rb +24 -9
- data/lib/hoodoo/version.rb +1 -1
- data/spec/logger/logger_spec.rb +67 -1
- data/spec/services/middleware/amqp_log_writer_spec.rb +20 -11
- data/spec/services/middleware/middleware_logging_spec.rb +174 -46
- data/spec/services/services/session_spec.rb +24 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MmIwZDk4ODJmMWM2MGQ0MjIwNWMwYTRjZTZlZjE3NDM5NWUxOTgzYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDA4ODMwYjc2Zjc1MTQ1Njk0YzMxNzRiMTFjMDRkYTdmMTI2MTA3YQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MzRlYzJiNDcyMjcxNzg1NWI0MGU2Y2IyMTFmZTI5Y2I4NTkxNGE1YmZkZWM2
|
10
|
+
ZWM4MmZhNzZkNjNhZmY0ZDM5Mjg5Mjg4NDgzYTM0YzExNDAwNDk0MDkwODIz
|
11
|
+
MThkNGYwMWM3Njg3ZGQwNmIyMjM3ZjcxMzg5MDU2YzZiMzk0NmE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YWViZTVjNDRkZTM1ZTYzZmRlYjg5YmU2YThjYTNjN2RhYTAyZGNmNjQxZmY2
|
14
|
+
NDQ3ZDM2MmVmMGRmMzg2YWI1MTk5NDJlNWVkZWM2ZmNlNDZmYmM5NjUwMjYw
|
15
|
+
MzI1MzAxMDQ4MTMwY2JmN2NiNTI1ZTk0MmM1NTE2ZTU2NGU4ZTE=
|
data/lib/hoodoo/logger/logger.rb
CHANGED
@@ -103,13 +103,17 @@ module Hoodoo
|
|
103
103
|
# Internal default timeouts may even mean that the writer is still running
|
104
104
|
# (possibly entirely hung).
|
105
105
|
#
|
106
|
-
# +
|
107
|
-
#
|
108
|
-
#
|
106
|
+
# +writer_instances+:: One or more _instances_ of a subclass of
|
107
|
+
# Hoodoo::Logger::FastWriter or
|
108
|
+
# Hoodoo::Logger::SlowWriter, passed as one or
|
109
|
+
# more comma-separated parameters.
|
109
110
|
#
|
110
|
-
def remove(
|
111
|
-
|
112
|
-
|
111
|
+
def remove( *writer_instances )
|
112
|
+
writer_instances.each do | writer_instance |
|
113
|
+
communicator = @writers[ writer_instance ]
|
114
|
+
@pool.remove( communicator ) unless communicator.nil?
|
115
|
+
@writers.delete( writer_instance )
|
116
|
+
end
|
113
117
|
end
|
114
118
|
|
115
119
|
# Remove all writer instances from this logger.
|
@@ -124,6 +128,40 @@ module Hoodoo
|
|
124
128
|
@writers = {}
|
125
129
|
end
|
126
130
|
|
131
|
+
# Does this log instance's collection of writers include the given writer
|
132
|
+
# instance? Returns +true+ if so, else +false+.
|
133
|
+
#
|
134
|
+
# +writer_instance+:: An _instance_ of a subclass of
|
135
|
+
# Hoodoo::Logger::FastWriter or
|
136
|
+
# Hoodoo::Logger::SlowWriter.
|
137
|
+
#
|
138
|
+
def include?( writer_instance )
|
139
|
+
@writers.has_key?( writer_instance )
|
140
|
+
end
|
141
|
+
|
142
|
+
alias_method( :includes?, :include? )
|
143
|
+
|
144
|
+
# Does this log instance's collection of writers include any writer
|
145
|
+
# instances which are of the given writer _class_? Returns +true+ if so,
|
146
|
+
# else +false+.
|
147
|
+
#
|
148
|
+
# This is slower than #include? so try to work with writer instance
|
149
|
+
# queries rather than writer class queries if you can.
|
150
|
+
#
|
151
|
+
# +writer_class+:: A _subclass_ (class reference, not instance) of
|
152
|
+
# Hoodoo::Logger::FastWriter or
|
153
|
+
# Hoodoo::Logger::SlowWriter.
|
154
|
+
#
|
155
|
+
def include_class?( writer_class )
|
156
|
+
@writers.keys.each do | writer_instance |
|
157
|
+
return true if writer_instance.is_a?( writer_class )
|
158
|
+
end
|
159
|
+
|
160
|
+
return false
|
161
|
+
end
|
162
|
+
|
163
|
+
alias_method( :includes_class?, :include_class? )
|
164
|
+
|
127
165
|
# Returns an array of all log writer instances currently in use, in order
|
128
166
|
# of addition. See #add.
|
129
167
|
#
|
@@ -65,25 +65,22 @@ module Hoodoo; module Services
|
|
65
65
|
def report( level, component, code, data )
|
66
66
|
return if @alchemy.nil?
|
67
67
|
|
68
|
-
# Take care with Symbol keys in 'data' vs string keys in e.g. '
|
69
|
-
|
70
|
-
data[ :id ] ||= Hoodoo::UUID.generate()
|
68
|
+
# Take care with Symbol keys in 'data' vs string keys in e.g. 'session'.
|
71
69
|
|
72
70
|
session = data[ :session ] || {}
|
73
71
|
message = {
|
72
|
+
:id => data[ :id ],
|
73
|
+
:level => level,
|
74
|
+
:component => component,
|
75
|
+
:code => code,
|
76
|
+
:reported_at => Time.now.iso8601( 12 ),
|
74
77
|
|
75
|
-
:
|
76
|
-
:
|
77
|
-
:component => component,
|
78
|
-
:code => code,
|
79
|
-
:reported_at => Time.now.iso8601( 12 ),
|
80
|
-
|
81
|
-
:data => data,
|
82
|
-
|
83
|
-
:interaction_id => data[ :interaction_id ],
|
84
|
-
:caller_id => session[ 'caller_id' ],
|
85
|
-
:identity => ( session[ 'identity' ] || {} ).to_h
|
78
|
+
:interaction_id => data[ :interaction_id ],
|
79
|
+
:data => data,
|
86
80
|
|
81
|
+
:caller_id => session[ 'caller_id' ],
|
82
|
+
:caller_identity_name => session[ 'caller_identity_name' ],
|
83
|
+
:identity => ( session[ 'identity' ] || {} ).to_h
|
87
84
|
}.to_json()
|
88
85
|
|
89
86
|
@alchemy.send_message_to_service( @routing_key, { "body" => message } )
|
@@ -159,15 +159,16 @@ module Hoodoo; module Services
|
|
159
159
|
# middleware for simplicity/speed at parse time.
|
160
160
|
#
|
161
161
|
DEFAULT_TEST_SESSION.from_h!( {
|
162
|
-
'session_id'
|
163
|
-
'expires_at'
|
164
|
-
'caller_version'
|
165
|
-
'caller_id'
|
166
|
-
'
|
167
|
-
'
|
162
|
+
'session_id' => '01234567890123456789012345678901',
|
163
|
+
'expires_at' => ( Time.now + 172800 ).utc.iso8601,
|
164
|
+
'caller_version' => 1,
|
165
|
+
'caller_id' => 'c5ea12fb7f414a46850e73ee1bf6d95e',
|
166
|
+
'caller_identity_name' => 'c5ea12fb7f414a46850e73ee1bf6d95e',
|
167
|
+
'identity' => { 'caller_id' => 'c5ea12fb7f414a46850e73ee1bf6d95e' },
|
168
|
+
'permissions' => Hoodoo::Services::Permissions.new( {
|
168
169
|
'default' => { 'else' => Hoodoo::Services::Permissions::ALLOW }
|
169
170
|
} ).to_h,
|
170
|
-
'scoping'
|
171
|
+
'scoping' => {
|
171
172
|
'authorised_http_headers' => Hoodoo::Client::Headers::HEADER_TO_PROPERTY.map() { | key, sub_hash |
|
172
173
|
sub_hash[ :header ] if sub_hash[ :secured ] == true
|
173
174
|
}.compact
|
@@ -322,6 +323,29 @@ module Hoodoo; module Services
|
|
322
323
|
self.send( :add_file_logging, base_path )
|
323
324
|
end
|
324
325
|
|
326
|
+
# Set verbose logging. With verbose logging enabled, additional payload
|
327
|
+
# data is added - most notably, full session details (where possible)
|
328
|
+
# are included in each log message. These can increase log data size
|
329
|
+
# considerably, but may be useful if you encounter session-related
|
330
|
+
# errors or general operational issues and need log data to provide more
|
331
|
+
# insights.
|
332
|
+
#
|
333
|
+
# Verbose logging is _disabled_ by default.
|
334
|
+
#
|
335
|
+
# +verbose+:: +true+ to enable verbose logging, +false+ to disable it.
|
336
|
+
# The default is +false+.
|
337
|
+
#
|
338
|
+
def self.set_verbose_logging( verbose )
|
339
|
+
@@verbose_logging = verbose
|
340
|
+
end
|
341
|
+
|
342
|
+
# Returns +true+ if verbose logging is enabled, else +false+. For more,
|
343
|
+
# see ::set_verbose_logging.
|
344
|
+
#
|
345
|
+
def self.verbose_logging?
|
346
|
+
defined?( @@verbose_logging ) ? @@verbose_logging : false
|
347
|
+
end
|
348
|
+
|
325
349
|
# A Hoodoo::Services::Session instance to use for tests or when no
|
326
350
|
# local Memcached instance is known about (environment variable
|
327
351
|
# +MEMCACHED_HOST+ is not set). The session is (eventually) read each
|
@@ -1037,6 +1061,55 @@ module Hoodoo; module Services
|
|
1037
1061
|
end
|
1038
1062
|
end
|
1039
1063
|
|
1064
|
+
# Build common log information for the 'data' part of a payload based
|
1065
|
+
# on the given interaction. Returned as a Hash with Symbol keys.
|
1066
|
+
#
|
1067
|
+
# +interaction+:: Hoodoo::Services::Interaction describing a request.
|
1068
|
+
# A +context+ and +interaction_id+ are expected. The
|
1069
|
+
# +target_interface+ and +requested_action+ are optional
|
1070
|
+
# and if present result in a <tt>:target</tt> entry in
|
1071
|
+
# the returned Hash. The +context.session+ value if
|
1072
|
+
# present will be included in a <tt>:session</tt> entry;
|
1073
|
+
# if verbose logging is enabled this will be quoted in
|
1074
|
+
# full, else only identity-related parts are recorded.
|
1075
|
+
#
|
1076
|
+
def build_common_log_data_for( interaction )
|
1077
|
+
|
1078
|
+
session = interaction.context.session
|
1079
|
+
interface = interaction.target_interface
|
1080
|
+
action = interaction.requested_action
|
1081
|
+
|
1082
|
+
data = {
|
1083
|
+
:id => Hoodoo::UUID.generate(),
|
1084
|
+
:interaction_id => interaction.interaction_id
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
unless session.nil?
|
1088
|
+
if self.class.verbose_logging?
|
1089
|
+
data[ :session ] = session.to_h
|
1090
|
+
else
|
1091
|
+
data[ :session ] =
|
1092
|
+
{
|
1093
|
+
'session_id' => session.session_id,
|
1094
|
+
'caller_id' => session.caller_id,
|
1095
|
+
'caller_version' => session.caller_version,
|
1096
|
+
'caller_identity_name' => session.caller_identity_name,
|
1097
|
+
'identity' => Hoodoo::Utilities.stringify( ( session.identity || {} ).to_h() )
|
1098
|
+
}
|
1099
|
+
end
|
1100
|
+
end
|
1101
|
+
|
1102
|
+
unless interface.nil? || action.nil?
|
1103
|
+
data[ :target ] = {
|
1104
|
+
:resource => ( interface.resource || '' ).to_s,
|
1105
|
+
:version => interface.version,
|
1106
|
+
:action => ( action || '' ).to_s,
|
1107
|
+
}
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
return data
|
1111
|
+
end
|
1112
|
+
|
1040
1113
|
# Make an "inbound" call log based on the given interaction.
|
1041
1114
|
#
|
1042
1115
|
# +interaction+:: Hoodoo::Services::Interaction describing the inbound
|
@@ -1049,6 +1122,8 @@ module Hoodoo; module Services
|
|
1049
1122
|
#
|
1050
1123
|
def log_inbound_request( interaction )
|
1051
1124
|
|
1125
|
+
data = build_common_log_data_for( interaction )
|
1126
|
+
|
1052
1127
|
# Annoying dance required to extract all HTTP header data from Rack.
|
1053
1128
|
|
1054
1129
|
env = interaction.rack_request.env
|
@@ -1059,27 +1134,26 @@ module Hoodoo; module Services
|
|
1059
1134
|
headers[ 'CONTENT_TYPE' ] = env[ 'CONTENT_TYPE' ]
|
1060
1135
|
headers[ 'CONTENT_LENGTH' ] = env[ 'CONTENT_LENGTH' ]
|
1061
1136
|
|
1062
|
-
data = {
|
1063
|
-
:
|
1064
|
-
:
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
:query => env[ 'QUERY_STRING' ],
|
1072
|
-
:headers => headers
|
1073
|
-
}
|
1137
|
+
data[ :payload ] = {
|
1138
|
+
:method => env[ 'REQUEST_METHOD', ],
|
1139
|
+
:scheme => env[ 'rack.url_scheme' ],
|
1140
|
+
:host => env[ 'SERVER_NAME' ],
|
1141
|
+
:port => env[ 'SERVER_PORT' ],
|
1142
|
+
:script => env[ 'SCRIPT_NAME' ],
|
1143
|
+
:path => env[ 'PATH_INFO' ],
|
1144
|
+
:query => env[ 'QUERY_STRING' ],
|
1145
|
+
:headers => headers
|
1074
1146
|
}
|
1075
1147
|
|
1076
1148
|
# Deal with body data and security issues.
|
1077
1149
|
|
1078
|
-
secure
|
1150
|
+
secure = true
|
1151
|
+
interface = interaction.target_interface
|
1152
|
+
action = interaction.requested_action
|
1079
1153
|
|
1080
|
-
unless
|
1081
|
-
secure_log_actions =
|
1082
|
-
secure_type
|
1154
|
+
unless interface.nil? || action.nil?
|
1155
|
+
secure_log_actions = interface.secure_log_for()
|
1156
|
+
secure_type = secure_log_actions[ action ]
|
1083
1157
|
|
1084
1158
|
# Allow body logging if there's no security specified for this action
|
1085
1159
|
# or the security is specified for the response only (since we log the
|
@@ -1089,14 +1163,6 @@ module Hoodoo; module Services
|
|
1089
1163
|
# as will any other unexpected value that might get specified.
|
1090
1164
|
|
1091
1165
|
secure = false if secure_type.nil? || secure_type == :response
|
1092
|
-
|
1093
|
-
# Fill in unrelated useful data since we know it is available here.
|
1094
|
-
|
1095
|
-
data[ :target ] = {
|
1096
|
-
:resource => ( interaction.target_interface.resource || '' ).to_s,
|
1097
|
-
:version => interaction.target_interface.version,
|
1098
|
-
:action => ( interaction.requested_action || '' ).to_s
|
1099
|
-
}
|
1100
1166
|
end
|
1101
1167
|
|
1102
1168
|
# Compile the remaining log payload and send it.
|
@@ -1143,17 +1209,7 @@ module Hoodoo; module Services
|
|
1143
1209
|
#
|
1144
1210
|
return if ( context.response.halt_processing? )
|
1145
1211
|
|
1146
|
-
|
1147
|
-
|
1148
|
-
data = {
|
1149
|
-
:interaction_id => interaction.interaction_id,
|
1150
|
-
:session => ( interaction.context.session || {} ).to_h,
|
1151
|
-
:target => {
|
1152
|
-
:resource => ( interface.resource || '' ).to_s,
|
1153
|
-
:version => interface.version,
|
1154
|
-
:action => ( action || '' ).to_s,
|
1155
|
-
}
|
1156
|
-
}
|
1212
|
+
data = build_common_log_data_for( interaction )
|
1157
1213
|
|
1158
1214
|
# Don't bother logging list responses - they could be huge - instead
|
1159
1215
|
# log all list-related parameters from the inbound request. At least
|
@@ -1174,7 +1230,7 @@ module Hoodoo; module Services
|
|
1174
1230
|
|
1175
1231
|
unless interface.nil? || action.nil?
|
1176
1232
|
secure_log_actions = interface.secure_log_for()
|
1177
|
-
secure_type
|
1233
|
+
secure_type = secure_log_actions[ action ]
|
1178
1234
|
|
1179
1235
|
# Allow body logging if there's no security specified for this action
|
1180
1236
|
# or the security is specified for the request only (since we log the
|
@@ -1211,25 +1267,22 @@ module Hoodoo; module Services
|
|
1211
1267
|
# the interaction currently being logged.
|
1212
1268
|
#
|
1213
1269
|
def log_outbound_response( interaction, rack_data )
|
1214
|
-
secure = true
|
1215
|
-
id = nil
|
1216
|
-
level = if interaction.context.response.halt_processing?
|
1217
|
-
:error
|
1218
|
-
else
|
1219
|
-
:info
|
1220
|
-
end
|
1221
1270
|
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1271
|
+
level = interaction.context.response.halt_processing? ? :error : :info
|
1272
|
+
data = build_common_log_data_for( interaction )
|
1273
|
+
|
1274
|
+
data[ :payload ] = {
|
1275
|
+
:http_status_code => rack_data[ 0 ].to_i,
|
1276
|
+
:http_headers => rack_data[ 1 ]
|
1228
1277
|
}
|
1229
1278
|
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1279
|
+
secure = true
|
1280
|
+
interface = interaction.target_interface
|
1281
|
+
action = interaction.requested_action
|
1282
|
+
|
1283
|
+
unless interface.nil? || action.nil?
|
1284
|
+
secure_log_actions = interface.secure_log_for()
|
1285
|
+
secure_type = secure_log_actions[ action ]
|
1233
1286
|
|
1234
1287
|
# Allow body logging if there's no security specified for this action
|
1235
1288
|
# or the security is specified for the request only (since we log the
|
@@ -1239,12 +1292,6 @@ module Hoodoo; module Services
|
|
1239
1292
|
# as will any other unexpected value that might get specified.
|
1240
1293
|
|
1241
1294
|
secure = false if secure_type.nil? || secure_type == :request
|
1242
|
-
|
1243
|
-
data[ :target ] = {
|
1244
|
-
:resource => ( interaction.target_interface.resource || '' ).to_s,
|
1245
|
-
:version => interaction.target_interface.version,
|
1246
|
-
:action => ( interaction.requested_action || '' ).to_s
|
1247
|
-
}
|
1248
1295
|
end
|
1249
1296
|
|
1250
1297
|
if secure == false || level == :error
|
@@ -1263,7 +1310,9 @@ module Hoodoo; module Services
|
|
1263
1310
|
# persistence layers store the item as an error with the correct ID.
|
1264
1311
|
|
1265
1312
|
body = ::JSON.parse( body )
|
1266
|
-
|
1313
|
+
|
1314
|
+
uuid = body[ 'id' ]
|
1315
|
+
data[ :id ] = uuid unless uuid.nil?
|
1267
1316
|
rescue
|
1268
1317
|
end
|
1269
1318
|
|
@@ -1275,9 +1324,6 @@ module Hoodoo; module Services
|
|
1275
1324
|
data[ :payload ][ :response_body ] = body
|
1276
1325
|
end
|
1277
1326
|
|
1278
|
-
data[ :id ] = id unless id.nil?
|
1279
|
-
data[ :session ] = interaction.context.session.to_h unless interaction.context.session.nil?
|
1280
|
-
|
1281
1327
|
@@logger.report(
|
1282
1328
|
level,
|
1283
1329
|
:Middleware,
|
@@ -1310,17 +1356,14 @@ module Hoodoo; module Services
|
|
1310
1356
|
|
1311
1357
|
return unless @@logger.report?( :debug )
|
1312
1358
|
|
1359
|
+
data = build_common_log_data_for( interaction )
|
1360
|
+
|
1313
1361
|
scheme = interaction.rack_request.scheme || 'unknown_scheme'
|
1314
1362
|
host_with_port = interaction.rack_request.host_with_port || 'unknown_host'
|
1315
1363
|
full_path = interaction.rack_request.fullpath || '/unknown_path'
|
1316
1364
|
|
1317
|
-
data = {
|
1318
|
-
|
1319
|
-
:interaction_id => interaction.interaction_id,
|
1320
|
-
:payload => { 'args' => args }
|
1321
|
-
}
|
1322
|
-
|
1323
|
-
data[ :session ] = interaction.context.session.to_h unless interaction.context.session.nil?
|
1365
|
+
data[ :full_uri ] = "#{ scheme }://#{ host_with_port }#{ full_path }"
|
1366
|
+
data[ :payload ] = { 'args' => args }
|
1324
1367
|
|
1325
1368
|
@@logger.report(
|
1326
1369
|
:debug,
|
@@ -1353,6 +1396,35 @@ module Hoodoo; module Services
|
|
1353
1396
|
def respond_for( interaction, preflight = false )
|
1354
1397
|
interaction.context.response.body = '' if preflight
|
1355
1398
|
|
1399
|
+
# Oddly placed code for efficiency and sanity.
|
1400
|
+
#
|
1401
|
+
# When #log_outbound_response is called below, it would make sense to
|
1402
|
+
# use its existing code path for logging errors and include a variant of
|
1403
|
+
# the "if" below to add the X-Error-Logged-Via-Alchemy HTTP header if
|
1404
|
+
# required down at that level.
|
1405
|
+
#
|
1406
|
+
# However, we want the Rack response payload all wrapped up for the log
|
1407
|
+
# and it's generated here, then passed in; somehow the logging method
|
1408
|
+
# would need to update the now-compiled Rack data, or we generate the
|
1409
|
+
# Rack data again on exit, but then the logged Rack data would be wrong.
|
1410
|
+
#
|
1411
|
+
# To solve all this, just deal with the an-error-was-logged header here,
|
1412
|
+
# before we log anything or generate Rack information.
|
1413
|
+
|
1414
|
+
if (
|
1415
|
+
interaction.context.response.halt_processing? &&
|
1416
|
+
self.class.on_queue? &&
|
1417
|
+
defined?( @@alchemy ) &&
|
1418
|
+
@@logger.include_class?( Hoodoo::Services::Middleware::AMQPLogWriter )
|
1419
|
+
)
|
1420
|
+
|
1421
|
+
interaction.context.response.add_header(
|
1422
|
+
'X-Error-Logged-Via-Alchemy',
|
1423
|
+
'yes',
|
1424
|
+
true
|
1425
|
+
)
|
1426
|
+
end
|
1427
|
+
|
1356
1428
|
rack_data = interaction.context.response.for_rack()
|
1357
1429
|
log_outbound_response( interaction, rack_data )
|
1358
1430
|
|
@@ -32,6 +32,14 @@ module Hoodoo
|
|
32
32
|
#
|
33
33
|
attr_accessor :caller_id
|
34
34
|
|
35
|
+
# An optional property of a session is the Caller's "identity name",
|
36
|
+
# a generic way to refer to this Caller which will appear in logs.
|
37
|
+
# The use is up to the session creator, in combination with whatever
|
38
|
+
# logging engine is in use; if it ascribes meaning to the identity
|
39
|
+
# name, then the session creator must ensure it comforms.
|
40
|
+
#
|
41
|
+
attr_accessor :caller_identity_name
|
42
|
+
|
35
43
|
# Callers can change; if so, related sessions must be invalidated.
|
36
44
|
# This must be achieved by keeping a version count on the Caller. A
|
37
45
|
# session is associated with a particular Caller version and if the
|
@@ -192,7 +200,7 @@ module Hoodoo
|
|
192
200
|
self.to_h(),
|
193
201
|
TTL )
|
194
202
|
|
195
|
-
rescue
|
203
|
+
rescue => exception
|
196
204
|
|
197
205
|
# Log error and return nil if the session can't be parsed
|
198
206
|
#
|
@@ -245,7 +253,7 @@ module Hoodoo
|
|
245
253
|
end
|
246
254
|
end
|
247
255
|
|
248
|
-
rescue
|
256
|
+
rescue => exception
|
249
257
|
|
250
258
|
# Log error and return nil if the session can't be parsed
|
251
259
|
#
|
@@ -301,7 +309,7 @@ module Hoodoo
|
|
301
309
|
return :ok
|
302
310
|
end
|
303
311
|
|
304
|
-
rescue
|
312
|
+
rescue => exception
|
305
313
|
|
306
314
|
# Log error and return nil if the session can't be parsed
|
307
315
|
#
|
@@ -337,7 +345,7 @@ module Hoodoo
|
|
337
345
|
return :not_found
|
338
346
|
end
|
339
347
|
|
340
|
-
rescue
|
348
|
+
rescue => exception
|
341
349
|
|
342
350
|
# Log error and return nil if the session can't be parsed
|
343
351
|
#
|
@@ -376,6 +384,7 @@ module Hoodoo
|
|
376
384
|
session_id
|
377
385
|
caller_id
|
378
386
|
caller_version
|
387
|
+
caller_identity_name
|
379
388
|
|
380
389
|
).each do | property |
|
381
390
|
value = self.send( property )
|
@@ -420,6 +429,7 @@ module Hoodoo
|
|
420
429
|
session_id
|
421
430
|
caller_id
|
422
431
|
caller_version
|
432
|
+
caller_identity_name
|
423
433
|
|
424
434
|
).each do | property |
|
425
435
|
value = hash[ property ]
|
@@ -549,8 +559,9 @@ module Hoodoo
|
|
549
559
|
raise 'Hoodoo::Services::Session.connect_to_memcached: The Memcached connection host data is nil or empty'
|
550
560
|
end
|
551
561
|
|
552
|
-
|
553
|
-
|
562
|
+
exception = nil
|
563
|
+
stats = nil
|
564
|
+
mclient = nil
|
554
565
|
|
555
566
|
begin
|
556
567
|
@@dalli_clients ||= {}
|
@@ -565,13 +576,17 @@ module Hoodoo
|
|
565
576
|
|
566
577
|
stats = @@dalli_clients[ host ].stats()
|
567
578
|
|
568
|
-
rescue
|
569
|
-
|
579
|
+
rescue => e
|
580
|
+
exception = e
|
570
581
|
|
571
582
|
end
|
572
583
|
|
573
584
|
if stats.nil?
|
574
|
-
|
585
|
+
if exception.nil?
|
586
|
+
raise "Hoodoo::Services::Session.connect_to_memcached: Did not get back meaningful data from Memcached at '#{ host }'"
|
587
|
+
else
|
588
|
+
raise "Hoodoo::Services::Session.connect_to_memcached: Cannot connect to Memcached at '#{ host }': #{ exception.to_s }"
|
589
|
+
end
|
575
590
|
else
|
576
591
|
return @@dalli_clients[ host ]
|
577
592
|
end
|
data/lib/hoodoo/version.rb
CHANGED
data/spec/logger/logger_spec.rb
CHANGED
@@ -51,7 +51,7 @@ describe Hoodoo::Logger do
|
|
51
51
|
@logger.error( 'Three instances of StreamWriter' )
|
52
52
|
end
|
53
53
|
|
54
|
-
it 'removes requested
|
54
|
+
it 'removes a requested instance' do
|
55
55
|
@logger.remove( @stderr_2 )
|
56
56
|
|
57
57
|
expect( @stderr_1 ).to receive( :report ).once
|
@@ -62,6 +62,17 @@ describe Hoodoo::Logger do
|
|
62
62
|
@logger.error( 'Two instances of StreamWriter' )
|
63
63
|
end
|
64
64
|
|
65
|
+
it 'removes two requested instances' do
|
66
|
+
@logger.remove( @stderr_3, @stderr_2 )
|
67
|
+
|
68
|
+
expect( @stderr_1 ).to receive( :report ).once
|
69
|
+
expect( @stderr_2 ).to_not receive( :report )
|
70
|
+
expect( @stderr_3 ).to_not receive( :report )
|
71
|
+
expect( $stderr ).to_not receive( :puts )
|
72
|
+
|
73
|
+
@logger.error( 'One instance of StreamWriter' )
|
74
|
+
end
|
75
|
+
|
65
76
|
it 'removes all instances' do
|
66
77
|
@logger.remove_all
|
67
78
|
|
@@ -161,6 +172,61 @@ describe Hoodoo::Logger do
|
|
161
172
|
|
162
173
|
# ===========================================================================
|
163
174
|
|
175
|
+
context 'enquiries' do
|
176
|
+
before :each do
|
177
|
+
@logger = described_class.new
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'via include(s)? work' do
|
181
|
+
a = Hoodoo::Logger::StreamWriter.new( $stderr )
|
182
|
+
b = Hoodoo::Logger::StreamWriter.new( $stderr )
|
183
|
+
c = Hoodoo::Logger::StreamWriter.new( $stderr )
|
184
|
+
|
185
|
+
@logger.add( a, b )
|
186
|
+
|
187
|
+
expect( @logger.include?( a ) ).to eq( true )
|
188
|
+
expect( @logger.include?( b ) ).to eq( true )
|
189
|
+
expect( @logger.include?( c ) ).to eq( false )
|
190
|
+
|
191
|
+
expect( @logger.includes?( a ) ).to eq( true )
|
192
|
+
expect( @logger.includes?( b ) ).to eq( true )
|
193
|
+
expect( @logger.includes?( c ) ).to eq( false )
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'via include(s)_class? work' do
|
197
|
+
a = Hoodoo::Logger::StreamWriter.new( $stderr )
|
198
|
+
b = Hoodoo::Logger::StreamWriter.new( $stderr )
|
199
|
+
c = Hoodoo::Logger::FileWriter.new( 'file1' )
|
200
|
+
d = Hoodoo::Logger::FileWriter.new( 'file2' )
|
201
|
+
|
202
|
+
@logger.add( a, b )
|
203
|
+
|
204
|
+
expect( @logger.include_class?( Hoodoo::Logger::StreamWriter ) ).to eq( true )
|
205
|
+
expect( @logger.include_class?( Hoodoo::Logger::FileWriter ) ).to eq( false )
|
206
|
+
|
207
|
+
expect( @logger.includes_class?( Hoodoo::Logger::StreamWriter ) ).to eq( true )
|
208
|
+
expect( @logger.includes_class?( Hoodoo::Logger::FileWriter ) ).to eq( false )
|
209
|
+
|
210
|
+
@logger.add( c, d )
|
211
|
+
|
212
|
+
expect( @logger.include_class?( Hoodoo::Logger::StreamWriter ) ).to eq( true )
|
213
|
+
expect( @logger.include_class?( Hoodoo::Logger::FileWriter ) ).to eq( true )
|
214
|
+
|
215
|
+
expect( @logger.includes_class?( Hoodoo::Logger::StreamWriter ) ).to eq( true )
|
216
|
+
expect( @logger.includes_class?( Hoodoo::Logger::FileWriter ) ).to eq( true )
|
217
|
+
|
218
|
+
@logger.remove( a, b )
|
219
|
+
|
220
|
+
expect( @logger.include_class?( Hoodoo::Logger::StreamWriter ) ).to eq( false )
|
221
|
+
expect( @logger.include_class?( Hoodoo::Logger::FileWriter ) ).to eq( true )
|
222
|
+
|
223
|
+
expect( @logger.includes_class?( Hoodoo::Logger::StreamWriter ) ).to eq( false )
|
224
|
+
expect( @logger.includes_class?( Hoodoo::Logger::FileWriter ) ).to eq( true )
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# ===========================================================================
|
229
|
+
|
164
230
|
context 'legacy logging' do
|
165
231
|
before :each do
|
166
232
|
@logger = described_class.new
|
@@ -35,6 +35,7 @@ describe Hoodoo::Services::Middleware::AMQPLogWriter do
|
|
35
35
|
@identity_id_1 = Hoodoo::UUID.generate
|
36
36
|
@identity_id_2 = Hoodoo::UUID.generate
|
37
37
|
@identity_id_3 = Hoodoo::UUID.generate
|
38
|
+
@identity_id_4 = Hoodoo::UUID.generate
|
38
39
|
|
39
40
|
@authorised_ids = [ Hoodoo::UUID.generate, Hoodoo::UUID.generate ]
|
40
41
|
@authorised_codes = [ 'CODE_A', 'CODE_B' ]
|
@@ -50,6 +51,8 @@ describe Hoodoo::Services::Middleware::AMQPLogWriter do
|
|
50
51
|
:authorised_codes => @authorised_codes
|
51
52
|
}
|
52
53
|
|
54
|
+
@session.caller_identity_name = @identity_id_4
|
55
|
+
|
53
56
|
@alchemy = OpenStruct.new
|
54
57
|
@queue = 'foo.bar'
|
55
58
|
@logger = described_class.new( @alchemy, @queue )
|
@@ -65,22 +68,28 @@ describe Hoodoo::Services::Middleware::AMQPLogWriter do
|
|
65
68
|
interaction_id = Hoodoo::UUID.generate
|
66
69
|
data = {
|
67
70
|
:id => id,
|
68
|
-
:
|
69
|
-
:
|
71
|
+
:interaction_id => interaction_id,
|
72
|
+
:session =>
|
73
|
+
{
|
74
|
+
'caller_id' => @session.caller_id,
|
75
|
+
'caller_identity_name' => @session.caller_identity_name,
|
76
|
+
'identity' => @session.identity.to_h()
|
77
|
+
}
|
70
78
|
}
|
71
79
|
|
72
80
|
expected_hash = {
|
73
|
-
:id
|
74
|
-
:level
|
75
|
-
:component
|
76
|
-
:code
|
77
|
-
:reported_at
|
81
|
+
:id => id,
|
82
|
+
:level => 'warn',
|
83
|
+
:component => component,
|
84
|
+
:code => code,
|
85
|
+
:reported_at => reported_at,
|
78
86
|
|
79
|
-
:
|
87
|
+
:interaction_id => interaction_id,
|
88
|
+
:data => data,
|
80
89
|
|
81
|
-
:
|
82
|
-
:
|
83
|
-
:identity
|
90
|
+
:caller_id => @caller_id,
|
91
|
+
:caller_identity_name => @identity_id_4,
|
92
|
+
:identity => Hoodoo::Utilities.stringify( @session.identity.to_h )
|
84
93
|
}
|
85
94
|
|
86
95
|
expect( @alchemy ).to receive( :send_message_to_service ).with( @queue, { "body" => expected_hash.to_json } ).once
|
@@ -123,13 +123,6 @@ describe Hoodoo::Services::Middleware do
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
def app
|
127
|
-
Rack::Builder.new do
|
128
|
-
use Hoodoo::Services::Middleware
|
129
|
-
run TestLogService.new
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
126
|
it 'has the expected "test" mode loggers' do
|
134
127
|
instances = force_logging_to( 'test' )
|
135
128
|
|
@@ -235,9 +228,91 @@ describe Hoodoo::Services::Middleware do
|
|
235
228
|
expect( instances[ 0 ] ).to be_a( Hoodoo::Services::Middleware::AMQPLogWriter )
|
236
229
|
expect( Hoodoo::Services::Middleware.logger.level ).to eq( :info )
|
237
230
|
end
|
231
|
+
|
232
|
+
# When logging to Alchemy, the middleware should set an
|
233
|
+
# "X-Error-Logged-Via-Alchemy" HTTP header. An Alchemy router/edge
|
234
|
+
# splitter component can use this to avoid double-logging error data
|
235
|
+
# if it implements a middleware-based approach to error reporting.
|
236
|
+
#
|
237
|
+
context '"X-Error-Logged-Via-Alchemy" HTTP header is set for' do
|
238
|
+
before :each do
|
239
|
+
force_logging_to( 'development' )
|
240
|
+
expect_any_instance_of(FakeAlchemy).to receive(:send_message_to_service).at_least(:once)
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'service errors' do
|
244
|
+
expect_any_instance_of( TestLogImplementation ).to receive( :show ) do | instance, context |
|
245
|
+
context.response.not_found( context.request.ident )
|
246
|
+
end
|
247
|
+
|
248
|
+
spec_helper_silence_stdout do
|
249
|
+
get '/v1/test_log/hello', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
250
|
+
end
|
251
|
+
|
252
|
+
expect( last_response.headers[ 'X-Error-Logged-Via-Alchemy' ] ).to eq( 'yes' )
|
253
|
+
expect( last_response.status ).to eq( 404 )
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'service exceptions' do
|
257
|
+
expect_any_instance_of( TestLogImplementation ).to receive( :show ) do
|
258
|
+
raise "boo!"
|
259
|
+
end
|
260
|
+
|
261
|
+
spec_helper_silence_stdout do
|
262
|
+
get '/v1/test_log/hello', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
263
|
+
end
|
264
|
+
|
265
|
+
expect( last_response.headers[ 'X-Error-Logged-Via-Alchemy' ] ).to eq( 'yes' )
|
266
|
+
expect( last_response.status ).to eq( 500 )
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'invalid' do
|
270
|
+
before :each do
|
271
|
+
@old_test_session = Hoodoo::Services::Middleware.test_session()
|
272
|
+
end
|
273
|
+
|
274
|
+
after :each do
|
275
|
+
Hoodoo::Services::Middleware.set_test_session( @old_test_session )
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'session errors' do
|
279
|
+
Hoodoo::Services::Middleware.set_test_session( nil )
|
280
|
+
|
281
|
+
spec_helper_silence_stdout do
|
282
|
+
get '/v1/test_log/hello', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
283
|
+
end
|
284
|
+
|
285
|
+
expect( last_response.headers[ 'X-Error-Logged-Via-Alchemy' ] ).to eq( 'yes' )
|
286
|
+
expect( last_response.status ).to eq( 401 )
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'permission errors' do
|
290
|
+
session = @old_test_session.dup()
|
291
|
+
session.permissions = Hoodoo::Services::Permissions.new # Default is 'deny all'
|
292
|
+
|
293
|
+
Hoodoo::Services::Middleware.set_test_session( session )
|
294
|
+
|
295
|
+
spec_helper_silence_stdout do
|
296
|
+
get '/v1/test_log/hello', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
297
|
+
end
|
298
|
+
|
299
|
+
expect( last_response.headers[ 'X-Error-Logged-Via-Alchemy' ] ).to eq( 'yes' )
|
300
|
+
expect( last_response.status ).to eq( 403 )
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Middleware exceptions are not tested. There's no way to know the kind
|
305
|
+
# of failure that might happen in the real-world and the point at which
|
306
|
+
# the exception occurs in the processing chain may influence whether or
|
307
|
+
# not the header gets set. We might end up with double logging from an
|
308
|
+
# router/edge splitter in such cases, but that's acceptable for what
|
309
|
+
# should be an extremely rare event.
|
310
|
+
|
311
|
+
end
|
238
312
|
end
|
239
313
|
|
240
|
-
context '
|
314
|
+
context 'with' do
|
315
|
+
|
241
316
|
class HashLogger < Hoodoo::Logger::FastWriter
|
242
317
|
@@log_data = []
|
243
318
|
|
@@ -301,56 +376,109 @@ describe Hoodoo::Services::Middleware do
|
|
301
376
|
end
|
302
377
|
end
|
303
378
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
379
|
+
context 'verbose logging' do
|
380
|
+
context 'which is turned off' do
|
381
|
+
it 'by default' do
|
382
|
+
expect( Hoodoo::Services::Middleware.verbose_logging? ).to eq( false )
|
383
|
+
end
|
308
384
|
|
309
|
-
|
310
|
-
|
385
|
+
it 'and omits non-identity information in the session section' do
|
386
|
+
get '/v1/test_log/hello', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
311
387
|
|
312
|
-
|
313
|
-
|
314
|
-
entry = outbound.first; expect( entry[ :data ][ :payload ] ).to have_key( :response_body )
|
315
|
-
end
|
388
|
+
inbound, result, outbound = get_data_for( :show )
|
389
|
+
data = result.first[ :data ]
|
316
390
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
391
|
+
expect( data[ :session ][ 'session_id' ] ).to be_present
|
392
|
+
expect( data[ :session ][ 'caller_id' ] ).to be_present
|
393
|
+
expect( data[ :session ][ 'caller_version' ] ).to be_present
|
394
|
+
expect( data[ :session ][ 'caller_identity_name' ] ).to be_present
|
395
|
+
expect( data[ :session ][ 'identity' ] ).to be_present
|
321
396
|
|
322
|
-
|
323
|
-
|
397
|
+
expect( data[ :session ][ 'permissions' ] ).to_not be_present
|
398
|
+
expect( data[ :session ][ 'scoping' ] ).to_not be_present
|
399
|
+
end
|
400
|
+
end
|
324
401
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
402
|
+
context 'which is turned on' do
|
403
|
+
before :each do
|
404
|
+
@old_verbose = Hoodoo::Services::Middleware.verbose_logging?
|
405
|
+
Hoodoo::Services::Middleware.set_verbose_logging( true )
|
406
|
+
end
|
329
407
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
408
|
+
after :each do
|
409
|
+
Hoodoo::Services::Middleware.set_verbose_logging( @old_verbose )
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'and includes non-identity information in the session section' do
|
413
|
+
get '/v1/test_log/hello', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
334
414
|
|
335
|
-
|
336
|
-
|
415
|
+
inbound, result, outbound = get_data_for( :show )
|
416
|
+
data = result.first[ :data ]
|
337
417
|
|
338
|
-
|
339
|
-
|
340
|
-
|
418
|
+
expect( data[ :session ][ 'session_id' ] ).to be_present
|
419
|
+
expect( data[ :session ][ 'caller_id' ] ).to be_present
|
420
|
+
expect( data[ :session ][ 'caller_version' ] ).to be_present
|
421
|
+
expect( data[ :session ][ 'caller_identity_name' ] ).to be_present
|
422
|
+
expect( data[ :session ][ 'identity' ] ).to be_present
|
423
|
+
expect( data[ :session ][ 'permissions' ] ).to be_present
|
424
|
+
expect( data[ :session ][ 'scoping' ] ).to be_present
|
425
|
+
end
|
426
|
+
end
|
341
427
|
end
|
342
428
|
|
343
|
-
|
344
|
-
#
|
345
|
-
it 'does not log requests or responses unexpectedly' do
|
346
|
-
patch '/v2/test_log_b/foo', '{ "foo": "bar" }', { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
429
|
+
context 'secure logging' do
|
347
430
|
|
348
|
-
|
349
|
-
|
431
|
+
# To test_log, 'create' says secure for 'request'
|
432
|
+
#
|
433
|
+
it 'does not log creation requests unexpectedly' do
|
434
|
+
post '/v1/test_log', '{ "foo": "bar" }', { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
350
435
|
|
351
|
-
|
352
|
-
|
353
|
-
|
436
|
+
inbound, result, outbound = get_data_for( :create )
|
437
|
+
check_common_entries( 'TestLog', 1, 'create', inbound.last, result.first, outbound.first )
|
438
|
+
|
439
|
+
entry = inbound.last; expect( entry[ :data ][ :payload ] ).to_not have_key( :body )
|
440
|
+
entry = result.first; expect( entry[ :data ] ).to have_key( :payload )
|
441
|
+
entry = outbound.first; expect( entry[ :data ][ :payload ] ).to have_key( :response_body )
|
442
|
+
end
|
443
|
+
|
444
|
+
# To test_log, 'update' says secure for 'request'
|
445
|
+
#
|
446
|
+
it 'does not log update responses unexpectedly' do
|
447
|
+
patch '/v1/test_log/foo', '{ "foo": "bar" }', { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
448
|
+
|
449
|
+
inbound, result, outbound = get_data_for( :update )
|
450
|
+
check_common_entries( 'TestLog', 1, 'update', inbound.last, result.first, outbound.first )
|
451
|
+
|
452
|
+
entry = inbound.last; expect( entry[ :data ][ :payload ] ).to have_key( :body )
|
453
|
+
entry = result.first; expect( entry[ :data ] ).to_not have_key( :payload )
|
454
|
+
entry = outbound.first; expect( entry[ :data ][ :payload ] ).to_not have_key( :response_body )
|
455
|
+
end
|
456
|
+
|
457
|
+
# To test_log_b, 'create' says secure for 'both'.
|
458
|
+
#
|
459
|
+
it 'does not log requests or responses unexpectedly' do
|
460
|
+
post '/v2/test_log_b', '{ "foo": "bar" }', { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
461
|
+
|
462
|
+
inbound, result, outbound = get_data_for( :create )
|
463
|
+
check_common_entries( 'TestLogB', 2, 'create', inbound.last, result.first, outbound.first )
|
464
|
+
|
465
|
+
entry = inbound.last; expect( entry[ :data ][ :payload ] ).to_not have_key( :body )
|
466
|
+
entry = result.first; expect( entry[ :data ] ).to_not have_key( :payload )
|
467
|
+
entry = outbound.first; expect( entry[ :data ][ :payload ] ).to_not have_key( :response_body )
|
468
|
+
end
|
469
|
+
|
470
|
+
# To test_log_b, 'update' does not ask for security.
|
471
|
+
#
|
472
|
+
it 'does not log requests or responses unexpectedly' do
|
473
|
+
patch '/v2/test_log_b/foo', '{ "foo": "bar" }', { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
|
474
|
+
|
475
|
+
inbound, result, outbound = get_data_for( :update )
|
476
|
+
check_common_entries( 'TestLogB', 2, 'update', inbound.last, result.first, outbound.first )
|
477
|
+
|
478
|
+
entry = inbound.last; expect( entry[ :data ][ :payload ] ).to have_key( :body )
|
479
|
+
entry = result.first; expect( entry[ :data ] ).to have_key( :payload )
|
480
|
+
entry = outbound.first; expect( entry[ :data ][ :payload ] ).to have_key( :response_body )
|
481
|
+
end
|
354
482
|
end
|
355
483
|
end
|
356
484
|
end
|
@@ -293,7 +293,13 @@ describe Hoodoo::Services::Session do
|
|
293
293
|
raise 'Mock Memcached connection failure'
|
294
294
|
end
|
295
295
|
|
296
|
-
expect( Hoodoo::Services::Middleware.logger ).to
|
296
|
+
expect( Hoodoo::Services::Middleware.logger ).to(
|
297
|
+
receive( :warn ).once.with(
|
298
|
+
'Hoodoo::Services::Session\\#load_from_memcached!: Session loading failed - connection fault or session corrupt',
|
299
|
+
'Mock Memcached connection failure'
|
300
|
+
).and_call_original
|
301
|
+
)
|
302
|
+
|
297
303
|
expect( loader.load_from_memcached!( '1234' ) ).to eq( :fail )
|
298
304
|
end
|
299
305
|
|
@@ -303,11 +309,20 @@ describe Hoodoo::Services::Session do
|
|
303
309
|
:caller_version => 1
|
304
310
|
)
|
305
311
|
|
312
|
+
# The first 'set' call is an attempt to update the caller version before
|
313
|
+
# the updated session is saved.
|
314
|
+
|
306
315
|
expect_any_instance_of( Hoodoo::Services::Session::MockDalliClient ).to receive( :set ).once do
|
307
316
|
raise 'Mock Memcached connection failure'
|
308
317
|
end
|
309
318
|
|
310
|
-
expect( Hoodoo::Services::Middleware.logger ).to
|
319
|
+
expect( Hoodoo::Services::Middleware.logger ).to(
|
320
|
+
receive( :warn ).once.with(
|
321
|
+
'Hoodoo::Services::Session\\#update_caller_version_in_memcached: Client version update - connection fault or corrupt record',
|
322
|
+
'Mock Memcached connection failure'
|
323
|
+
).and_call_original
|
324
|
+
)
|
325
|
+
|
311
326
|
expect( s.save_to_memcached() ).to eq( :fail )
|
312
327
|
end
|
313
328
|
|
@@ -322,7 +337,13 @@ describe Hoodoo::Services::Session do
|
|
322
337
|
raise 'Mock Memcached connection failure'
|
323
338
|
end
|
324
339
|
|
325
|
-
expect( Hoodoo::Services::Middleware.logger ).to
|
340
|
+
expect( Hoodoo::Services::Middleware.logger ).to(
|
341
|
+
receive( :warn ).once.with(
|
342
|
+
'Hoodoo::Services::Session\\#save_to_memcached: Session saving failed - connection fault or session corrupt',
|
343
|
+
'Mock Memcached connection failure'
|
344
|
+
).and_call_original
|
345
|
+
)
|
346
|
+
|
326
347
|
expect( s.save_to_memcached() ).to eq( :fail )
|
327
348
|
end
|
328
349
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hoodoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Loyalty New Zealand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|