un-cli 0.0.75 → 0.0.78

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.
package/index.html CHANGED
@@ -8,25 +8,25 @@
8
8
  </head>
9
9
  <body>
10
10
 
11
- <table>
11
+ <table border =0>
12
12
  <tr>
13
13
  <td>
14
14
  Admin User
15
15
  </td>
16
- <td colspan =3><input type = 'text' id = 'txtAdmin' value = 'admin'></td>
16
+ <td colspan =5><input type = 'text' id = 'txtAdmin' value = 'admin'></td>
17
17
  </tr>
18
18
  <tr>
19
19
  <td>
20
20
  Admin Password
21
21
  </td>
22
- <td colspan =3><input type = 'password' id = 'txtPassword' value = ''></td>
22
+ <td colspan =5><input type = 'password' id = 'txtPassword' value = ''></td>
23
23
  </tr>
24
24
  <tr>
25
25
 
26
- <td colspan =5><button id = 'btnLogin'>Login</button></td>
26
+ <td colspan =6><button id = 'btnLogin'>Login</button></td>
27
27
  </tr>
28
28
  <tr><td>Service</td>
29
- <td colspan =3 ><select id ='cmbService'>
29
+ <td colspan =5 ><select id ='cmbService'>
30
30
 
31
31
  </select>
32
32
  </td>
@@ -34,21 +34,51 @@
34
34
 
35
35
  <tr>
36
36
  <td >Age</td>
37
- <td colspan =3><input type ='text' id = 'txtAge' value = '10' style="width:30px"> minutes</td>
37
+ <td colspan =5><input type ='text' id = 'txtAge' value = '10' style="width:30px"> minutes</td>
38
38
  </tr>
39
- <tr colspan =4>
40
- <td><button id = 'btnTraceLogs'>Trace Logs</button></td>
41
- <td><button id = 'btnValidateLogs'>Validate Logs</button></td>
42
- <td><button id = 'btnUpdateSubnetworkLogs'>Update Subnetwork Logs</button></td>
43
- <td><button id = 'btnAR'>Attribute Rules Logs</button></td>
44
- <td><button id = 'btnSQLLogs'>SQL Logs</button></td>
45
- <td>Message<input id = 'txtFilter' type = 'text'></td>
46
- <td>User<input id = 'txtUser' type = 'text'></td>
39
+ <tr>
40
+ <td>Message</td>
41
+ <td><input id = 'txtFilter' type = 'text'></td>
42
+ <td>User</td>
43
+ <td colspan =3><input id = 'txtUser' type = 'text'></td>
47
44
  </tr>
45
+ <tr>
48
46
 
47
+ <td title = "Newer date goes here">Start Time</td>
48
+ <td><input id = 'txtStartTime' type = 'text'></td>
49
+ <td title = "Older date goes here">End Time</td>
50
+ <td colspan =3><input id = 'txtEndTime' type = 'text'></td>
51
+ </tr>
52
+ <tr>
53
+
54
+ <td>Method Name</td>
55
+ <td><input id = 'txtMethodName' type = 'text'></td>
56
+ <td>RequestID</td>
57
+ <td colspan =3><input id = 'txtRequestId' type = 'text'></td>
58
+ </tr>
59
+ </table>
60
+
61
+ <table>
62
+ <tr>
63
+ <td colspan = 9>
64
+ <button id = 'btnTraceLogs'>Trace Logs</button>
65
+ <button id = 'btnValidateLogs'>Validate Logs</button>
66
+ <button id = 'btnUpdateSubnetworkLogs'>Update Subnetwork Logs</button>
67
+ <button id = 'btnAR'>Attribute Rules Logs</button>
68
+ <button id = 'btnSQLLogs'>SQL Logs</button>
69
+ <button id = 'btnApplyEditsLogs'>ApplyEdits Logs</button>
70
+ <button id = 'btnQueryLogs'>Query Logs</button>
71
+ <button id = 'btnReconcileLogs'>Reconcile Logs</button>
72
+ <button id = 'btnstopEditingLogs'>StopEditing Logs</button>
73
+ <button id = 'btnWaitLogs'>Wait Logs</button>
74
+ <button id = 'btnDownloadLogs'>Raw Logs</button>
75
+ </td>
76
+
77
+ </tr>
78
+ <tr><td colspan=9><small>Elapsed time is in minutes:seconds:milliseconds</small></td></tr>
49
79
  </table>
50
80
 
51
- <table id = 'tblResult' border =1 cellpadding = 4 cellspacing = 4 style="text-align:center">
81
+ <table id = 'tblResult' border =1 cellpadding = 4 cellspacing = 4 style="text-align:left">
52
82
 
53
83
  </table>
54
84
  <script type = 'module'>
@@ -58,15 +88,19 @@
58
88
  import logger from "./logger.mjs"
59
89
 
60
90
 
61
-
91
+
62
92
  let parameters = {
63
- "user": "unadmin",
93
+ "user": "",
64
94
  "password": "",
65
- "portal": "https://utilitynetwork.esri.com/portal",
95
+ "portal": "", //https://utilitynetwork.esri.com/portal set your portal url webadaptor if not /portal
66
96
  "service": "",
67
- "referer": "https://utilitynetwork.esri.com/log"
97
+ "referer": "", //set the referer to be the same url you are running this from https://utilitynetwork.esri.com/log,
98
+ "server": undefined //when there are multiple federate server, update the correct one here.
99
+
68
100
  }
69
-
101
+
102
+ if (parameters.portal === "") parameters.portal = window.location.origin + "/portal"
103
+ if (parameters.referer === "") parameters.referer = window.location.href
70
104
 
71
105
  let portal;
72
106
  let adminLog = null;
@@ -77,6 +111,14 @@
77
111
  const txtPassword = document.getElementById("txtPassword")
78
112
 
79
113
  btnLogin.addEventListener("click", () => init())
