Selaa lähdekoodia

Add ability to log all MAX responses.
Improve error logging on parse errors of MAX response parts.

Andrew Klopper 8 vuotta sitten
vanhempi
commit
242683d58b

+ 2 - 1
BulkPrintingAPI/appsettings.Development.json

@@ -12,6 +12,7 @@
12 12
     "Port": 4006,
13 13
     "ConnectTimeout": 10000,
14 14
     "ReceiveTimeout": 10000,
15
-    "SendTimeout":  10000
15
+    "SendTimeout": 10000,
16
+    "LogResponses":  true
16 17
   }
17 18
 }

+ 1 - 1
BulkPrintingAPI/appsettings.json

@@ -5,7 +5,7 @@
5 5
   "Logging": {
6 6
     "IncludeScopes": false,
7 7
     "LogLevel": {
8
-      "Default": "Warning"
8
+      "Default": "Debug"
9 9
     }
10 10
   },
11 11
   "TokenAuthentication": {

+ 103 - 38
MAXClient/Client.cs

@@ -21,6 +21,7 @@ namespace MAX
21 21
         private int _userId;
22 22
         private string _username;
23 23
         private string _password;
24
+        private bool _logResponses;
24 25
 
25 26
         private TcpClient _connection = null;
26 27
         private NetworkStream _connectionStream = null;
@@ -28,7 +29,7 @@ namespace MAX
28 29
 
29 30
         private bool _disposed = false;
30 31
 
31
-        public Client(ILogger logger, string host, int port, int vendorId, string serialNumber, int userId, string username, string password)
32
+        public Client(ILogger logger, bool logResponses, string host, int port, int vendorId, string serialNumber, int userId, string username, string password)
32 33
         {
33 34
             _logger = logger;
34 35
             _host = host;
@@ -38,14 +39,15 @@ namespace MAX
38 39
             _userId = userId;
39 40
             _username = username;
40 41
             _password = password;
42
+            _logResponses = logResponses;
41 43
 
42 44
             ConnectTimeout = 10000;
43 45
             ReceiveTimeout = 10000;
44 46
             SendTimeout = 10000;
45 47
         }
46 48
 
47
-        public Client(ILogger logger, string host, int port, LoginCredentials credentials)
48
-            : this(logger, host, port, credentials.Vendor.Id, credentials.Vendor.SerialNumber,
49
+        public Client(ILogger logger, bool logResponses, string host, int port, LoginCredentials credentials)
50
+            : this(logger, logResponses, host, port, credentials.Vendor.Id, credentials.Vendor.SerialNumber,
49 51
                   credentials.User.Id, credentials.User.Username, credentials.Password)
50 52
         {
51 53
         }
@@ -120,28 +122,28 @@ namespace MAX
120 122
                 Username = _username,
121 123
                 FirstName = parts[4],
122 124
                 Surname = parts[3],
123
-                Enabled = bool.Parse(parts[6]),
124
-                Level = (User.UserLevel)int.Parse(parts[1]),
125
-                System = int.Parse(parts[2]),
126
-                LastLogin = DateTime.Parse(parts[5])
125
+                Enabled = ParseBool(parts[6], "User.Enabled(6)", response),
126
+                Level = (User.UserLevel)ParseInt(parts[1], "User.Level(1)", response),
127
+                System = ParseInt(parts[2], "User.System(2)", response),
128
+                LastLogin = ParseDateTime(parts[5], "User.LastLogin(5)", response)
127 129
             };
128 130
 
129 131
             if (user.Level == User.UserLevel.CustomUser)
130 132
             {
131
-                user.CanPrintOffline = bool.Parse(parts[7]);
132
-                user.OfflinePrintValue = decimal.Parse(parts[8]);
133
-                user.CanPrintOnline = bool.Parse(parts[9]);
134
-                user.OnlinePrintValue = decimal.Parse(parts[10]);
135
-                user.CanReprintOffline = bool.Parse(parts[11]);
136
-                user.OfflineReprintValue = decimal.Parse(parts[12]);
137
-                user.CanReprintOnline = bool.Parse(parts[13]);
138
-                user.OnlineReprintValue = decimal.Parse(parts[14]);
139
-                user.BulkExport = bool.Parse(parts[15]);
140
-                user.BulkExportMaxValue = decimal.Parse(parts[16]);
141
-                user.BulkOrder = bool.Parse(parts[17]);
142
-                user.BulkOrderMaxValue = decimal.Parse(parts[18]);
143
-                user.BulkViewPins = bool.Parse(parts[19]);
144
-                user.BulkReExport = bool.Parse(parts[20]);
133
+                user.CanPrintOffline = ParseBool(parts[7], "User.CanPrintOffline(7)", response);
134
+                user.OfflinePrintValue = ParseDecimal(parts[8], "User.OfflinePrintValue(8)", response);
135
+                user.CanPrintOnline = ParseBool(parts[9], "User.CanPrintOnline(9)", response);
136
+                user.OnlinePrintValue = ParseDecimal(parts[10], "User.OnlinePrintValue(10)", response);
137
+                user.CanReprintOffline = ParseBool(parts[11], "User.CanReprintOffline(11)", response);
138
+                user.OfflineReprintValue = ParseDecimal(parts[12], "User.OfflineReprintValue(12)", response);
139
+                user.CanReprintOnline = ParseBool(parts[13], "User.CanReprintOnline(13)", response);
140
+                user.OnlineReprintValue = ParseDecimal(parts[14], "User.OnlineReprintValue(14)", response);
141
+                user.BulkExport = ParseBool(parts[15], "User.BulkExport(15)", response);
142
+                user.BulkExportMaxValue = ParseDecimal(parts[16], "User.BulkExportMaxValue(16)", response);
143
+                user.BulkOrder = ParseBool(parts[17], "User.BulkOrder(17)", response);
144
+                user.BulkOrderMaxValue = ParseDecimal(parts[18], "User.BulkOrderMaxValue(18)", response);
145
+                user.BulkViewPins = ParseBool(parts[19], "User.BulkViewPins(19)", response);
146
+                user.BulkReExport = ParseBool(parts[20], "User.BulkReExport(20)", response);
145 147
             }
146 148
 
147 149
             return user;
@@ -184,7 +186,12 @@ namespace MAX
184 186
 
185 187
         private string Decrypt(string cipherText)
186 188
         {
187
-            return Utils.TripleDESDecrypt(cipherText, _des);
189
+            var response = Utils.TripleDESDecrypt(cipherText, _des);
190
+            if (_logResponses)
191
+            {
192
+                _logger.LogDebug("Decrypted response for {0}: {1}", LoginCredentials.Format(_userId, _username, _vendorId, _serialNumber), response);
193
+            }
194
+            return response;
188 195
         }
189 196
 
190 197
         private string Encrypt(string plainText)
@@ -246,14 +253,14 @@ namespace MAX
246 253
             var parts = response.Split('|');
247 254
             return new Account()
248 255
             {
249
-                Id = int.Parse(parts[1]),
256
+                Id = ParseInt(parts[1], "Account.Id(1)", response),
250 257
                 Name = parts[2],
251
-                Balance = decimal.Parse(parts[3]),
252
-                Status = (Account.AccountStatus)int.Parse(parts[4]),
258
+                Balance = ParseDecimal(parts[3], "Account.Balance(3)", response),
259
+                Status = (Account.AccountStatus)ParseInt(parts[4], "Account.AccountStatus(4)", response),
253 260
                 Reference = parts[5],
254 261
                 Warehouse = new Warehouse()
255 262
                 {
256
-                    Id = int.Parse(parts[6]),
263
+                    Id = ParseInt(parts[6], "Account.Warehouse.Id(6)", response),
257 264
                     Name = parts[7]
258 265
                 }
259 266
             };
@@ -268,7 +275,7 @@ namespace MAX
268 275
             var response = ExpectResponse(Decrypt(await ReadMessageAsync().ConfigureAwait(false)), "OK");
269 276
 
270 277
             var parts = response.Split('|');
271
-            var count = int.Parse(parts[1]);
278
+            var count = ParseInt(parts[1], "Products.Count(1)", response);
272 279
 
273 280
             var catalogue = new ProductCatalogue();
274 281
             
@@ -280,7 +287,7 @@ namespace MAX
280 287
                 response = ExpectResponse(Decrypt(await ReadMessageAsync().ConfigureAwait(false)), "OK");
281 288
 
282 289
                 parts = response.Split('|');
283
-                int networkId = int.Parse(parts[4]);
290
+                int networkId = ParseInt(parts[4], "Product.NetworkId(4)", response);
284 291
                 Network network;
285 292
                 if (! catalogue.NetworkMap.TryGetValue(networkId, out network))
286 293
                 {
@@ -289,17 +296,70 @@ namespace MAX
289 296
 
290 297
                 catalogue.AddProduct(
291 298
                     network: network,
292
-                    id: int.Parse(parts[1]),
293
-                    faceValue: decimal.Parse(parts[2]),
299
+                    id: ParseInt(parts[1], "Product.Id(1)", response),
300
+                    faceValue: ParseDecimal(parts[2], "Product.FaceValue(2)", response),
294 301
                     description: parts[3],
295
-                    voucherType: (Batch.Vouchertype)int.Parse(parts[6]),
296
-                    discountPercentage: decimal.Parse(parts[7])
302
+                    voucherType: (Batch.Vouchertype)ParseInt(parts[6], "Product.VoucherType(6)", response),
303
+                    discountPercentage: ParseDecimal(parts[7], "Product.DiscountPercentage(7)", response)
297 304
                 );
298 305
             }
299 306
 
300 307
             return catalogue;
301 308
         }
