hoodoo 1.5.2 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|