114
+
115
+ function msToMinSecMs(millis) {
116
+ const minutes = Math.floor(millis / 60000);
117
+ const seconds = Math.floor(((millis % 60000) / 1000))
118
+ const miliseconds =Math.floor( ((millis % 60000) % 1000) )
119
+ return minutes + ":" + (seconds < 10 ? '0' : '') + seconds + "." + (miliseconds < 10 ? '00' : '') + (miliseconds >= 10 && miliseconds <=99 ? '0' : '') + miliseconds
120
+ }
121
+
80
122
  async function init() {
81
123
  try {
82
124
 
@@ -91,10 +133,23 @@
91
133
  token = await getToken(parameters);
92
134
 
93
135
  //if we logged in successfully
94
- const opt = document.createElement("option")
136
+ let opt = document.createElement("option")
95
137
  opt.textContent = "(All Services)"
96
138
  cmbService.appendChild (opt)
97
139
 
140
+ opt = document.createElement("option")
141
+ opt.textContent = "System/ValidationTools.GPServer"
142
+ cmbService.appendChild (opt)
143
+
144
+ opt = document.createElement("option")
145
+ opt.textContent = "System/UtilityNetworkTools.GPServer"
146
+ cmbService.appendChild (opt)
147
+
148
+ opt = document.createElement("option")
149
+ opt.textContent = "System/VersionManagementTools.GPServer"
150
+ cmbService.appendChild (opt)
151
+
152
+
98
153
  const services = await portal.services()
99
154
  const featureServices = services.services.filter(s => s.type == "FeatureServer")
100
155
  featureServices.forEach(s=> {
@@ -110,17 +165,23 @@
110
165
  document.getElementById("btnUpdateSubnetworkLogs").disabled = false
111
166
  document.getElementById("btnAR").disabled = false
112
167
  document.getElementById("btnSQLLogs").disabled = false
113
-
168
+ document.getElementById("btnApplyEditsLogs").disabled = false
169
+ document.getElementById("btnQueryLogs").disabled = false
170
+ document.getElementById("btnDownloadLogs").disabled = false
171
+ document.getElementById("btnReconcileLogs").disabled = false
172
+ document.getElementById("btnstopEditingLogs").disabled = false
173
+ document.getElementById("btnWaitLogs").disabled = false
174
+
114
175
 
115
176
  }
116
177
  catch(ex){
117
- alert(`Failed to login to ${parameters.portal} check the user/password and make sure its an admin`)
178
+ alert(`Failed to login to ${parameters.portal} check the user/password and make sure its an admin: \n\nMore details: ${JSON.stringify(ex)}`)
118
179
  }
119
180
  }
120
181
 
121
182
 
122
183
  async function getToken(parameters) {
123
- portal = new Portal(parameters.portal, parameters.user, parameters.password,300, parameters.server, parameters.referer)
184
+ portal = new Portal(parameters.portal, parameters.user, parameters.password,30000, parameters.server, parameters.referer)
124
185
  console.log("About to connect..")
125
186
  const token = await portal.connect()
126
187
  console.log(`Token generanted successfully.`)
@@ -129,7 +190,7 @@
129
190
 
130
191
 
131
192
  async function loadTraceLogs () {
132
-
193
+
133
194
  //build table
134
195
  const tblResult = document.getElementById("tblResult");
135
196
  //clear
@@ -143,9 +204,136 @@
143
204
  console.log(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
144
205
 
145
206
  //page query the admin log
146
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102002], "------ Trace Parameters ----", "VERBOSE")
207
+ let allTheMessages = await adminLogQueryWithPaging(mins, parameters.service, [102002], "------ Trace Parameters ----", "VERBOSE")
208
+
209
+ let allMessages = filterMessages (allTheMessages).map(m => {
210
+ const newMessage = Object.assign({}, m);
211
+ delete newMessage.machine;
212
+ delete newMessage.type;
213
+ delete newMessage.code;
214
+ //delete newMessage.requestID;
215
+ delete newMessage.process;
216
+ delete newMessage.thread;
217
+ newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
218
+ newMessage.time = new Date(newMessage.time).toLocaleString()
219
+ delete newMessage.elapsed
220
+
221
+ try{
222
+
223
+ //Total Trace Time (4.745 seconds)
224
+
225
+ let re = /Total Trace Time \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
226
+ let res = re.exec(m.message)
227
+ if (res && res.length > 1)
228
+ newMessage.traceTime = parseFloat(res[1])*1000
229
+
230
+ let re1 = /Trace Type: .\w.*/;
231
+ let res1 = re1.exec(m.message)
232
+ if (res1 && res1.length > 0)
233
+ newMessage.traceType = res1[0].replace("Trace Type: ","")
234
+
235
+
236
+ let x ;
237
+ x = /Version name:.*,/.exec(m.message);
238
+ if (x && x.length > 0) newMessage.versionName = x[0].replace("Version name:", "").replace(",", "")
239
+
240
+ x = /Moment:.*\r\n/.exec(m.message);
241
+ if (x && x.length > 0) newMessage.moment = x[0].replace("Moment:", "").replace("\r\n", "") * 1000000
242
+
243
+
244
+ }
245
+ catch(ex){
246
+ console.error(ex)
247
+ }
147
248
 
148
- await populateMessages(allMessages)
249
+
250
+ return newMessage;
251
+ })
252
+ .sort( (m1,m2) => m2.elapsedms - m1.elapsedms)
253
+
254
+ //clear
255
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
256
+
257
+ const header = document.createElement("tr");
258
+ const cService = document.createElement("th");
259
+ cService.textContent = "Source"
260
+ const cTime = document.createElement("th");
261
+ cTime.textContent = "Time"
262
+ const cUser = document.createElement("th");
263
+ cUser.textContent = "User"
264
+ const cMethod = document.createElement("th");
265
+ cMethod.textContent = "Method"
266
+ const cVersion = document.createElement("th");
267
+ cVersion.textContent = "Version"
268
+ const cMoment = document.createElement("th");
269
+ cMoment.textContent = "Moment"
270
+ const cElapsedMS = document.createElement("th");
271
+ cElapsedMS.textContent = "Elapsed"
272
+ const cTraceType = document.createElement("th");
273
+ cTraceType.textContent = "Trace Type"
274
+ const cTraceTime = document.createElement("th");
275
+ cTraceTime.textContent = "Trace Time"
276
+ const cRequestId = document.createElement("th");
277
+ cRequestId.textContent = "RequestId"
278
+ const cLog = document.createElement("th");
279
+ cLog.textContent = "Full Log"
280
+ header.appendChild (cService)
281
+ header.appendChild (cTime)
282
+ header.appendChild (cUser)
283
+ header.appendChild (cMethod)
284
+ header.appendChild (cVersion)
285
+ header.appendChild (cMoment)
286
+ header.appendChild (cTraceType)
287
+ header.appendChild (cTraceTime)
288
+ header.appendChild (cRequestId)
289
+ header.appendChild (cElapsedMS)
290
+
291
+ header.appendChild (cLog)
292
+ tblResult.appendChild(header)
293
+ allMessages.forEach(m => {
294
+ const logRow = document.createElement("tr");
295
+ const cService = document.createElement("td");
296
+ cService.textContent = m.source.replace(".MapServer", "")
297
+ const cTime = document.createElement("td");
298
+ cTime.textContent = m.time
299
+ const cUser = document.createElement("td");
300
+ cUser.textContent = m.user
301
+ const cMethod = document.createElement("td");
302
+ cMethod.textContent = m.methodName
303
+ const cElapsedMS = document.createElement("td");
304
+ cElapsedMS.textContent = msToMinSecMs(m.elapsedms)
305
+ const cTraceType = document.createElement("td");
306
+ cTraceType.textContent = m.traceType
307
+ const cTraceTime = document.createElement("td");
308
+ cTraceTime.textContent = msToMinSecMs(m.traceTime)
309
+ const cRequestId = document.createElement("td");
310
+ cRequestId.textContent = m.requestID
311
+ const cVersion = document.createElement("td");
312
+ cVersion.textContent = m.versionName
313
+ const cMoment = document.createElement("td");
314
+ cMoment.textContent = m.moment
315
+ const cLog = document.createElement("td");
316
+ cLog.textContent = "..."
317
+ cLog.fullLog = m.message;
318
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
319
+ logRow.appendChild (cService)
320
+ logRow.appendChild (cTime)
321
+ logRow.appendChild (cUser)
322
+ logRow.appendChild (cMethod)
323
+ logRow.appendChild (cVersion)
324
+ logRow.appendChild (cMoment)
325
+ logRow.appendChild (cTraceType)
326
+ logRow.appendChild (cTraceTime)
327
+ logRow.appendChild (cRequestId)
328
+ logRow.appendChild (cElapsedMS)
329
+
330
+ logRow.appendChild (cLog)
331
+ tblResult.appendChild(logRow)
332
+ })
333
+
334
+
335
+ addCSV(allMessages)
336
+ //await populateMessages(allMessages)
149
337
 
150
338
 
151
339
  }
@@ -155,241 +343,1413 @@
155
343
  async function loadValidateLogs () {
156
344
  //build table
157
345
  const tblResult = document.getElementById("tblResult");
158
- //clear
159
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
160
-
346
+
161
347
  parameters.service = cmbService.options[cmbService.selectedIndex].text
162
348
 
163
349
 
164
350
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
165
351
 
166
352
  console.log(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
167
-
168
- //-1 && m.message.indexOf("The network is built.") > -1 && m.methodName == 'BuildEngineLog')
169
- //page query the admin log
170
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "The network is built.", "VERBOSE")
353
+
354
+
355
+ let allMessages = [];
356
+ //clear
357
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
358
+
359
+
360
+ //-1 && m.message.indexOf("The network is built.") > -1 && m.methodName == 'BuildEngineLog')
361
+ //page query the admin log
362
+ // prior to 11.1 let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "The network is built.", "VERBOSE")
363
+ let allMessagesNew = await adminLogQueryWithPaging(mins, parameters.service, [102003,100002], "", "DEBUG")
364
+
365
+ allMessagesNew = allMessagesNew.filter(m => m.message.indexOf( "String request successfully processed.") >= 0 || m.message.indexOf( "End ValidateNetworkTopology") >= 0 || m.message.indexOf( "Network built.") >= 0 )
171
366
 
172
-
173
- //validate logs missing elapsed populate it
174
- allMessages = allMessages.map( m => {
175
- try{
367
+ //Network built:
368
+ //validate logs missing elapsed populate it
369
+ allMessagesNew = allMessagesNew.map( m => {
370
+ try{
371
+
372
+ //The network is built. 0.093 seconds (4.982 total) - 29 MB memory
373
+ //Network built: 0.056 seconds (0.359 total) - 0 MB memory
374
+ //let re = /The network is built. [-+]?([0-9]*\.[0-9]+|[0-9]+) seconds \([-+]?([0-9]*\.[0-9]+|[0-9]+) total\)/;
176
375
 
177
- //The network is built. 0.093 seconds (4.982 total) - 29 MB memory
178
-
179
- let re = /The network is built. [-+]?([0-9]*\.[0-9]+|[0-9]+) seconds \([-+]?([0-9]*\.[0-9]+|[0-9]+) total\)/;
180
- let res = re.exec(m.message)
181
- if (res && res.length > 1)
182
- m.elapsed = res[2]
376
+
377
+ //get extent
378
+
379
+ let x ;
380
+ x = /Extent:.*\r\n/.exec(m.message);
381
+ if (x && x.length > 0) m.extent = x[0].replace("Extent:", "").replace("\r\n", "")
382
+ x = /Version name:.*\r\n/.exec(m.message);
383
+ if (x && x.length > 0) m.versionName = x[0].replace("Version name:", "").replace("\r\n", "")
384
+
385
+ let re = new RegExp(`Network built. [-+]?([0-9]*\\.[0-9]+|[0-9]+) seconds \\([-+]?([0-9]*\\.[0-9]+|[0-9]+) total\\)`)
386
+ let res = re.exec(m.message)
387
+
388
+ if (!res)
389
+ {
390
+ //try with th other string
391
+ re = new RegExp(`Network built: [-+]?([0-9]*\\.[0-9]+|[0-9]+) seconds \\([-+]?([0-9]*\\.[0-9]+|[0-9]+) total\\)`)
392
+ res = re.exec(m.message)
393
+ }
394
+ if (res && res.length > 1)
395
+ m.validateTime = res[2]
396
+
397
+ return m;
398
+ }
399
+
400
+
401
+ catch(ex){
402
+ return m;
403
+ }
404
+
405
+
406
+ })
407
+
408
+ //build out the dictionary, key is request id, value is another dictionary
409
+ const queryLogs = {}
410
+ //sort by time
411
+ allMessages = allMessagesNew.sort ( (m1, m2) => m2.time - m1.time )
412
+ allMessages.forEach (m => {
413
+
414
+ if (!queryLogs[m.requestID])
415
+ queryLogs[m.requestID] = {"message": "Time,Method,Elapsed_ms,Message"}
416
+
417
+ queryLogs[m.requestID].message += "\r\n" + m.time + "," + m.methodName + "," + Math.round(m.elapsed*1000) + "," + m.message
418
+
419
+ //get elapsed
420
+ //check for async (method GPReconcileVersionAsync::Execute)
421
+ //sync
422
+ //VersionManagementServer::HandleREST_ReconcileOperation
423
+ //message Returned moment:
424
+ if (m.message.indexOf("End ValidateNetworkTopology")> -1 || m.message.indexOf("String request successfully processed.") > -1 )
425
+ /*
426
+ ( m.methodName.indexOf("UtilityNetworkServer::HandleREST_ValidateNetworkTopologyOperation") > -1 ||
427
+ m.methodName.indexOf("GPServer.ExecuteJob.ValidateNetworkTopology") > -1
428
+ )
429
+ */
430
+
431
+ {
432
+ queryLogs[m.requestID].elapsed = m.elapsed
433
+ queryLogs[m.requestID].source = m.source.replace(".MapServer", "")
434
+ queryLogs[m.requestID].user = m.user
435
+ queryLogs[m.requestID].time = m.time
436
+ queryLogs[m.requestID].requestID = m.requestID
437
+ queryLogs[m.requestID].methodName = m.methodName
438
+
439
+
440
+ }
441
+
442
+
443
+ if(m.validateTime) {
444
+ queryLogs[m.requestID].validateTime = m.validateTime
445
+ queryLogs[m.requestID].versionName = m.versionName
446
+ queryLogs[m.requestID].extent = m.extent
447
+ }
448
+
449
+
450
+
451
+
452
+ })
453
+
454
+ allMessages = []
455
+
456
+ Object.keys(queryLogs).forEach(k =>
457
+ {
458
+ const m = queryLogs[k]
459
+ if (m.validateTime && m.elapsed)
460
+ allMessages.push(m)
461
+
462
+ })
463
+
464
+
465
+ // allMessages.push(...allMessagesNew);
466
+
467
+
468
+
469
+
470
+ //sort messages
471
+
472
+ allMessages = filterMessages (allMessages).map(m => {
473
+ const newMessage = Object.assign({}, m);
474
+ delete newMessage.machine;
475
+ delete newMessage.type;
476
+ delete newMessage.code;
477
+ //delete newMessage.requestID;
478
+ delete newMessage.process;
479
+ delete newMessage.thread;
480
+ newMessage.validateTime = parseInt (parseFloat(newMessage.validateTime) * 1000)
481
+ newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
482
+ newMessage.time = new Date(newMessage.time).toLocaleString()
483
+ delete newMessage.elapsed
484
+ return newMessage;
485
+ })
486
+ .sort( (m1,m2) => m2.elapsedms - m1.elapsedms)
487
+
488
+ //clear
489
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
490
+
491
+ const header = document.createElement("tr");
492
+ const cService = document.createElement("th");
493
+ cService.textContent = "Source"
494
+ const cTime = document.createElement("th");
495
+ cTime.textContent = "Time"
496
+ const cUser = document.createElement("th");
497
+ cUser.textContent = "User"
498
+ const cMethod = document.createElement("th");
499
+ cMethod.textContent = "Method"
500
+ const cExtent = document.createElement("th");
501
+ cExtent.textContent = "Extent"
502
+ const cVersion = document.createElement("th");
503
+ cVersion.textContent = "Version"
504
+
505
+ const cValidateTime = document.createElement("th");
506
+ cValidateTime.textContent = "Validate Time "
507
+
508
+ const cElapsedMS = document.createElement("th");
509
+ cElapsedMS.textContent = "Elapsed "
510
+
511
+ const cRequestId = document.createElement("th");
512
+ cRequestId.textContent = "RequestId"
513
+ const cLog = document.createElement("th");
514
+ cLog.textContent = "Full Log"
515
+
516
+ header.appendChild (cService)
517
+ header.appendChild (cTime)
518
+ header.appendChild (cUser)
519
+ header.appendChild (cMethod)
520
+ header.appendChild (cExtent)
521
+ header.appendChild (cVersion)
522
+ header.appendChild (cValidateTime)
523
+ header.appendChild (cElapsedMS)
524
+ header.appendChild (cRequestId)
525
+ header.appendChild (cLog)
526
+ tblResult.appendChild(header)
527
+ allMessages.forEach(m => {
528
+ const logRow = document.createElement("tr");
529
+ const cService = document.createElement("td");
530
+ cService.textContent = m.source.replace(".MapServer", "")
531
+ const cTime = document.createElement("td");
532
+ cTime.textContent = m.time
533
+ const cUser = document.createElement("td");
534
+ cUser.textContent = m.user
535
+ const cMethod = document.createElement("td");
536
+ cMethod.textContent = m.methodName
537
+ const cExtent = document.createElement("td");
538
+ cExtent.textContent = m.extent
539
+ const cVersion = document.createElement("td");
540
+ cVersion.textContent = m.versionName
541
+
542
+ const cValidateTime = document.createElement("td");
543
+ cValidateTime.textContent = msToMinSecMs(m.validateTime)
183
544
 
184
- return m;
545
+ const cElapsedMS = document.createElement("td");
546
+ cElapsedMS.textContent = msToMinSecMs(m.elapsedms)
547
+
548
+ const cRequestId = document.createElement("td");
549
+ cRequestId.textContent = m.requestID;
550
+ const cLog = document.createElement("td");
551
+ cLog.textContent = "..."
552
+ cLog.fullLog = m.message;
553
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
554
+ logRow.appendChild (cService)
555
+ logRow.appendChild (cTime)
556
+ logRow.appendChild (cUser)
557
+ logRow.appendChild (cMethod)
558
+ logRow.appendChild (cExtent)
559
+ logRow.appendChild (cVersion)
560
+ logRow.appendChild (cValidateTime)
561
+ logRow.appendChild (cElapsedMS)
562
+ logRow.appendChild (cRequestId)
563
+ logRow.appendChild (cLog)
564
+ tblResult.appendChild(logRow)
565
+ })
566
+
567
+ //await populateMessages(allMessages)
568
+ addCSV(allMessages)
569
+
570
+ }
571
+
572
+
573
+ async function loadUpdateSubnetworkLogs () {
574
+ //build table
575
+ const tblResult = document.getElementById("tblResult");
576
+ //clear
577
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
578
+
579
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
580
+
581
+
582
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
583
+
584
+
585
+ console.log(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
586
+ let allTheMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "---- Subnetwork Parameters ----", "VERBOSE")
587
+
588
+
589
+
590
+ let allMessages = filterMessages (allTheMessages).map(m => {
591
+
592
+ const newMessage = Object.assign({}, m);
593
+ try{
594
+
595
+ delete newMessage.machine;
596
+ delete newMessage.type;
597
+ delete newMessage.code;
598
+ //delete newMessage.requestID;
599
+ delete newMessage.process;
600
+ delete newMessage.thread;
601
+
602
+
603
+ let re = /Total \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
604
+ let res = re.exec(m.message)
605
+ if (res && res.length > 0)
606
+ newMessage.elapsed = res[1]
607
+
608
+ re = /Total update subnetwork time \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
609
+ res = re.exec(m.message)
610
+ if (res && res.length > 0)
611
+ newMessage.elapsed = res[1]
612
+
613
+
614
+ let re1 = /Subnetwork name: .*/;
615
+ let res1 = re1.exec(m.message)
616
+ if (res1 && res1.length > 0)
617
+ newMessage.subnetworkName = res1[0].replace("Subnetwork name: ","")
618
+
619
+
620
+ newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
621
+ newMessage.time = new Date(newMessage.time).toLocaleString()
622
+ delete newMessage.elapsed
623
+
624
+
185
625
  }
186
626
  catch(ex){
187
- return m;
627
+ console.error(ex)
188
628
  }
629
+ finally {
630
+ return newMessage;
631
+ }
632
+
189
633
  })
634
+ .sort( (m1,m2) => m2.elapsedms - m1.elapsedms)
635
+
636
+ //clear
637
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
638
+
639
+ const header = document.createElement("tr");
640
+ const cService = document.createElement("th");
641
+ cService.textContent = "Source"
642
+ const cTime = document.createElement("th");
643
+ cTime.textContent = "Time"
644
+ const cUser = document.createElement("th");
645
+ cUser.textContent = "User"
646
+ const cMethod = document.createElement("th");
647
+ cMethod.textContent = "Method"
648
+ const cElapsedMS = document.createElement("th");
649
+ cElapsedMS.textContent = "Elapsed "
650
+ const cSubnetworkName = document.createElement("th");
651
+ cSubnetworkName.textContent = "Subnetwork Name"
652
+ const cRequestId = document.createElement("th");
653
+ cRequestId.textContent = "RequestId"
654
+ const cLog = document.createElement("th");
655
+ cLog.textContent = "Full Log"
656
+ header.appendChild (cService)
657
+ header.appendChild (cTime)
658
+ header.appendChild (cUser)
659
+ header.appendChild (cMethod)
660
+ header.appendChild (cSubnetworkName)
661
+ header.appendChild (cElapsedMS)
662
+ header.appendChild (cRequestId)
663
+ header.appendChild (cLog)
664
+ tblResult.appendChild(header)
665
+ allMessages.forEach(m => {
666
+ const logRow = document.createElement("tr");
667
+ const cService = document.createElement("td");
668
+ cService.textContent = m.source.replace(".MapServer", "")
669
+ const cTime = document.createElement("td");
670
+ cTime.textContent = m.time
671
+ const cUser = document.createElement("td");
672
+ cUser.textContent = m.user
673
+ const cMethod = document.createElement("td");
674
+ cMethod.textContent = m.methodName
675
+ const cElapsedMS = document.createElement("td");
676
+ cElapsedMS.textContent =msToMinSecMs(m.elapsedms)
677
+ const cSubnetworkName = document.createElement("td");
678
+ cSubnetworkName.textContent = m.subnetworkName
679
+ const cRequestId = document.createElement("td");
680
+ cRequestId.textContent = m.requestID
681
+ const cLog = document.createElement("td");
682
+ cLog.textContent = "..."
683
+ cLog.fullLog = m.message;
684
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
685
+ logRow.appendChild (cService)
686
+ logRow.appendChild (cTime)
687
+ logRow.appendChild (cUser)
688
+ logRow.appendChild (cMethod)
689
+ logRow.appendChild (cSubnetworkName)
690
+ logRow.appendChild (cElapsedMS)
691
+ logRow.appendChild (cRequestId)
692
+ logRow.appendChild (cLog)
693
+ tblResult.appendChild(logRow)
694
+ })
695
+
696
+ addCSV(allMessages)
697
+
698
+
699
+ }
700
+
701
+
702
+
703
+ async function loadAttributeRules () {
704
+
705
+ //build table
706
+ const tblResult = document.getElementById("tblResult");
707
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
708
+
709
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
710
+
711
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
712
+
713
+ let showMaxGuid = true
714
+ let showMinGuid = false
715
+
716
+ logger.info(`Querying attribute rules logs for ${parameters.service} in the past ${mins} minutes...`)
717
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule executed:", "DEBUG")
718
+
719
+
720
+ const arMessages = filterMessages(allMessages)
721
+ .filter(m => m.message.indexOf("Attribute rule executed: ") > -1)
722
+ .map (m => JSON.parse(m.message.replace("Attribute rule executed: ", "")))
723
+ .map( m => {
724
+ m["Elapsed Time (ms)"] = Math.round(m["Elapsed Time"]*1000000)/1000
725
+ // m["Arcade Evaluation Time:"] = Math.round(m["Arcade Evaluation Time:"]*1000,6)
726
+ //m.ArcadeTime = m["Arcade Evaluation Time:"]
727
+
728
+ delete m["Arcade Evaluation Time:"];
729
+ delete m["Elapsed Time"];
730
+ //delete m ['GlobalID'];
731
+ return m
732
+ })
733
+ .sort( (m1, m2) => m2["Elapsed Time (ms)"]- m1["Elapsed Time (ms)"])
734
+ .reduce( ( prev, cur ) => {
735
+ if (prev [cur["Rule name"]] === undefined)
736
+ {
737
+ prev [cur["Rule name"]] = {
738
+ "totalTime": 0,
739
+ "occurrence": 0,
740
+ "minTime": Number.MAX_SAFE_INTEGER,
741
+ "maxTime": -1,
742
+ "avgTime": 0,
743
+ "maxGuid": null,
744
+ "minGuid": null
745
+ };
746
+ }
747
+
748
+ prev [cur["Rule name"]].totalTime = prev [cur["Rule name"]].totalTime + cur["Elapsed Time (ms)"]
749
+
750
+ if (cur["Elapsed Time (ms)"] < prev [cur["Rule name"]].minTime ) {
751
+ prev [cur["Rule name"]].minTime = cur["Elapsed Time (ms)"];
752
+ prev [cur["Rule name"]].minGuid = cur["GlobalID"];
753
+ }
754
+
755
+ if (cur["Elapsed Time (ms)"] > prev [cur["Rule name"]].maxTime ){
756
+ prev [cur["Rule name"]].maxTime = cur["Elapsed Time (ms)"];
757
+ prev [cur["Rule name"]].maxGuid = cur["GlobalID"];
758
+ }
759
+
760
+ prev [cur["Rule name"]].occurrence++
761
+
762
+ prev [cur["Rule name"]].avgTime = prev [cur["Rule name"]].totalTime / prev [cur["Rule name"]].occurrence
763
+
764
+ return prev
765
+ }, {})
766
+
767
+ const rules = Object.keys(arMessages)
768
+ .map(a => {
769
+ const rule = {}
770
+ rule["Attribute Rule"] = a;
771
+ rule["Total Cost (ms)"] = parseFloat(arMessages[a].totalTime.toFixed(2))
772
+ rule["Occurrence"] = parseFloat(arMessages[a].occurrence)
773
+ if (!showMinGuid && !showMaxGuid) rule["Average Cost (ms)"] = parseFloat(arMessages[a].avgTime.toFixed(2))
774
+ rule["Max execution time (ms)"] = parseFloat(arMessages[a].maxTime.toFixed(2))
775
+ if (showMaxGuid) rule["Max GUID"] = arMessages[a].maxGuid
776
+ rule["Min execution time (ms)"] = parseFloat(arMessages[a].minTime.toFixed(2))
777
+ if (showMinGuid) rule["Min GUID"] = arMessages[a].minGuid
778
+ if (!showMinGuid && !showMaxGuid) rule["Occurrence"] = arMessages[a].occurrence;
779
+ return rule;
780
+ })
781
+ .sort( (m1, m2) => m2["Total Cost (ms)"] -m1["Total Cost (ms)"])
782
+ console.table(rules)
783
+
784
+ /*
785
+ Attribute Rule
786
+ │ Total Cost (ms)
787
+ │ Max execution time (ms)
788
+ │ Max GUID
789
+ │ Min execution time (m
790
+
791
+ */
792
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
793
+
794
+ const header = document.createElement("tr");
795
+ const cAttributeRule = document.createElement("th");
796
+ cAttributeRule.textContent = "Attribute Rule"
797
+
798
+ const cTotalCost = document.createElement("th");
799
+ cTotalCost.textContent = "Total Cost (ms)"
800
+
801
+ const cOccurrence = document.createElement("th");
802
+ cOccurrence.textContent = "Occurrence"
803
+
804
+ const cMaxExecutionTime = document.createElement("th");
805
+ cMaxExecutionTime.textContent = "Max execution time (ms)"
806
+
807
+ const cMaxGuid = document.createElement("th");
808
+ cMaxGuid.textContent = "Max GUID"
809
+
810
+ const cMinExecutionTime = document.createElement("th");
811
+ cMinExecutionTime.textContent = "Min execution time (ms)"
812
+
813
+
814
+ header.appendChild (cAttributeRule)
815
+ header.appendChild (cTotalCost)
816
+ header.appendChild (cOccurrence)
817
+ header.appendChild (cMaxExecutionTime)
818
+ header.appendChild (cMaxGuid)
819
+ header.appendChild (cMinExecutionTime)
820
+
821
+ tblResult.appendChild(header)
822
+
823
+
824
+ rules.forEach(rule =>
825
+ {
826
+
827
+ const logRow = document.createElement("tr");
828
+ const cAttributeRule = document.createElement("td");
829
+ cAttributeRule.textContent = rule["Attribute Rule"]
830
+
831
+ const cOccurrence = document.createElement("td");
832
+ cOccurrence.textContent = rule["Occurrence"]
833
+
834
+ const cTotalCost = document.createElement("td");
835
+ cTotalCost.textContent = msToMinSecMs(rule["Total Cost (ms)"])
836
+
837
+ const cMaxExecutionTime = document.createElement("td");
838
+ cMaxExecutionTime.textContent = msToMinSecMs(rule["Max execution time (ms)"])
839
+
840
+ const cMaxGuid = document.createElement("td");
841
+ cMaxGuid.textContent = rule["Max GUID"]
842
+
843
+ const cMinExecutionTime = document.createElement("td");
844
+ cMinExecutionTime.textContent = msToMinSecMs(rule["Min execution time (ms)"])
845
+
846
+ logRow.appendChild (cAttributeRule)
847
+ logRow.appendChild (cTotalCost)
848
+ logRow.appendChild (cOccurrence)
849
+ logRow.appendChild (cMaxExecutionTime)
850
+ logRow.appendChild (cMaxGuid)
851
+ logRow.appendChild (cMinExecutionTime)
852
+ tblResult.appendChild(logRow)
853
+
854
+
855
+ })
856
+
857
+
858
+ const totalARExecution = rules.reduce( (prev, cur) => prev + cur["Total Cost (ms)"], 0)
859
+ console.log(`Total time spend executing attribute rules (${Math.round(totalARExecution)} ms) (${Math.round(totalARExecution/1000)} s) (${Math.round(totalARExecution/(1000*60))} m)`)
860
+ addCSV(rules)
861
+
862
+
863
+ }
864
+
865
+
866
+ async function downloadLogs () {
867
+
868
+ //build table
869
+ const tblResult = document.getElementById("tblResult");
870
+ //clear
871
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
872
+
873
+
874
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
875
+
876
+
877
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
878
+
879
+
880
+ console.log(`Querying all debug logs for ${parameters.service} for the last ${mins} minutes ...`)
881
+
882
+ //startTime is the most recent
883
+ //endTime is the oldest
884
+
885
+
886
+ //page query the admin log
887
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [], "", "DEBUG")
888
+
889
+ //filter make time pretty
890
+ allMessages = filterMessages (allMessages)
891
+ .sort( (m1,m2) => m2.time - m1.time)
892
+ .map(m => {
893
+ const newMessage = Object.assign({}, m);
894
+ newMessage.time = new Date(newMessage.time).toLocaleString()
895
+ if (newMessage.source != "Server" && newMessage.code != 8000)
896
+ newMessage.elapsed = Math.round(newMessage.elapsed * 1000) ;
897
+ return newMessage;
898
+ })
899
+
900
+
901
+ await populateMessagesAsIs(allMessages)
902
+ addCSV(allMessages)
903
+
904
+ }
905
+
906
+ function addCSV (allMessages) {
907
+
908
+ allMessages = filterMessages (allMessages).map(m => {
909
+ const newMessage = Object.assign({}, m);
910
+ newMessage.message = newMessage?.message?.replace(",","-")
911
+ newMessage.message = newMessage?.message?.replace("\"","-")
912
+ return newMessage;
913
+ })
914
+
915
+ const csv= jsonToCSV(allMessages)
916
+ const blob = new Blob([csv], {"type": "text/csv"});
917
+ const url = window.URL.createObjectURL(blob);
918
+
919
+ const a = document.createElement('a');
920
+ a.download = "log.csv";
921
+ a.href = url;
922
+ a.textContent = "Download log.csv";
923
+ tblResult.appendChild(a);
924
+
925
+ }
926
+
927
+ function jsonToCSV(jsonObj) {
928
+
929
+ var fields = Object.keys(jsonObj[0])
930
+ var replacer = function(key, value) { return value === null ? '' : value }
931
+ var csv = jsonObj.map(function(row){
932
+ return fields.map(function(fieldName){
933
+ return JSON.stringify(row[fieldName], replacer)
934
+ }).join(',')
935
+ })
936
+ csv.unshift(fields.join(',')) // add header column
937
+ csv = csv.join('\r\n');
938
+ return csv;
939
+ }
940
+
941
+
942
+ async function loadApplyEditsLogs () {
943
+
944
+ //build table
945
+ const tblResult = document.getElementById("tblResult");
946
+ //clear
947
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
948
+
949
+
950
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
951
+
952
+
953
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
954
+
955
+
956
+ console.log(`Querying applyEdits logs for ${parameters.service} for the last ${mins} minutes ...`)
957
+
958
+ //startTime is the most recent
959
+ //endTime is the oldest
960
+
961
+
962
+ //page query the admin log , search for /applyEdits logs by methodname
963
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [17002,100004], "", "FINE", "/applyEdits")
964
+
965
+
966
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
967
+
968
+ let i =0;
969
+
970
+ const header = document.createElement("tr");
971
+ const cService = document.createElement("th");
972
+ cService.textContent = "Source"
973
+ const cTime = document.createElement("th");
974
+ cTime.textContent = "Time"
975
+ const cUser = document.createElement("th");
976
+ cUser.textContent = "User"
977
+ const cVersion = document.createElement("th");
978
+ cVersion.textContent = "Version"
979
+ const cIds = document.createElement("th");
980
+ cIds.textContent = "LayerIds"
981
+ const cTotalTime = document.createElement("th");
982
+ cTotalTime.title = "Total time applyEdits took"
983
+ cTotalTime.textContent = "Total Time"
984
+ const cRequestId = document.createElement("th");
985
+ cRequestId.textContent = "RequestId"
986
+ const cLog = document.createElement("th");
987
+ cLog.textContent = "applyEdits payload"
988
+ header.appendChild (cService)
989
+ header.appendChild (cTime)
990
+ header.appendChild (cUser)
991
+ header.appendChild (cVersion)
992
+ header.appendChild (cIds)
993
+ header.appendChild (cTotalTime)
994
+ header.appendChild (cRequestId)
995
+ header.appendChild (cLog)
996
+ tblResult.appendChild(header)
997
+
998
+ //build out the dictionary, key is request id, value is another dictionary
999
+ const applyEditslogs = {}
1000
+
1001
+ allMessages.forEach (m => {
1002
+
1003
+ if (!applyEditslogs[m.requestID])
1004
+ applyEditslogs[m.requestID] = {}
1005
+ //get elapsed
1006
+ if (m.message.indexOf("REST request successfully processed. Response size is ") > -1)
1007
+ {
1008
+ applyEditslogs[m.requestID].elapsed = m.elapsed
1009
+ applyEditslogs[m.requestID].source = m.source.replace(".MapServer", "")
1010
+ applyEditslogs[m.requestID].user = m.user
1011
+ applyEditslogs[m.requestID].time = m.time
1012
+ applyEditslogs[m.requestID].requestID = m.requestID
1013
+
1014
+ }
1015
+
1016
+ if (m.message.indexOf("GraphicFeatureServer::HandleRESTRequest ## inputJSON ") > -1)
1017
+ {
1018
+ applyEditslogs[m.requestID].message = m.message.replace("GraphicFeatureServer::HandleRESTRequest ## inputJSON = ","")
1019
+ const applyEditsPayload = JSON.parse(applyEditslogs[m.requestID].message)
1020
+ applyEditslogs[m.requestID].gdbVersion = applyEditsPayload.gdbVersion
1021
+ applyEditslogs[m.requestID].ids = [...new Set(applyEditsPayload.edits.reduce ( (prev, cur) => {prev.push(cur.id); return prev}, []) )];
1022
+ }
1023
+
1024
+
1025
+
1026
+ })
1027
+
1028
+ allMessages = []
1029
+
1030
+ Object.keys(applyEditslogs).forEach(k =>
1031
+ {
1032
+ const m = applyEditslogs[k]
1033
+ allMessages.push(m)
1034
+
1035
+ })
1036
+
1037
+
1038
+
1039
+ console.log ("Filtering messages...")
1040
+
1041
+ allMessages = filterMessages(allMessages)
1042
+ .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
1043
+
1044
+ allMessages.forEach (m => {
1045
+ const logRow = document.createElement("tr");
1046
+
1047
+ const cService = document.createElement("th");
1048
+ cService.textContent = m.source
1049
+
1050
+ const cTime = document.createElement("td");
1051
+ cTime.textContent = new Date(m.time).toLocaleString()
1052
+
1053
+ const cUser = document.createElement("td");
1054
+ cUser.textContent = m.user
1055
+
1056
+ const cVersion = document.createElement("td");
1057
+ cVersion.textContent = m.gdbVersion
1058
+
1059
+
1060
+ const cIds = document.createElement("td");
1061
+ cIds.textContent = m.ids
1062
+
1063
+ const cTotalTime = document.createElement("td");
1064
+ cTotalTime.textContent = msToMinSecMs(m.elapsed*1000 )
1065
+
1066
+ const cRequestId = document.createElement("td");
1067
+ cRequestId.textContent = m.requestID
1068
+
1069
+ const cLog = document.createElement("td");
1070
+ const cLogText = document.createElement("input")
1071
+ cLogText.type = "text"
1072
+ cLogText.style = "width:400px"
1073
+ cLogText.value = m.message
1074
+ cLogText.readOnly= true;
1075
+ cLog.appendChild(cLogText)
1076
+ //cLog.fullLog = m.payLoad;
1077
+ //cLog.title = m.payLoad + "\nClick to copy"
1078
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
1079
+ // alert("Copied to clipboard") })
1080
+ logRow.appendChild (cService)
1081
+ logRow.appendChild (cTime)
1082
+ logRow.appendChild (cUser)
1083
+ logRow.appendChild (cVersion)
1084
+ logRow.appendChild (cIds)
1085
+ logRow.appendChild (cTotalTime)
1086
+ logRow.appendChild (cRequestId)
1087
+ logRow.appendChild (cLog)
1088
+ tblResult.appendChild(logRow)
1089
+ });
1090
+
1091
+ addCSV(allMessages)
1092
+
1093
+ }
1094
+
1095
+
1096
+
1097
+
1098
+ async function stopEditingLogs () {
1099
+
1100
+ //build table
1101
+ const tblResult = document.getElementById("tblResult");
1102
+ //clear
1103
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1104
+
1105
+
1106
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
1107
+
1108
+
1109
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1110
+
1111
+
1112
+ console.log(`Querying stop editing logs for ${parameters.service} for the last ${mins} minutes ...`)
1113
+
1114
+ //startTime is the most recent
1115
+ //endTime is the oldest
1116
+
1117
+
1118
+ //page query the admin log , search for /stopediting logs by methodname
1119
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003,17003], "", "DEBUG")
1120
+
1121
+
1122
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1123
+
1124
+ let i =0;
1125
+
1126
+ const header = document.createElement("tr");
1127
+ const cService = document.createElement("th");
1128
+ cService.textContent = "Source"
1129
+ const cTime = document.createElement("th");
1130
+ cTime.textContent = "Time"
1131
+ const cUser = document.createElement("th");
1132
+ cUser.textContent = "User"
1133
+ const cVersion = document.createElement("th");
1134
+ cVersion.textContent = "Version"
1135
+ const cMethodName = document.createElement("th");
1136
+ cMethodName.textContent = "MethodName"
1137
+ const cRequestId = document.createElement("th");
1138
+ cRequestId.textContent = "RequestId"
1139
+ const cTotalTime = document.createElement("th");
1140
+ cTotalTime.title = "Total time stopEditing took"
1141
+ cTotalTime.textContent = "Total Time"
1142
+
1143
+
1144
+ const cLog = document.createElement("th");
1145
+ cLog.textContent = "StopEditing details"
1146
+ header.appendChild (cService)
1147
+ header.appendChild (cTime)
1148
+ header.appendChild (cUser)
1149
+ header.appendChild (cVersion)
1150
+ header.appendChild (cMethodName)
1151
+ header.appendChild (cRequestId)
1152
+ header.appendChild (cTotalTime)
1153
+
1154
+ header.appendChild (cLog)
1155
+ tblResult.appendChild(header)
1156
+
1157
+ //build out the dictionary, key is request id, value is another dictionary
1158
+ const queryLogs = {}
1159
+ //sort by time
1160
+ allMessages = allMessages.sort ( (m1, m2) => m2.time - m1.time )
1161
+ allMessages.forEach (m => {
1162
+
1163
+ if (!queryLogs[m.requestID])
1164
+ queryLogs[m.requestID] = {"message": "Time,Method,Elapsed_ms,Message"}
1165
+
1166
+ queryLogs[m.requestID].message += "\r\n" + m.time + "," + m.methodName + "," + Math.round(m.elapsed*1000) + "," + m.message
1167
+
1168
+ //get elapsed
1169
+ //check for async (method GPReconcileVersionAsync::Execute)
1170
+ //sync
1171
+ //VersionManagementServer::HandleREST_ReconcileOperation
1172
+ //message Returned moment:
1173
+ if ( m.methodName.indexOf("VersionManagementServer::HandleREST_StopEditingOperation") > -1
1174
+ && m.message.indexOf("End StopEditing") > -1
1175
+ )
1176
+ {
1177
+ queryLogs[m.requestID].elapsed = m.elapsed
1178
+ queryLogs[m.requestID].source = m.source.replace(".MapServer", "")
1179
+ queryLogs[m.requestID].user = m.user
1180
+ queryLogs[m.requestID].time = m.time
1181
+ queryLogs[m.requestID].requestID = m.requestID
1182
+ queryLogs[m.requestID].methodName = m.methodName.replace("VersionManagementServer::HandleREST_","")
1183
+
1184
+ }
1185
+
1186
+ if (m.message.indexOf("In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=") > -1)
1187
+ {
1188
+ let v = m.message.replace(": In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=","")
1189
+ v = v.substr(v.indexOf("{"))
1190
+ queryLogs[m.requestID].gdbVersion =v
1191
+
1192
+ }
1193
+
1194
+
1195
+
1196
+ })
1197
+
1198
+ allMessages = []
1199
+
1200
+ Object.keys(queryLogs).forEach(k =>
1201
+ {
1202
+ const m = queryLogs[k]
1203
+ if (m.methodName)
1204
+ allMessages.push(m)
1205
+
1206
+ })
1207
+
1208
+
1209
+
1210
+ console.log ("Filtering messages...")
1211
+
1212
+ allMessages = filterMessages(allMessages)
1213
+ .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
1214
+
1215
+ allMessages.forEach (m => {
1216
+ const logRow = document.createElement("tr");
1217
+
1218
+ const cService = document.createElement("th");
1219
+ cService.textContent = m.source
1220
+
1221
+ const cTime = document.createElement("td");
1222
+ cTime.textContent = new Date(m.time).toLocaleString()
1223
+
1224
+ const cUser = document.createElement("td");
1225
+ cUser.textContent = m.user
1226
+
1227
+ const cVersion = document.createElement("td");
1228
+ cVersion.textContent = m.gdbVersion
1229
+
1230
+ const cMethodName = document.createElement("td");
1231
+ cMethodName.textContent = m.methodName
1232
+
1233
+ const cRequestId = document.createElement("td");
1234
+ cRequestId.textContent = m.requestID
1235
+
1236
+ const cTotalTime = document.createElement("td");
1237
+ cTotalTime.textContent = msToMinSecMs(m.elapsed*1000 )
1238
+ const cLog = document.createElement("td");
1239
+ cLog.textContent = "..."
1240
+ cLog.title = "Click to copy full stopediting log"
1241
+ cLog.fullLog = m.message;
1242
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
1243
+
1244
+ //cLog.fullLog = m.payLoad;
1245
+ //cLog.title = m.payLoad + "\nClick to copy"
1246
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
1247
+ // alert("Copied to clipboard") })
1248
+ logRow.appendChild (cService)
1249
+ logRow.appendChild (cTime)
1250
+ logRow.appendChild (cUser)
1251
+ logRow.appendChild (cVersion)
1252
+ logRow.appendChild (cMethodName)
1253
+ logRow.appendChild (cRequestId)
1254
+ logRow.appendChild (cTotalTime)
1255
+
1256
+ logRow.appendChild (cLog)
1257
+ tblResult.appendChild(logRow)
1258
+ });
1259
+
1260
+ addCSV(allMessages)
1261
+
1262
+
1263
+
1264
+ }
1265
+
1266
+
1267
+
1268
+
1269
+
1270
+
1271
+
1272
+ async function waitLogs () {
1273
+
1274
+ //build table
1275
+ const tblResult = document.getElementById("tblResult");
1276
+ //clear
1277
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1278
+
1279
+
1280
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
1281
+
1282
+
1283
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1284
+
1285
+
1286
+ console.log(`Querying wait logs for ${parameters.service} for the last ${mins} minutes ...`)
1287
+
1288
+ //startTime is the most recent
1289
+ //endTime is the oldest
1290
+
1291
+
1292
+ //page query the admin log , search for /stopediting logs by methodname //parameters.service
1293
+ let allMessages = await adminLogQueryWithPaging(mins, "Server", [7615,8000], "", "INFO")
1294
+
1295
+ if (parameters.service != "(All Services)")
1296
+ allMessages = allMessages.filter(m => m.message.indexOf(parameters.service) > 0)
1297
+
1298
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1299
+
1300
+ let i =0;
1301
+
1302
+ const header = document.createElement("tr");
1303
+ const cService = document.createElement("th");
1304
+ cService.textContent = "Source"
1305
+ const cTime = document.createElement("th");
1306
+ cTime.textContent = "Time"
1307
+ const cMachine = document.createElement("th");
1308
+ cMachine.textContent = "Machine"
1309
+ const cMessage = document.createElement("th");
1310
+ cMessage.textContent = "Message"
1311
+ const cRequestId = document.createElement("th");
1312
+ cRequestId.textContent = "RequestId"
1313
+ const cTotalTime = document.createElement("th");
1314
+ cTotalTime.title = "Total wait time"
1315
+ cTotalTime.textContent = "Total Time"
1316
+
1317
+
1318
+ const cLog = document.createElement("th");
1319
+ cLog.textContent = "Wait time details"
1320
+ header.appendChild (cService)
1321
+ header.appendChild (cTime)
1322
+ header.appendChild (cMachine)
1323
+ header.appendChild (cMessage)
1324
+ header.appendChild (cRequestId)
1325
+ header.appendChild (cTotalTime)
1326
+
1327
+ header.appendChild (cLog)
1328
+ tblResult.appendChild(header)
1329
+
1330
+ console.log ("Filtering messages...")
1331
+
1332
+ allMessages = filterMessages(allMessages)
1333
+ .sort( (m1,m2) => Math.round(m2.elapsed) -Math.round(m1.elapsed))
1334
+
1335
+ allMessages.forEach (m => {
1336
+ const logRow = document.createElement("tr");
1337
+
1338
+ const cService = document.createElement("th");
1339
+ cService.textContent = m.source
1340
+
1341
+ const cTime = document.createElement("td");
1342
+ cTime.textContent = new Date(m.time).toLocaleString()
1343
+
1344
+ const cMachine = document.createElement("td");
1345
+ cMachine.textContent = m.machine
1346
+
1347
+ const cMessage = document.createElement("td");
1348
+ cMessage.textContent = m.message
1349
+
1350
+ const cRequestId = document.createElement("td");
1351
+ cRequestId.textContent = m.requestID
1352
+
1353
+ const cTotalTime = document.createElement("td");
1354
+ cTotalTime.textContent = msToMinSecMs(m.elapsed )
1355
+ const cLog = document.createElement("td");
1356
+ cLog.textContent = "..."
1357
+ cLog.title = "Click to copy full wait log"
1358
+ cLog.fullLog = m.message;
1359
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
1360
+
1361
+ //cLog.fullLog = m.payLoad;
1362
+ //cLog.title = m.payLoad + "\nClick to copy"
1363
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
1364
+ // alert("Copied to clipboard") })
1365
+ logRow.appendChild (cService)
1366
+ logRow.appendChild (cTime)
1367
+ logRow.appendChild (cMachine)
1368
+ logRow.appendChild (cMessage)
1369
+ logRow.appendChild (cRequestId)
1370
+ logRow.appendChild (cTotalTime)
1371
+
1372
+ logRow.appendChild (cLog)
1373
+ tblResult.appendChild(logRow)
1374
+ });
1375
+
1376
+ addCSV(allMessages)
1377
+
1378
+
1379
+
1380
+ }
1381
+
1382
+
1383
+
1384
+
1385
+ async function reconcileLogs () {
1386
+
1387
+ //build table
1388
+ const tblResult = document.getElementById("tblResult");
1389
+ //clear
1390
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1391
+
1392
+
1393
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
1394
+
1395
+
1396
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1397
+
1398
+
1399
+ console.log(`Querying reconcile logs for ${parameters.service} for the last ${mins} minutes ...`)
1400
+
1401
+ //startTime is the most recent
1402
+ //endTime is the oldest
1403
+
1404
+
1405
+ //page query the admin log , search for /applyEdits logs by methodname
1406
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003,102024,102023], "", "DEBUG")
1407
+
1408
+
1409
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1410
+
1411
+ let i =0;
1412
+
1413
+ const header = document.createElement("tr");
1414
+ const cService = document.createElement("th");
1415
+ cService.textContent = "Source"
1416
+ const cTime = document.createElement("th");
1417
+ cTime.textContent = "Time"
1418
+ const cUser = document.createElement("th");
1419
+ cUser.textContent = "User"
1420
+ const cVersion = document.createElement("th");
1421
+ cVersion.textContent = "Version"
1422
+ const cMethodName = document.createElement("th");
1423
+ cMethodName.textContent = "MethodName"
1424
+ const cRequestId = document.createElement("th");
1425
+ cRequestId.textContent = "RequestId"
1426
+ const cTotalTime = document.createElement("th");
1427
+ cTotalTime.title = "Total time reconcile took"
1428
+ cTotalTime.textContent = "Total Time"
1429
+
1430
+
1431
+ const cLog = document.createElement("th");
1432
+ cLog.textContent = "Reconcile details"
1433
+ header.appendChild (cService)
1434
+ header.appendChild (cTime)
1435
+ header.appendChild (cUser)
1436
+ header.appendChild (cVersion)
1437
+ header.appendChild (cMethodName)
1438
+ header.appendChild (cRequestId)
1439
+ header.appendChild (cTotalTime)
1440
+
1441
+ header.appendChild (cLog)
1442
+ tblResult.appendChild(header)
1443
+
1444
+ //build out the dictionary, key is request id, value is another dictionary
1445
+ const queryLogs = {}
1446
+ //sort by time
1447
+ allMessages = allMessages.sort ( (m1, m2) => m2.time - m1.time )
1448
+ allMessages.forEach (m => {
1449
+
1450
+ if (!queryLogs[m.requestID])
1451
+ queryLogs[m.requestID] = {"message": "Time,Method,Elapsed_ms,Message"}
1452
+
1453
+ queryLogs[m.requestID].message += "\r\n" + m.time + "," + m.methodName + "," + Math.round(m.elapsed*1000) + "," + m.message
1454
+
1455
+ //get elapsed
1456
+ //check for async (method GPReconcileVersionAsync::Execute)
1457
+ //sync
1458
+ //VersionManagementServer::HandleREST_ReconcileOperation
1459
+ //message Returned moment:
1460
+ if (m.message.indexOf("Returned moment: ")> -1 &&
1461
+ ( m.methodName.indexOf("VersionManagementServer::HandleREST_ReconcileOperation") > -1 ||
1462
+ m.methodName.indexOf("GPReconcileVersionAsync::Execute") > -1
1463
+ )
1464
+ )
1465
+ {
1466
+ queryLogs[m.requestID].elapsed = m.elapsed
1467
+ queryLogs[m.requestID].source = m.source.replace(".MapServer", "")
1468
+ queryLogs[m.requestID].user = m.user
1469
+ queryLogs[m.requestID].time = m.time
1470
+ queryLogs[m.requestID].requestID = m.requestID
1471
+ queryLogs[m.requestID].methodName = m.methodName
1472
+
1473
+ }
1474
+
1475
+ if (m.message.indexOf("EndReconcile;") > -1)
1476
+ {
1477
+ queryLogs[m.requestID].gdbVersion = m.message.replace("EndReconcile;","")
1478
+
1479
+
1480
+ }
1481
+
1482
+
1483
+
1484
+ })
1485
+
1486
+ allMessages = []
1487
+
1488
+ Object.keys(queryLogs).forEach(k =>
1489
+ {
1490
+ const m = queryLogs[k]
1491
+ if (m.methodName)
1492
+ allMessages.push(m)
1493
+
1494
+ })
1495
+
1496
+
1497
+
1498
+ console.log ("Filtering messages...")
1499
+
1500
+ allMessages = filterMessages(allMessages)
1501
+ .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
1502
+
1503
+ allMessages.forEach (m => {
1504
+ const logRow = document.createElement("tr");
1505
+
1506
+ const cService = document.createElement("th");
1507
+ cService.textContent = m.source
1508
+
1509
+ const cTime = document.createElement("td");
1510
+ cTime.textContent = new Date(m.time).toLocaleString()
1511
+
1512
+ const cUser = document.createElement("td");
1513
+ cUser.textContent = m.user
1514
+
1515
+ const cVersion = document.createElement("td");
1516
+ cVersion.textContent = m.gdbVersion
1517
+
1518
+ const cMethodName = document.createElement("td");
1519
+ cMethodName.textContent = m.methodName
1520
+
1521
+ const cRequestId = document.createElement("td");
1522
+ cRequestId.textContent = m.requestID
1523
+
1524
+ const cTotalTime = document.createElement("td");
1525
+ cTotalTime.textContent = msToMinSecMs(m.elapsed*1000 )
1526
+ const cLog = document.createElement("td");
1527
+ cLog.textContent = "..."
1528
+ cLog.title = "Click to copy full reconcile log"
1529
+ cLog.fullLog = m.message;
1530
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
1531
+
1532
+ //cLog.fullLog = m.payLoad;
1533
+ //cLog.title = m.payLoad + "\nClick to copy"
1534
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
1535
+ // alert("Copied to clipboard") })
1536
+ logRow.appendChild (cService)
1537
+ logRow.appendChild (cTime)
1538
+ logRow.appendChild (cUser)
1539
+ logRow.appendChild (cVersion)
1540
+ logRow.appendChild (cMethodName)
1541
+ logRow.appendChild (cRequestId)
1542
+ logRow.appendChild (cTotalTime)
1543
+
1544
+ logRow.appendChild (cLog)
1545
+ tblResult.appendChild(logRow)
1546
+ });
1547
+
1548
+ addCSV(allMessages)
190
1549
 