302 309
 
310
+        private bool LogParseError(string value, string valueName, string valueType, string fullResponse)
311
+        {
312
+            _logger.LogError(
313
+                "Failed to parse value: valueType={0} valueName={1} value={2} fullResponse={3} {4}",
314
+                valueType,
315
+                valueName,
316
+                value,
317
+                fullResponse,
318
+                LoginCredentials.Format(_userId, _username, _vendorId, _serialNumber)
319
+            );
320
+            throw new Exception(String.Format("Invalid value for {0}", valueName));
321
+        }
322
+
323
+        private bool ParseBool(string value, string valueName, string fullResponse)
324
+        {
325
+            bool ret;
326
+            if (! bool.TryParse(value, out ret))
327
+            {
328
+                LogParseError(value, valueName, "bool", fullResponse);
329
+            }
330
+            return ret;
331
+        }
332
+
333
+        private DateTime ParseDateTime(string value, string valueName, string fullResponse)
334
+        {
335
+            DateTime ret;
336
+            if (!DateTime.TryParse(value, out ret))
337
+            {
338
+                LogParseError(value, valueName, "DateTime", fullResponse);
339
+            }
340
+            return ret;
341
+        }
342
+
343
+        private decimal ParseDecimal(string value, string valueName, string fullResponse)
344
+        {
345
+            decimal ret;
346
+            if (!decimal.TryParse(value, out ret))
347
+            {
348
+                LogParseError(value, valueName, "decimal", fullResponse);
349
+            }
350
+            return ret;
351
+        }
352
+
353
+        private int ParseInt(string value, string valueName, string fullResponse)
354
+        {
355
+            int ret;
356
+            if (!int.TryParse(value, out ret))
357
+            {
358
+                LogParseError(value, valueName, "int", fullResponse);
359
+            }
360
+            return ret;
361
+        }
362
+
303 363
         public async Task<OrderResponse> PlaceOrderAsync(int accountId, Product product, int quantity,
304 364
             string customerReference, string internalReference, Guid? orderGuid, byte[] key)