191
1550
 
192
- await populateMessages(allMessages)
193
1551
 
194
-
195
1552
  }
196
1553
 
197
1554
 
198
- async function loadUpdateSubnetworkLogs () {
199
- //build table
200
- const tblResult = document.getElementById("tblResult");
201
- //clear
202
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
203
-
204
- parameters.service = cmbService.options[cmbService.selectedIndex].text
205
-
206
-
207
- let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1555
+ async function loadQueryLogs () {
208
1556
 
209
-
210
- console.log(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
211
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "---- Subnetwork Parameters ----", "VERBOSE")
1557
+ //build table
1558
+ const tblResult = document.getElementById("tblResult");
1559
+ //clear
1560
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1561
+
212
1562
 
213
-
214
- //update subnetwork missing elapsed populate it
215
- allMessages = allMessages.map( m => {
216
- try{
217
-
218
- let re = /Total \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
219
- let res = re.exec(m.message)
220
- if (res && res.length > 1)
221
- m.elapsed = res[1]
1563
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
222
1564
 
223
- re = /Total update subnetwork time \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
224
- res = re.exec(m.message)
225
- if (res && res.length > 1)
226
- m.elapsed = res[1]
227
-
228
- return m;
229
- }
230
- catch(ex){
231
- return m;
232
- }
233
- })
234
- await populateMessages(allMessages)
235
1565
 
236
-
237
- }
1566
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
238
1567
 
239
1568
 
1569
+ console.log(`Querying query logs for ${parameters.service} for the last ${mins} minutes ...`)
240
1570
 
241
- async function loadAttributeRules () {
242
-
243
- //build table
244
- const tblResult = document.getElementById("tblResult");
245
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
246
-
247
- let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1571
+ //startTime is the most recent
1572
+ //endTime is the oldest
248
1573
 
249
- parameters.service = cmbService.options[cmbService.selectedIndex].text
250
1574
 
251
- let showMaxGuid = true
252
- let showMinGuid = false
253
-
254
- logger.info(`Querying attribute rules logs for ${parameters.service} in the past ${mins} minutes...`)
255
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule execution complete:", "DEBUG")
256
-
257
-
258
- const arMessages = filterMessages(allMessages)
259
- .filter(m => m.message.indexOf("Attribute rule execution complete:") > -1)
260
- .map (m => JSON.parse(m.message.replace("Attribute rule execution complete:", "")))
261
- .map( m => {
262
- m["Elapsed Time (ms)"] = Math.round(m["Elapsed Time"]*1000000)/1000
263
- // m["Arcade Evaluation Time:"] = Math.round(m["Arcade Evaluation Time:"]*1000,6)
264
- //m.ArcadeTime = m["Arcade Evaluation Time:"]
265
-
266
- delete m["Arcade Evaluation Time:"];
267
- delete m["Elapsed Time"];
268
- //delete m ['GlobalID'];
269
- return m
270
- })
271
- .sort( (m1, m2) => m2["Elapsed Time (ms)"]- m1["Elapsed Time (ms)"])
272
- .reduce( ( prev, cur ) => {
273
- if (prev [cur["Rule name"]] === undefined)
274
- {
275
- prev [cur["Rule name"]] = {
276
- "totalTime": 0,
277
- "occurrence": 0,
278
- "minTime": Number.MAX_SAFE_INTEGER,
279
- "maxTime": -1,
280
- "avgTime": 0,
281
- "maxGuid": null,
282
- "minGuid": null
283
- };
284
- }
285
-
286
- prev [cur["Rule name"]].totalTime = prev [cur["Rule name"]].totalTime + cur["Elapsed Time (ms)"]
287
-
288
- if (cur["Elapsed Time (ms)"] < prev [cur["Rule name"]].minTime ) {
289
- prev [cur["Rule name"]].minTime = cur["Elapsed Time (ms)"];
290
- prev [cur["Rule name"]].minGuid = cur["GlobalID"];
291
- }
1575
+ //page query the admin log , search for /applyEdits logs by methodname
1576
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [17002,100004], "", "FINE", "layers/")
292
1577
 
293
- if (cur["Elapsed Time (ms)"] > prev [cur["Rule name"]].maxTime ){
294
- prev [cur["Rule name"]].maxTime = cur["Elapsed Time (ms)"];
295
- prev [cur["Rule name"]].maxGuid = cur["GlobalID"];
296
- }
297
-
298
- prev [cur["Rule name"]].occurrence++
299
-
300
- prev [cur["Rule name"]].avgTime = prev [cur["Rule name"]].totalTime / prev [cur["Rule name"]].occurrence
301
1578
 
302
- return prev
303
- }, {})
1579
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
304
1580
 
305
- const rules = Object.keys(arMessages)
306
- .map(a => {
307
- const rule = {}
308
- rule["Attribute Rule"] = a;
309
- rule["Total Cost (ms)"] = parseFloat(arMessages[a].totalTime.toFixed(2))
310
- if (!showMinGuid && !showMaxGuid) rule["Average Cost (ms)"] = parseFloat(arMessages[a].avgTime.toFixed(2))
311
- rule["Max execution time (ms)"] = parseFloat(arMessages[a].maxTime.toFixed(2))
312
- if (showMaxGuid) rule["Max GUID"] = arMessages[a].maxGuid
313
- rule["Min execution time (ms)"] = parseFloat(arMessages[a].minTime.toFixed(2))
314
- if (showMinGuid) rule["Min GUID"] = arMessages[a].minGuid
315
- if (!showMinGuid && !showMaxGuid) rule["Occurrence"] = arMessages[a].occurrence;
316
- return rule;
317
- })
318
- .sort( (m1, m2) => m2["Total Cost (ms)"] -m1["Total Cost (ms)"])
319
- console.table(rules)
1581
+ let i =0;
1582
+
1583
+ const header = document.createElement("tr");
1584
+ const cService = document.createElement("th");
1585
+ cService.textContent = "Source"
1586
+ const cTime = document.createElement("th");
1587
+ cTime.textContent = "Time"
1588
+ const cUser = document.createElement("th");
1589
+ cUser.textContent = "User"
1590
+ const cVersion = document.createElement("th");
1591
+ cVersion.textContent = "Version"
1592
+ const cMoment = document.createElement("th");
1593
+ cMoment.textContent = "Moment"
1594
+ const cMethodName = document.createElement("th");
1595
+ cMethodName.textContent = "MethodName"
1596
+ const cTotalTime = document.createElement("th");
1597
+ cTotalTime.title = "Total time query took"
1598
+ cTotalTime.textContent = "Total Time"
1599
+
1600
+ const cWhere = document.createElement("th");
1601
+ cWhere.textContent = "Where clause"
1602
+ const cGeometry = document.createElement("th");
1603
+ cGeometry.textContent = "Geometry/Extent"
1604
+
1605
+ const cRequestId = document.createElement("th");
1606
+ cRequestId.textContent = "RequestId"
1607
+
1608
+ const cLog = document.createElement("th");
1609
+ cLog.textContent = "query payload"
1610
+ header.appendChild (cService)
1611
+ header.appendChild (cTime)
1612
+ header.appendChild (cUser)
1613
+ header.appendChild (cVersion)
1614
+ header.appendChild (cMoment)
1615
+ header.appendChild (cMethodName)
1616
+ header.appendChild (cTotalTime)
1617
+
1618
+ header.appendChild (cWhere)
1619
+ header.appendChild (cGeometry)
1620
+ header.appendChild (cRequestId)
1621
+ header.appendChild (cLog)
1622
+ tblResult.appendChild(header)
1623
+
1624
+ //build out the dictionary, key is request id, value is another dictionary
1625
+ const queryLogs = {}
1626
+
1627
+ allMessages.forEach (m => {
1628
+
1629
+ if (!queryLogs[m.requestID])
1630
+ queryLogs[m.requestID] = {}
1631
+ //get elapsed
1632
+ if (m.message.indexOf("REST request successfully processed. Response size is ") > -1)
1633
+ {
1634
+ queryLogs[m.requestID].elapsed = m.elapsed
1635
+ queryLogs[m.requestID].source = m.source.replace(".MapServer", "")
1636
+ queryLogs[m.requestID].user = m.user
1637
+ queryLogs[m.requestID].time = m.time
1638
+ queryLogs[m.requestID].requestID = m.requestID
320
1639
 
321
- /*
322
- Attribute Rule
323
- Total Cost (ms)
324
- │ Max execution time (ms)
325
- Max GUID
326
- Min execution time (m
1640
+ }
1641
+
1642
+ if (m.message.indexOf("GraphicFeatureServer::HandleRESTRequest ## inputJSON = ") > -1)
1643
+ {
1644
+ queryLogs[m.requestID].message = m.message.replace("GraphicFeatureServer::HandleRESTRequest ## inputJSON = ","")
1645
+ const queryPayload = JSON.parse(queryLogs[m.requestID].message)
1646
+ queryLogs[m.requestID].gdbVersion = queryPayload.gdbVersion
1647
+ queryLogs[m.requestID].moment = queryPayload.historicMoment
1648
+ queryLogs[m.requestID].methodName = m.methodName;
1649
+ queryLogs[m.requestID].where = queryPayload.where
1650
+ queryLogs[m.requestID].geometry = JSON.stringify(queryPayload.geometry)
1651
+
1652
+ }
327
1653
 
328
- */
329
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1654
+
1655
+
1656
+ })
330
1657
 
331
- const header = document.createElement("tr");
332
- const cAttributeRule = document.createElement("th");
333
- cAttributeRule.textContent = "Attribute Rule"
334
-
335
- const cTotalCost = document.createElement("th");
336
- cTotalCost.textContent = "Total Cost (ms)"
337
-
338
- const cMaxExecutionTime = document.createElement("th");
339
- cMaxExecutionTime.textContent = "Max execution time (ms)"
1658
+ allMessages = []
340
1659
 
341
- const cMaxGuid = document.createElement("th");
342
- cMaxGuid.textContent = "Max GUID"
1660
+ Object.keys(queryLogs).forEach(k =>
1661
+ {
1662
+ const m = queryLogs[k]
1663
+ allMessages.push(m)
1664
+
1665
+ })
343
1666
 
344
- const cMinExecutionTime = document.createElement("th");
345
- cMinExecutionTime.textContent = "Min execution time (ms)"
346
1667
 
347
-
348
- header.appendChild (cAttributeRule)
349
- header.appendChild (cTotalCost)
350
- header.appendChild (cMaxExecutionTime)
351
- header.appendChild (cMaxGuid)
352
- header.appendChild (cMinExecutionTime)
353
1668
 
354
- tblResult.appendChild(header)
1669
+ console.log ("Filtering messages...")
1670
+
1671
+ allMessages = filterMessages(allMessages)
1672
+ .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
355
1673
 
1674
+ allMessages.forEach (m => {
1675
+ const logRow = document.createElement("tr");
1676
+
1677
+ const cService = document.createElement("th");
1678
+ cService.textContent = m.source
356
1679
 
357
- rules.forEach(rule =>
358
- {
359
-
360
- const logRow = document.createElement("tr");
361
- const cAttributeRule = document.createElement("td");
362
- cAttributeRule.textContent = rule["Attribute Rule"]
363
-
364
- const cTotalCost = document.createElement("td");
365
- cTotalCost.textContent = rule["Total Cost (ms)"]
366
-
367
- const cMaxExecutionTime = document.createElement("td");
368
- cMaxExecutionTime.textContent = rule["Max execution time (ms)"]
1680
+ const cTime = document.createElement("td");
1681
+ cTime.textContent = new Date(m.time).toLocaleString()
369
1682
 
370
- const cMaxGuid = document.createElement("td");
371
- cMaxGuid.textContent = rule["Max GUID"]
1683
+ const cUser = document.createElement("td");
1684
+ cUser.textContent = m.user
372
1685
 
373
- const cMinExecutionTime = document.createElement("td");
374
- cMinExecutionTime.textContent = rule["Min execution time (ms)"]
375
-
376
- logRow.appendChild (cAttributeRule)
377
- logRow.appendChild (cTotalCost)
378
- logRow.appendChild (cMaxExecutionTime)
379
- logRow.appendChild (cMaxGuid)
380
- logRow.appendChild (cMinExecutionTime)
381
- tblResult.appendChild(logRow)
382
-
383
-
384
- })
1686
+ const cVersion = document.createElement("td");
1687
+ cVersion.textContent = m.gdbVersion
1688
+
1689
+ const cMoment = document.createElement("td");
1690
+ cMoment.textContent = m.moment
1691
+
1692
+ const cMethodName = document.createElement("td");
1693
+ cMethodName.textContent = m.methodName
385
1694
 
1695
+ const cWhere = document.createElement("td");
1696
+ cWhere.textContent = m.where
386
1697
 
387
- const totalARExecution = rules.reduce( (prev, cur) => prev + cur["Total Cost (ms)"], 0)
388
- console.log(`Total time spend executing attribute rules (${Math.round(totalARExecution)} ms) (${Math.round(totalARExecution/1000)} s) (${Math.round(totalARExecution/(1000*60))} m)`)
389
-
1698
+ const cGeometry = document.createElement("td");
1699
+ cGeometry.textContent = m.geometry
390
1700
 
1701
+
1702
+ const cRequestId = document.createElement("td");
1703
+ cRequestId.textContent = m.requestID
1704
+
1705
+ const buildGeoPython = `
1706
+ def make_poly(array):
1707
+ json = dict(hasZ=False, hasM=False, rings=array)
1708
+ return arcpy.AsShape(json, esri_json=True)
1709
+
1710
+ g = ${m.geometry}
1711
+ if 'rings' in g:
1712
+ arcpy.CopyFeatures_management(make_poly(g['rings']), 'memory/foo')
1713
+ else:
1714
+ verts = [[[g['xmin'], g['ymin']], [g['xmin'], g['ymax']], [g['xmax'
1715
+ ], g['ymax']], [g['xmax'], g['ymin']]]]
1716
+ arcpy.CopyFeatures_management(make_poly(verts), 'memory/foo')
1717
+
1718
+ `
1719
+ cGeometry.pythonCode = buildGeoPython
1720
+ //cLog.fullLog = m.payLoad;
1721
+ cGeometry.title = "\nClick to copy python code to generate geometry"
1722
+ cGeometry.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.pythonCode); alert("Copied to clipboard")})
1723
+
1724
+ const cTotalTime = document.createElement("td");
1725
+ cTotalTime.textContent = msToMinSecMs(m.elapsed*1000 )
1726
+ const cLog = document.createElement("td");
1727
+ const cLogText = document.createElement("input")
1728
+ cLogText.type = "text"
1729
+ cLogText.style = "width:400px"
1730
+ cLogText.value = m.message
1731
+ cLogText.readOnly= true;
1732
+ cLog.appendChild(cLogText)
1733
+
1734
+ logRow.appendChild (cService)
1735
+ logRow.appendChild (cTime)
1736
+ logRow.appendChild (cUser)
1737
+ logRow.appendChild (cVersion)
1738
+ logRow.appendChild (cMoment)
1739
+ logRow.appendChild (cMethodName)
1740
+ logRow.appendChild (cTotalTime)
1741
+ logRow.appendChild (cWhere)
1742
+ logRow.appendChild (cGeometry)
1743
+ logRow.appendChild (cRequestId)
1744
+ logRow.appendChild (cLog)
1745
+ tblResult.appendChild(logRow)
1746
+ });
1747
+
1748
+ addCSV(allMessages)
391
1749
 