305 365
         {
@@ -333,11 +393,11 @@ namespace MAX
333 393
             {
334 394
                 Batch = new Batch()
335 395
                 {
336
-                    Id = int.Parse(parts[1]),
396
+                    Id = ParseInt(parts[1], "Batch.Id(1)", response),
337 397
                     OrderReference = parts[2],
338
-                    RequestedQuantity = int.Parse(parts[3]),
339
-                    DeliveredQuantity = int.Parse(parts[4]),
340
-                    Cost = decimal.Parse(parts[5]),
398
+                    RequestedQuantity = ParseInt(parts[3], "Batch.RequestQuantity(3)", response),
399
+                    DeliveredQuantity = ParseInt(parts[4], "Batch.DeliveredQuantity(4)", response),
400
+                    Cost = ParseDecimal(parts[5], "Batch.Cost(5)", response),
341 401
                     InternalReference = internalReference,
342 402
                     OrderGuid = orderGuid,
343 403
                     AccountId = accountId,
@@ -353,7 +413,7 @@ namespace MAX
353 413
                     OrderedById = _userId,
354 414
                     ReadyForDownload = false
355 415
                 },
356
-                RemainingBalance = decimal.Parse(parts[6])
416
+                RemainingBalance = ParseDecimal(parts[6], "Batch.RemainingBalance(6)", response)
357 417
             };
358 418
         }
359 419
 
@@ -379,7 +439,12 @@ namespace MAX
379 439
             {
380 440
                 throw new Exception("Invalid message size");
381 441
             }
382
-            return Encoding.ASCII.GetString(await ReadBytesAsync(size).ConfigureAwait(false));
442
+            var response = Encoding.ASCII.GetString(await ReadBytesAsync(size).ConfigureAwait(false));
443
+            if (_logResponses)
444
+            {
445
+                _logger.LogDebug("Response for {0}: {1}", LoginCredentials.Format(_userId, _username, _vendorId, _serialNumber), response);
446
+            }
447
+            return response;
383 448
         }
384 449
 
385 450
         public int ReceiveTimeout { get; set; }

+ 4 - 2
MAXClient/ClientFactory.cs

@@ -13,7 +13,7 @@ namespace MAX
13 13
         public Client GetClient(ILogger logger, int vendorId, string serialNumber, int userId,
14 14
             string username, string password)
15 15
         {
16
-            var client = new Client(logger, Host, Port, vendorId, serialNumber, userId,
16
+            var client = new Client(logger, LogResponses, Host, Port, vendorId, serialNumber, userId,
17 17
                 username, password);
18 18
             client.ConnectTimeout = ConnectTimeout;
19 19
             client.ReceiveTimeout = ReceiveTimeout;
@@ -23,7 +23,7 @@ namespace MAX
23 23
 
24 24
         public Client GetClient(ILogger logger, LoginCredentials credentials)
25 25
         {
26
-            var client = new Client(logger, Host, Port, credentials);
26
+            var client = new Client(logger, LogResponses, Host, Port, credentials);
27 27
             client.ConnectTimeout = ConnectTimeout;
28 28
             client.ReceiveTimeout = ReceiveTimeout;
29 29
             client.SendTimeout = SendTimeout;
@@ -39,5 +39,7 @@ namespace MAX
39 39
         public int ReceiveTimeout { get; set; }
40 40
 
41 41
         public int SendTimeout { get; set; }
42
+
43
+        public bool LogResponses { get; set; }
42 44
     }
43 45
 }