392
1750
  }
1751
+
1752
+
393
1753
  async function loadSQLLogs () {
394
1754
 
395
1755
  //build table
@@ -460,11 +1820,15 @@ async function loadSQLLogs () {
460
1820
  const cVersion = document.createElement("th");
461
1821
  cVersion.textContent = "Version"
462
1822
  const cQueryTime = document.createElement("th");
463
- cQueryTime.textContent = "Query Time (ms)"
1823
+ cQueryTime.textContent = "Query Time"
464
1824
  cQueryTime.title = "includes search + data access nextRow"
465
1825
  const cTotalTime = document.createElement("th");
466
1826
  cTotalTime.title = "Total time the cursor was opened"
467
- cTotalTime.textContent = "Total Time (ms)"
1827
+ cTotalTime.textContent = "Total Time"
1828
+
1829
+ const cRequestId = document.createElement("th");
1830
+ cRequestId.textContent = "RequestId"
1831
+
468
1832
  const cLog = document.createElement("th");
469
1833
  cLog.textContent = "Full SQL"
470
1834
  header.appendChild (cService)
@@ -473,11 +1837,12 @@ async function loadSQLLogs () {
473
1837
  header.appendChild (cVersion)
474
1838
  header.appendChild (cQueryTime)
475
1839
  header.appendChild (cTotalTime)
1840
+ header.appendChild (cRequestId)
476
1841
  header.appendChild (cLog)
477
1842
  tblResult.appendChild(header)
478
1843
 
479
1844
 
480
- allMessages= allMessages.forEach(m =>
1845
+ allMessages.forEach(m =>
481
1846
  {
482
1847
 
483
1848
  const logRow = document.createElement("tr");
@@ -507,9 +1872,12 @@ async function loadSQLLogs () {
507
1872
  cVersion.textContent = m.message.substr( idxVersion + 9, idxNext - idxVersion - 9 )
508
1873
  }
509
1874
  const cQueryTime = document.createElement("td");
510
- cQueryTime.textContent = numberWithCommas(m.totalExecutionElapsed)
1875
+ cQueryTime.textContent = msToMinSecMs(m.totalExecutionElapsed )// numberWithCommas(m.totalExecutionElapsed)
511
1876
  const cTotalTime = document.createElement("td");
512
- cTotalTime.textContent = numberWithCommas(Math.round(m.elapsed*1000))
1877
+ cTotalTime.textContent = msToMinSecMs(m.elapsed*1000) //numberWithCommas(Math.round(m.elapsed*1000))
1878
+ const cRequestId = document.createElement("td");
1879
+ cRequestId.textContent = m.requestID
1880
+
513
1881
  const cLog = document.createElement("td");
514
1882
  const cLogText = document.createElement("input")
515
1883
  cLogText.type = "text"
@@ -520,22 +1888,22 @@ async function loadSQLLogs () {
520
1888
  //cLog.textContent = m.message.substr( m.message.indexOf("SQL: ") + 5, 50) + "..."
521
1889
  cLog.fullLog = m.message;
522
1890
  cLog.title = m.message + "\nClick to copy"
523
- cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
524
- /* alert("Copied to clipboard") */})
1891
+ //cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
1892
+ /* alert("Copied to clipboard") *///})
525
1893
  logRow.appendChild (cService)
526
1894
  logRow.appendChild (cTime)
527
1895
  logRow.appendChild (cUser)
528
1896
  logRow.appendChild (cVersion)
529
1897
  logRow.appendChild (cQueryTime)
530
1898
  logRow.appendChild (cTotalTime)
1899
+ logRow.appendChild (cRequestId)
531
1900
  logRow.appendChild (cLog)
532
1901
  tblResult.appendChild(logRow)
533
1902
 
534
1903
 
535
1904
  })
536
-
537
- //await populateMessages(allMessages)
538
-
1905
+
1906
+ addCSV(allMessages)
539
1907
 
540
1908
  }
541
1909
 
@@ -558,11 +1926,42 @@ function numberWithCommas(x) {
558
1926
  const btnUpdateSubnetworkLogs = document.getElementById("btnUpdateSubnetworkLogs");
559
1927
  btnUpdateSubnetworkLogs.addEventListener("click", e => loadUpdateSubnetworkLogs())
560
1928
  btnUpdateSubnetworkLogs.disabled = true
1929
+
1930
+
1931
+ const btnDownloadLogs = document.getElementById("btnDownloadLogs");
1932
+ btnDownloadLogs.addEventListener("click", e => downloadLogs())
1933
+ btnDownloadLogs.disabled = true
1934
+
1935
+
1936
+ const btnReconcileLogs = document.getElementById("btnReconcileLogs");
1937
+ btnReconcileLogs.addEventListener("click", e => reconcileLogs())
1938
+ btnReconcileLogs.disabled = true
1939
+
1940
+ const btnstopEditingLogs = document.getElementById("btnstopEditingLogs");
1941
+ btnstopEditingLogs.addEventListener("click", e => stopEditingLogs())
1942
+ btnstopEditingLogs.disabled = true
1943
+
1944
+
1945
+
1946
+ const btnWait = document.getElementById("btnWaitLogs");
1947
+ btnWait.addEventListener("click", e => waitLogs())
1948
+ btnWait.disabled = true
1949
+
561
1950
 
562
1951
  const btnSQLLogs = document.getElementById("btnSQLLogs");
563
1952
  btnSQLLogs.addEventListener("click", e => loadSQLLogs())
564
1953
  btnSQLLogs.disabled = true
565
1954
 
1955
+
1956
+ const btnApplyEditsLogs = document.getElementById("btnApplyEditsLogs");
1957
+ btnApplyEditsLogs.addEventListener("click", e => loadApplyEditsLogs())
1958
+ btnApplyEditsLogs.disabled = true
1959
+
1960
+
1961
+ const btnQueryLogs = document.getElementById("btnQueryLogs");
1962
+ btnQueryLogs.addEventListener("click", e => loadQueryLogs())
1963
+ btnQueryLogs.disabled = true
1964
+
566
1965
  const btnAR = document.getElementById("btnAR");
567
1966
  btnAR.addEventListener("click", e => loadAttributeRules())
568
1967
  btnAR.disabled = true
@@ -570,13 +1969,24 @@ function numberWithCommas(x) {
570
1969
  function filterMessages (allMessages) {
571
1970
  const txtFilter = document.getElementById("txtFilter")
572
1971
  const txtUser = document.getElementById("txtUser")
573
- if (txtFilter.value == "" && txtUser.value == "") return allMessages;
1972
+ const txtMethodName = document.getElementById("txtMethodName")
1973
+ const txtRequestId = document.getElementById("txtRequestId")
1974
+
1975
+ //don't bother if no filters
1976
+ if (txtFilter.value == "" && txtUser.value == ""
1977
+ && txtMethodName.value == "" && txtRequestId.value == "" ) return allMessages;
1978
+
574
1979
  //const filtered= allMessages.filter(m => m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) > 0 && m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) > 0)
575
1980
  const filtered= allMessages.filter(m => {
576
1981
 
577
1982
  if (m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) >= 0
578
- &&
579
- m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) >= 0)
1983
+ &&
1984
+ m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) >= 0
1985
+ &&
1986
+ m.methodName.toUpperCase().indexOf(txtMethodName.value.toUpperCase()) >= 0
1987
+ &&
1988
+ m.requestID.toUpperCase().indexOf(txtRequestId.value.toUpperCase()) >= 0
1989
+ )
580
1990
  return true
581
1991
 
582
1992
  return false
@@ -584,6 +1994,86 @@ function numberWithCommas(x) {
584
1994
  return filtered
585
1995
  }
586
1996
 
1997
+ async function populateMessagesAsIs(allTheMessages) {
1998
+
1999
+ //build table
2000
+ const tblResult = document.getElementById("tblResult");
2001
+ //clear
2002
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
2003
+ let totalElapsed = 0;
2004
+ const header = document.createElement("tr");
2005
+ const cService = document.createElement("th");
2006
+ cService.textContent = "Source"
2007
+ const cTime = document.createElement("th");
2008
+ cTime.textContent = "Time"
2009
+ const cUser = document.createElement("th");
2010
+ cUser.textContent = "User"
2011
+ const cMethod = document.createElement("th");
2012
+ cMethod.textContent = "Method"
2013
+ const cRequestId = document.createElement("th");
2014
+ cRequestId.textContent = "RequestId"
2015
+ const cCode = document.createElement("th");
2016
+ cCode.textContent = "Code"
2017
+ const cLevel = document.createElement("th");
2018
+ cLevel.textContent = "Level"
2019
+ const cElapsedMS = document.createElement("th");
2020
+ cElapsedMS.textContent = "Elapsed"
2021
+ const cLog = document.createElement("th");
2022
+ cLog.textContent = "Full Log"
2023
+ header.appendChild (cService)
2024
+ header.appendChild (cTime)
2025
+ header.appendChild (cUser)
2026
+ header.appendChild (cMethod)
2027
+ header.appendChild (cRequestId)
2028
+ header.appendChild (cCode)
2029
+ header.appendChild (cLevel)
2030
+
2031
+ header.appendChild (cElapsedMS)
2032
+ header.appendChild (cLog)
2033
+ tblResult.appendChild(header)
2034
+ allTheMessages.forEach(m => {
2035
+ const logRow = document.createElement("tr");
2036
+ const cService = document.createElement("td");
2037
+ cService.textContent = m.source.replace(".MapServer", "")
2038
+ const cTime = document.createElement("td");
2039
+ cTime.textContent = new Date(m.time).toLocaleString()
2040
+ const cUser = document.createElement("td");
2041
+ cUser.textContent = m.user
2042
+ const cMethod = document.createElement("td");
2043
+ cMethod.textContent = m.methodName
2044
+ const cRequestId = document.createElement("td");
2045
+ cRequestId.textContent = m.requestID
2046
+ const cCode = document.createElement("td");
2047
+ cCode.textContent = m.code
2048
+ const cLevel = document.createElement("td");
2049
+ cLevel.textContent = m.type
2050
+ const cElapsedMS = document.createElement("td");
2051
+ cElapsedMS.textContent =msToMinSecMs(m.elapsed)
2052
+ totalElapsed+=m.elapsed
2053
+ const cLog = document.createElement("td");
2054
+ cLog.textContent = m.message
2055
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
2056
+ logRow.appendChild (cService)
2057
+ logRow.appendChild (cTime)
2058
+ logRow.appendChild (cUser)
2059
+ logRow.appendChild (cMethod)
2060
+ logRow.appendChild (cRequestId)
2061
+ logRow.appendChild (cCode)
2062
+ logRow.appendChild (cLevel)
2063
+ logRow.appendChild (cElapsedMS)
2064
+ logRow.appendChild (cLog)
2065
+ tblResult.appendChild(logRow)
2066
+ }
2067
+
2068
+ )
2069
+ const logRow = document.createElement("tr");
2070
+ const cTotalElapsedMS = document.createElement("td");
2071
+ cTotalElapsedMS.colSpan = 9
2072
+ cTotalElapsedMS.textContent = `Total Elapsed ${msToMinSecMs(totalElapsed)}`
2073
+ logRow.appendChild(cTotalElapsedMS)
2074
+ tblResult.appendChild(logRow)
2075
+
2076
+ }
587
2077
  async function populateMessages(allTheMessages) {
588
2078
 
589
2079
  //sort messages
@@ -593,7 +2083,7 @@ function numberWithCommas(x) {
593
2083
  delete newMessage.machine;
594
2084
  delete newMessage.type;
595
2085
  delete newMessage.code;
596
- delete newMessage.requestID;
2086
+ //delete newMessage.requestID;
597
2087
  delete newMessage.process;
598
2088
  delete newMessage.thread;
599
2089
  newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
@@ -618,7 +2108,7 @@ function numberWithCommas(x) {
618
2108
  const cMethod = document.createElement("th");
619
2109
  cMethod.textContent = "Method"
620
2110
  const cElapsedMS = document.createElement("th");
621
- cElapsedMS.textContent = "Elapsed (ms)"
2111
+ cElapsedMS.textContent = "Elapsed"
622
2112
  const cLog = document.createElement("th");
623
2113
  cLog.textContent = "Full Log"
624
2114
  header.appendChild (cService)
@@ -639,7 +2129,7 @@ function numberWithCommas(x) {
639
2129
  const cMethod = document.createElement("td");
640
2130
  cMethod.textContent = m.methodName
641
2131
  const cElapsedMS = document.createElement("td");
642
- cElapsedMS.textContent = m.elapsedms
2132
+ cElapsedMS.textContent = msToMinSecMs(m.elapsedms)
643
2133
  const cLog = document.createElement("td");
644
2134
  cLog.textContent = "..."
645
2135
  cLog.fullLog = m.message;
@@ -655,8 +2145,16 @@ function numberWithCommas(x) {
655
2145
  }
656
2146
 
657
2147
 
658
- async function adminLogQueryWithPaging(mins, theService, code, filter, level){
659
- const topLogCount = 1000;
2148
+ //paging works from newer message walking to the oldest message
2149
+ //start time must be less than end time
2150
+ //you specify startTime, t10 and endtime t1
2151
+ //you get back messages from t10 to t5,
2152
+ //you then start start time at t5 and end time at t1
2153
+ //you then get messages from t5 to t3
2154
+ //you then set the start time at t3 and end time at t1
2155
+ //finally you get all messages between t3 and t1 and hasmore false.
2156
+ async function adminLogQueryWithPaging(mins, theService, code, messageFilter, level, methodFilter = ""){
2157
+ let topLogCount = 2000;
660
2158
  let stop = false;
661
2159
  const prg = document.createTextNode("Loading.... 0%");
662
2160
  const btn = document.createElement("button")
@@ -666,25 +2164,52 @@ function numberWithCommas(x) {
666
2164
  let adminLog = new AdminLog(token, portal.serverUrl)
667
2165
  tblResult.appendChild(prg);
668
2166
  tblResult.appendChild(btn)
669
- const startTime = Date.now()
670
- const endTime = Date.now() - mins*60*1000
671
- let services = [theService + ".MapServer"]
2167
+ let startTime = Date.now()
2168
+ const txtStartTime = document.getElementById("txtStartTime")
2169
+ if (txtStartTime.value != "")
2170
+ startTime = new Date(txtStartTime.value).getTime()
2171
+
2172
+ let endTime = startTime - mins*60*1000
2173
+ const txtEndTime = document.getElementById("txtEndTime")
2174
+ if (txtEndTime.value != "")
2175
+ endTime = new Date(txtEndTime.value).getTime()
2176
+
2177
+ let services = []
2178
+ if (!theService.includes(".GPServer"))
2179
+ services = [theService + ".MapServer"]
2180
+ else
2181
+ services = [theService]
2182
+
672
2183
  if (theService == "(All Services)")
673
2184
  services = "*"
2185
+
2186
+ if (theService == "Server")
2187
+ services = "Server"
2188
+
674
2189
  let result= await adminLog.query(code, services, topLogCount, startTime ,endTime , level)
675
2190
  let jsonRes = await result.json()
676
2191
  let allMessages = [].concat(jsonRes.logMessages)
677
- allMessages = allMessages.filter(m => m.message.indexOf(filter) > -1)
2192
+ allMessages = allMessages.filter(m => m.message.indexOf(messageFilter) > -1 && m.methodName.indexOf(methodFilter) > -1)
2193
+
2194
+ let oldStart = undefined;
2195
+ let newStartTime = undefined;
678
2196
  while (jsonRes.hasMore && !stop)
679
2197
  {
680
2198
  //start paging
681
- prg.textContent = "Loading ... " + parseInt((( (startTime - endTime) - (jsonRes.endTime - endTime) ) /((startTime - endTime)))*100) + "%"
682
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
683
- result= await adminLog.query(code, services, topLogCount, jsonRes.endTime, endTime, level)
2199
+ oldStart = newStartTime;
2200
+ newStartTime = jsonRes.endTime
2201
+ //we keep getting the same starttime, time to move towards end..
2202
+ if (oldStart == newStartTime)
2203
+ newStartTime-=1;
2204
+
2205
+ prg.textContent = "Loading ... " + Math.round(100*parseFloat((( (startTime - endTime) - (newStartTime - endTime) ) /((startTime - endTime)))*100),2)/100+ "%"
2206
+ logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(newStartTime)} and ${new Date(endTime)} ${newStartTime}-${endTime}`)
2207
+ result= await adminLog.query(code, services, topLogCount, newStartTime, endTime, level)
684
2208
  jsonRes = await result.json()
685
-
686
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf(filter) > -1))
2209
+
2210
+ allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf(messageFilter) > -1 && m.methodName.indexOf(methodFilter) > -1))
687
2211
  }
2212
+ logger.info(`Completed aggregation total messages ${allMessages.length}`);
688
2213
 
689
2214
  return allMessages
690
2215