un-cli 0.0.76 → 0.0.79

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,23 +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>
47
- <td>Start Time<input id = 'txtStartTime' type = 'text'></td>
48
- <td>End Time<input id = 'txtEndTime' 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>
49
44
  </tr>
45
+ <tr>
50
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>
51
79
  </table>
52
80
 
53
- <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">
54
82
 
55
83
  </table>
56
84
  <script type = 'module'>
@@ -60,15 +88,19 @@
60
88
  import logger from "./logger.mjs"
61
89
 
62
90
 
63
-
91
+
64
92
  let parameters = {
65
- "user": "unadmin",
93
+ "user": "",
66
94
  "password": "",
67
- "portal": "https://utilitynetwork.esri.com/portal",
95
+ "portal": "", //https://utilitynetwork.esri.com/portal set your portal url webadaptor if not /portal
68
96
  "service": "",
69
- "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
+
70
100
  }
71
-
101
+
102
+ if (parameters.portal === "") parameters.portal = window.location.origin + "/portal"
103
+ if (parameters.referer === "") parameters.referer = window.location.href
72
104
 
73
105
  let portal;
74
106
  let adminLog = null;
@@ -79,6 +111,14 @@
79
111
  const txtPassword = document.getElementById("txtPassword")
80
112
 
81
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
+
82
122
  async function init() {
83
123
  try {
84
124
 
@@ -93,10 +133,23 @@
93
133
  token = await getToken(parameters);
94
134
 
95
135
  //if we logged in successfully
96
- const opt = document.createElement("option")
136
+ let opt = document.createElement("option")
97
137
  opt.textContent = "(All Services)"
98
138
  cmbService.appendChild (opt)
99
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
+
100
153
  const services = await portal.services()
101
154
  const featureServices = services.services.filter(s => s.type == "FeatureServer")
102
155
  featureServices.forEach(s=> {
@@ -112,17 +165,23 @@
112
165
  document.getElementById("btnUpdateSubnetworkLogs").disabled = false
113
166
  document.getElementById("btnAR").disabled = false
114
167
  document.getElementById("btnSQLLogs").disabled = false
115
-
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
+
116
175
 
117
176
  }
118
177
  catch(ex){
119
- 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)}`)
120
179
  }
121
180
  }
122
181
 
123
182
 
124
183
  async function getToken(parameters) {
125
- 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)
126
185
  console.log("About to connect..")
127
186
  const token = await portal.connect()
128
187
  console.log(`Token generanted successfully.`)
@@ -152,7 +211,7 @@
152
211
  delete newMessage.machine;
153
212
  delete newMessage.type;
154
213
  delete newMessage.code;
155
- delete newMessage.requestID;
214
+ //delete newMessage.requestID;
156
215
  delete newMessage.process;
157
216
  delete newMessage.thread;
158
217
  newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
@@ -172,6 +231,15 @@
172
231
  let res1 = re1.exec(m.message)
173
232
  if (res1 && res1.length > 0)
174
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
+
175
243
 
176
244
  }
177
245
  catch(ex){
@@ -195,20 +263,29 @@
195
263
  cUser.textContent = "User"
196
264
  const cMethod = document.createElement("th");
197
265
  cMethod.textContent = "Method"
266
+ const cVersion = document.createElement("th");
267
+ cVersion.textContent = "Version"
268
+ const cMoment = document.createElement("th");
269
+ cMoment.textContent = "Moment"
198
270
  const cElapsedMS = document.createElement("th");
199
- cElapsedMS.textContent = "Elapsed (ms)"
271
+ cElapsedMS.textContent = "Elapsed"
200
272
  const cTraceType = document.createElement("th");
201
273
  cTraceType.textContent = "Trace Type"
202
274
  const cTraceTime = document.createElement("th");
203
275
  cTraceTime.textContent = "Trace Time"
276
+ const cRequestId = document.createElement("th");
277
+ cRequestId.textContent = "RequestId"
204
278
  const cLog = document.createElement("th");
205
279
  cLog.textContent = "Full Log"
206
280
  header.appendChild (cService)
207
281
  header.appendChild (cTime)
208
282
  header.appendChild (cUser)
209
283
  header.appendChild (cMethod)
284
+ header.appendChild (cVersion)
285
+ header.appendChild (cMoment)
210
286
  header.appendChild (cTraceType)
211
287
  header.appendChild (cTraceTime)
288
+ header.appendChild (cRequestId)
212
289
  header.appendChild (cElapsedMS)
213
290
 
214
291
  header.appendChild (cLog)
@@ -224,12 +301,17 @@
224
301
  const cMethod = document.createElement("td");
225
302
  cMethod.textContent = m.methodName
226
303
  const cElapsedMS = document.createElement("td");
227
- cElapsedMS.textContent = m.elapsedms
304
+ cElapsedMS.textContent = msToMinSecMs(m.elapsedms)
228
305
  const cTraceType = document.createElement("td");
229
306
  cTraceType.textContent = m.traceType
230
307
  const cTraceTime = document.createElement("td");
231
- cTraceTime.textContent = m.traceTime
232
-
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
233
315
  const cLog = document.createElement("td");
234
316
  cLog.textContent = "..."
235
317
  cLog.fullLog = m.message;
@@ -238,8 +320,11 @@
238
320
  logRow.appendChild (cTime)
239
321
  logRow.appendChild (cUser)
240
322
  logRow.appendChild (cMethod)
323
+ logRow.appendChild (cVersion)
324
+ logRow.appendChild (cMoment)
241
325
  logRow.appendChild (cTraceType)
242
326
  logRow.appendChild (cTraceTime)
327
+ logRow.appendChild (cRequestId)
243
328
  logRow.appendChild (cElapsedMS)
244
329
 
245
330
  logRow.appendChild (cLog)
@@ -247,7 +332,7 @@
247
332
  })
248
333
 
249
334
 
250
-
335
+ addCSV(allMessages)
251
336
  //await populateMessages(allMessages)
252
337
 
253
338
 
@@ -258,42 +343,229 @@
258
343
  async function loadValidateLogs () {
259
344
  //build table
260
345
  const tblResult = document.getElementById("tblResult");
261
- //clear
262
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
263
-
346
+
264
347
  parameters.service = cmbService.options[cmbService.selectedIndex].text
265
348
 
266
349
 
267
350
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
268
351
 
269
352
  console.log(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
270
-
271
- //-1 && m.message.indexOf("The network is built.") > -1 && m.methodName == 'BuildEngineLog')
272
- //page query the admin log
273
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "The network is built.", "VERBOSE")
274
-
275
-
276
- //validate logs missing elapsed populate it
277
- allMessages = allMessages.map( m => {
278
- try{
279
-
280
- //The network is built. 0.093 seconds (4.982 total) - 29 MB memory
281
353
 
282
- let re = /The network is built. [-+]?([0-9]*\.[0-9]+|[0-9]+) seconds \([-+]?([0-9]*\.[0-9]+|[0-9]+) total\)/;
283
- let res = re.exec(m.message)
284
- if (res && res.length > 1)
285
- m.elapsed = res[2]
354
+
355
+ let allMessages = [];
356
+ //clear
357
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
358
+
286
359
 
287
- return m;
288
- }
289
- catch(ex){
290
- return m;
291
- }
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 )
366
+
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\)/;
375
+
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;
292
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
293
541
 
542
+ const cValidateTime = document.createElement("td");
543
+ cValidateTime.textContent = msToMinSecMs(m.validateTime)
544
+
545
+ const cElapsedMS = document.createElement("td");
546
+ cElapsedMS.textContent = msToMinSecMs(m.elapsedms)
294
547
 
295
- await populateMessages(allMessages)
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
+ })
296
566
 
567
+ //await populateMessages(allMessages)
568
+ addCSV(allMessages)
297
569
 
298
570
  }
299
571
 
@@ -323,7 +595,7 @@ async function loadUpdateSubnetworkLogs () {
323
595
  delete newMessage.machine;
324
596
  delete newMessage.type;
325
597
  delete newMessage.code;
326
- delete newMessage.requestID;
598
+ //delete newMessage.requestID;
327
599
  delete newMessage.process;
328
600
  delete newMessage.thread;
329
601
 
@@ -374,9 +646,11 @@ async function loadUpdateSubnetworkLogs () {
374
646
  const cMethod = document.createElement("th");
375
647
  cMethod.textContent = "Method"
376
648
  const cElapsedMS = document.createElement("th");
377
- cElapsedMS.textContent = "Elapsed (ms)"
649
+ cElapsedMS.textContent = "Elapsed "
378
650
  const cSubnetworkName = document.createElement("th");
379
651
  cSubnetworkName.textContent = "Subnetwork Name"
652
+ const cRequestId = document.createElement("th");
653
+ cRequestId.textContent = "RequestId"
380
654
  const cLog = document.createElement("th");
381
655
  cLog.textContent = "Full Log"
382
656
  header.appendChild (cService)
@@ -385,7 +659,7 @@ async function loadUpdateSubnetworkLogs () {
385
659
  header.appendChild (cMethod)
386
660
  header.appendChild (cSubnetworkName)
387
661
  header.appendChild (cElapsedMS)
388
-
662
+ header.appendChild (cRequestId)
389
663
  header.appendChild (cLog)
390
664
  tblResult.appendChild(header)
391
665
  allMessages.forEach(m => {
@@ -399,10 +673,11 @@ async function loadUpdateSubnetworkLogs () {
399
673
  const cMethod = document.createElement("td");
400
674
  cMethod.textContent = m.methodName
401
675
  const cElapsedMS = document.createElement("td");
402
- cElapsedMS.textContent = m.elapsedms
676
+ cElapsedMS.textContent =msToMinSecMs(m.elapsedms)
403
677
  const cSubnetworkName = document.createElement("td");
404
678
  cSubnetworkName.textContent = m.subnetworkName
405
-
679
+ const cRequestId = document.createElement("td");
680
+ cRequestId.textContent = m.requestID
406
681
  const cLog = document.createElement("td");
407
682
  cLog.textContent = "..."
408
683
  cLog.fullLog = m.message;
@@ -413,11 +688,12 @@ async function loadUpdateSubnetworkLogs () {
413
688
  logRow.appendChild (cMethod)
414
689
  logRow.appendChild (cSubnetworkName)
415
690
  logRow.appendChild (cElapsedMS)
416
-
691
+ logRow.appendChild (cRequestId)
417
692
  logRow.appendChild (cLog)
418
693
  tblResult.appendChild(logRow)
419
694
  })
420
695
 
696
+ addCSV(allMessages)
421
697
 
422
698
 
423
699
  }
@@ -438,12 +714,12 @@ async function loadAttributeRules () {
438
714
  let showMinGuid = false
439
715
 
440
716
  logger.info(`Querying attribute rules logs for ${parameters.service} in the past ${mins} minutes...`)
441
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule execution complete:", "DEBUG")
717
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule executed:", "DEBUG")
442
718
 
443
719
 
444
720
  const arMessages = filterMessages(allMessages)
445
- .filter(m => m.message.indexOf("Attribute rule execution complete:") > -1)
446
- .map (m => JSON.parse(m.message.replace("Attribute rule execution complete:", "")))
721
+ .filter(m => m.message.indexOf("Attribute rule executed: ") > -1)
722
+ .map (m => JSON.parse(m.message.replace("Attribute rule executed: ", "")))
447
723
  .map( m => {
448
724
  m["Elapsed Time (ms)"] = Math.round(m["Elapsed Time"]*1000000)/1000
449
725
  // m["Arcade Evaluation Time:"] = Math.round(m["Arcade Evaluation Time:"]*1000,6)
@@ -493,6 +769,7 @@ async function loadAttributeRules () {
493
769
  const rule = {}
494
770
  rule["Attribute Rule"] = a;
495
771
  rule["Total Cost (ms)"] = parseFloat(arMessages[a].totalTime.toFixed(2))
772
+ rule["Occurrence"] = parseFloat(arMessages[a].occurrence)
496
773
  if (!showMinGuid && !showMaxGuid) rule["Average Cost (ms)"] = parseFloat(arMessages[a].avgTime.toFixed(2))
497
774
  rule["Max execution time (ms)"] = parseFloat(arMessages[a].maxTime.toFixed(2))
498
775
  if (showMaxGuid) rule["Max GUID"] = arMessages[a].maxGuid
@@ -521,6 +798,9 @@ async function loadAttributeRules () {
521
798
  const cTotalCost = document.createElement("th");
522
799
  cTotalCost.textContent = "Total Cost (ms)"
523
800
 
801
+ const cOccurrence = document.createElement("th");
802
+ cOccurrence.textContent = "Occurrence"
803
+
524
804
  const cMaxExecutionTime = document.createElement("th");
525
805
  cMaxExecutionTime.textContent = "Max execution time (ms)"
526
806
 
@@ -533,6 +813,7 @@ async function loadAttributeRules () {
533
813
 
534
814
  header.appendChild (cAttributeRule)
535
815
  header.appendChild (cTotalCost)
816
+ header.appendChild (cOccurrence)
536
817
  header.appendChild (cMaxExecutionTime)
537
818
  header.appendChild (cMaxGuid)
538
819
  header.appendChild (cMinExecutionTime)
@@ -547,20 +828,24 @@ async function loadAttributeRules () {
547
828
  const cAttributeRule = document.createElement("td");
548
829
  cAttributeRule.textContent = rule["Attribute Rule"]
549
830
 
831
+ const cOccurrence = document.createElement("td");
832
+ cOccurrence.textContent = rule["Occurrence"]
833
+
550
834
  const cTotalCost = document.createElement("td");
551
- cTotalCost.textContent = rule["Total Cost (ms)"]
552
-
835
+ cTotalCost.textContent = msToMinSecMs(rule["Total Cost (ms)"])
836
+
553
837
  const cMaxExecutionTime = document.createElement("td");
554
- cMaxExecutionTime.textContent = rule["Max execution time (ms)"]
838
+ cMaxExecutionTime.textContent = msToMinSecMs(rule["Max execution time (ms)"])
555
839
 
556
840
  const cMaxGuid = document.createElement("td");
557
841
  cMaxGuid.textContent = rule["Max GUID"]
558
842
 
559
843
  const cMinExecutionTime = document.createElement("td");
560
- cMinExecutionTime.textContent = rule["Min execution time (ms)"]
844
+ cMinExecutionTime.textContent = msToMinSecMs(rule["Min execution time (ms)"])
561
845
 
562
846
  logRow.appendChild (cAttributeRule)
563
847
  logRow.appendChild (cTotalCost)
848
+ logRow.appendChild (cOccurrence)
564
849
  logRow.appendChild (cMaxExecutionTime)
565
850
  logRow.appendChild (cMaxGuid)
566
851
  logRow.appendChild (cMinExecutionTime)
@@ -572,11 +857,13 @@ async function loadAttributeRules () {
572
857
 
573
858
  const totalARExecution = rules.reduce( (prev, cur) => prev + cur["Total Cost (ms)"], 0)
574
859
  console.log(`Total time spend executing attribute rules (${Math.round(totalARExecution)} ms) (${Math.round(totalARExecution/1000)} s) (${Math.round(totalARExecution/(1000*60))} m)`)
575
-
860
+ addCSV(rules)
576
861
 
577
862
 
578
863
  }
579
- async function loadSQLLogs () {
864
+
865
+
866
+ async function downloadLogs () {
580
867
 
581
868
  //build table
582
869
  const tblResult = document.getElementById("tblResult");
@@ -590,83 +877,975 @@ async function loadSQLLogs () {
590
877
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
591
878
 
592
879
 
593
- console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
880
+ console.log(`Querying all debug logs for ${parameters.service} for the last ${mins} minutes ...`)
594
881
 
595
882
  //startTime is the most recent
596
883
  //endTime is the oldest
597
884
 
598
885
 
599
886
  //page query the admin log
600
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102023], "EndCursor;", "DEBUG")
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
+
601
900
 
901
+ await populateMessagesAsIs(allMessages)
902
+ addCSV(allMessages)
903
+
904
+ }
602
905
 
603
- console.log ("Filtering messages...")
604
-
605
- allMessages = filterMessages(allMessages)
606
- .map( m=> {
607
- m.dataAccessElapsed =0;
608
- m.executeQueryElapsed = 0;
609
- const sDataAccess = "DataAccess "
610
- const idxDataAccess = m.message.indexOf(sDataAccess)
611
- if (idxDataAccess >=0) {
612
- const idxNext = m.message.indexOf(" ",idxDataAccess + sDataAccess.length )
613
- m.dataAccessElapsed = parseInt(m.message.substr( idxDataAccess + sDataAccess.length, idxNext - idxDataAccess - sDataAccess.length))
614
- }
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
+ })
615
914
 
616
- const sExecuteQuery = "ExecuteQuery "
617
- const idxExecuteQuery = m.message.indexOf(sExecuteQuery)
618
- if (idxExecuteQuery >=0) {
619
- const idxNext = m.message.indexOf(" ",idxExecuteQuery + sExecuteQuery.length)
620
- m.executeQueryElapsed = parseInt(m.message.substr( idxExecuteQuery + sExecuteQuery.length, idxNext - idxExecuteQuery - sExecuteQuery.length))
621
- }
622
-
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);
623
924
 
624
- //m.dataAccessElapsed = parseFloat(m.message.split(";")[1].split(" ")[1])
625
- //m.executeQueryElapsed = parseFloat(m.message.split(";")[2].split(" ")[1])
626
- m.totalExecutionElapsed = m.dataAccessElapsed + m.executeQueryElapsed
627
- m.elapsed = parseFloat(m.elapsed); return m;
925
+ }
628
926
 
629
- })
630
- .sort( (m1,m2) => m2.totalExecutionElapsed - m1.totalExecutionElapsed)
631
- .slice(0, 100) ;//first 100
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)
632
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
+
633
961
 
634
- console.log("-----Top SQL----")
635
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
962
+ //page query the admin log , search for /applyEdits logs by methodname
963
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [17002,100004], "", "FINE", "/applyEdits")
636
964
 
637
- let i =0;
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
+ }
638
1015
 
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 cVersion = document.createElement("th");
647
- cVersion.textContent = "Version"
648
- const cQueryTime = document.createElement("th");
649
- cQueryTime.textContent = "Query Time (ms)"
650
- cQueryTime.title = "includes search + data access nextRow"
651
- const cTotalTime = document.createElement("th");
652
- cTotalTime.title = "Total time the cursor was opened"
653
- cTotalTime.textContent = "Total Time (ms)"
654
- const cLog = document.createElement("th");
655
- cLog.textContent = "Full SQL"
656
- header.appendChild (cService)
657
- header.appendChild (cTime)
658
- header.appendChild (cUser)
659
- header.appendChild (cVersion)
660
- header.appendChild (cQueryTime)
661
- header.appendChild (cTotalTime)
662
- header.appendChild (cLog)
663
- tblResult.appendChild(header)
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
+ }
664
1023
 
1024
+
1025
+
1026
+ })
665
1027
 
666
- allMessages= allMessages.forEach(m =>
667
- {
668
-
669
- const logRow = document.createElement("tr");
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)
1549
+
1550
+
1551
+
1552
+ }
1553
+
1554
+
1555
+ async function loadQueryLogs () {
1556
+
1557
+ //build table
1558
+ const tblResult = document.getElementById("tblResult");
1559
+ //clear
1560
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1561
+
1562
+
1563
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
1564
+
1565
+
1566
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1567
+
1568
+
1569
+ console.log(`Querying query logs for ${parameters.service} for the last ${mins} minutes ...`)
1570
+
1571
+ //startTime is the most recent
1572
+ //endTime is the oldest
1573
+
1574
+
1575
+ //page query the admin log , search for /applyEdits logs by methodname
1576
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [17002,100004], "", "FINE", "layers/")
1577
+
1578
+
1579
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1580
+
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
1639
+
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
+ }
1653
+
1654
+
1655
+
1656
+ })
1657
+
1658
+ allMessages = []
1659
+
1660
+ Object.keys(queryLogs).forEach(k =>
1661
+ {
1662
+ const m = queryLogs[k]
1663
+ allMessages.push(m)
1664
+
1665
+ })
1666
+
1667
+
1668
+
1669
+ console.log ("Filtering messages...")
1670
+
1671
+ allMessages = filterMessages(allMessages)
1672
+ .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
1673
+
1674
+ allMessages.forEach (m => {
1675
+ const logRow = document.createElement("tr");
1676
+
1677
+ const cService = document.createElement("th");
1678
+ cService.textContent = m.source
1679
+
1680
+ const cTime = document.createElement("td");
1681
+ cTime.textContent = new Date(m.time).toLocaleString()
1682
+
1683
+ const cUser = document.createElement("td");
1684
+ cUser.textContent = m.user
1685
+
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
1694
+
1695
+ const cWhere = document.createElement("td");
1696
+ cWhere.textContent = m.where
1697
+
1698
+ const cGeometry = document.createElement("td");
1699
+ cGeometry.textContent = m.geometry
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)
1749
+
1750
+ }
1751
+
1752
+
1753
+ async function loadSQLLogs () {
1754
+
1755
+ //build table
1756
+ const tblResult = document.getElementById("tblResult");
1757
+ //clear
1758
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1759
+
1760
+
1761
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
1762
+
1763
+
1764
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1765
+
1766
+
1767
+ console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
1768
+
1769
+ //startTime is the most recent
1770
+ //endTime is the oldest
1771
+
1772
+
1773
+ //page query the admin log
1774
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102023], "EndCursor;", "DEBUG")
1775
+
1776
+
1777
+ console.log ("Filtering messages...")
1778
+
1779
+ allMessages = filterMessages(allMessages)
1780
+ .map( m=> {
1781
+ m.dataAccessElapsed =0;
1782
+ m.executeQueryElapsed = 0;
1783
+ const sDataAccess = "DataAccess "
1784
+ const idxDataAccess = m.message.indexOf(sDataAccess)
1785
+ if (idxDataAccess >=0) {
1786
+ const idxNext = m.message.indexOf(" ",idxDataAccess + sDataAccess.length )
1787
+ m.dataAccessElapsed = parseInt(m.message.substr( idxDataAccess + sDataAccess.length, idxNext - idxDataAccess - sDataAccess.length))
1788
+ }
1789
+
1790
+ const sExecuteQuery = "ExecuteQuery "
1791
+ const idxExecuteQuery = m.message.indexOf(sExecuteQuery)
1792
+ if (idxExecuteQuery >=0) {
1793
+ const idxNext = m.message.indexOf(" ",idxExecuteQuery + sExecuteQuery.length)
1794
+ m.executeQueryElapsed = parseInt(m.message.substr( idxExecuteQuery + sExecuteQuery.length, idxNext - idxExecuteQuery - sExecuteQuery.length))
1795
+ }
1796
+
1797
+
1798
+ //m.dataAccessElapsed = parseFloat(m.message.split(";")[1].split(" ")[1])
1799
+ //m.executeQueryElapsed = parseFloat(m.message.split(";")[2].split(" ")[1])
1800
+ m.totalExecutionElapsed = m.dataAccessElapsed + m.executeQueryElapsed
1801
+ m.elapsed = parseFloat(m.elapsed); return m;
1802
+
1803
+ })
1804
+ .sort( (m1,m2) => m2.totalExecutionElapsed - m1.totalExecutionElapsed)
1805
+ .slice(0, 100) ;//first 100
1806
+
1807
+
1808
+ console.log("-----Top SQL----")
1809
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1810
+
1811
+ let i =0;
1812
+
1813
+ const header = document.createElement("tr");
1814
+ const cService = document.createElement("th");
1815
+ cService.textContent = "Source"
1816
+ const cTime = document.createElement("th");
1817
+ cTime.textContent = "Time"
1818
+ const cUser = document.createElement("th");
1819
+ cUser.textContent = "User"
1820
+ const cVersion = document.createElement("th");
1821
+ cVersion.textContent = "Version"
1822
+ const cQueryTime = document.createElement("th");
1823
+ cQueryTime.textContent = "Query Time"
1824
+ cQueryTime.title = "includes search + data access nextRow"
1825
+ const cTotalTime = document.createElement("th");
1826
+ cTotalTime.title = "Total time the cursor was opened"
1827
+ cTotalTime.textContent = "Total Time"
1828
+
1829
+ const cRequestId = document.createElement("th");
1830
+ cRequestId.textContent = "RequestId"
1831
+
1832
+ const cLog = document.createElement("th");
1833
+ cLog.textContent = "Full SQL"
1834
+ header.appendChild (cService)
1835
+ header.appendChild (cTime)
1836
+ header.appendChild (cUser)
1837
+ header.appendChild (cVersion)
1838
+ header.appendChild (cQueryTime)
1839
+ header.appendChild (cTotalTime)
1840
+ header.appendChild (cRequestId)
1841
+ header.appendChild (cLog)
1842
+ tblResult.appendChild(header)
1843
+
1844
+
1845
+ allMessages.forEach(m =>
1846
+ {
1847
+
1848
+ const logRow = document.createElement("tr");
670
1849
  const x = m.message.split(";")
671
1850
  x.shift()
672
1851
  console.log(`id: ${i++}`)
@@ -693,9 +1872,12 @@ async function loadSQLLogs () {
693
1872
  cVersion.textContent = m.message.substr( idxVersion + 9, idxNext - idxVersion - 9 )
694
1873
  }
695
1874
  const cQueryTime = document.createElement("td");
696
- cQueryTime.textContent = numberWithCommas(m.totalExecutionElapsed)
1875
+ cQueryTime.textContent = msToMinSecMs(m.totalExecutionElapsed )// numberWithCommas(m.totalExecutionElapsed)
697
1876
  const cTotalTime = document.createElement("td");
698
- 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
+
699
1881
  const cLog = document.createElement("td");
700
1882
  const cLogText = document.createElement("input")
701
1883
  cLogText.type = "text"
@@ -706,22 +1888,22 @@ async function loadSQLLogs () {
706
1888
  //cLog.textContent = m.message.substr( m.message.indexOf("SQL: ") + 5, 50) + "..."
707
1889
  cLog.fullLog = m.message;
708
1890
  cLog.title = m.message + "\nClick to copy"
709
- cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
710
- /* 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") *///})
711
1893
  logRow.appendChild (cService)
712
1894
  logRow.appendChild (cTime)
713
1895
  logRow.appendChild (cUser)
714
1896
  logRow.appendChild (cVersion)
715
1897
  logRow.appendChild (cQueryTime)
716
1898
  logRow.appendChild (cTotalTime)
1899
+ logRow.appendChild (cRequestId)
717
1900
  logRow.appendChild (cLog)
718
1901
  tblResult.appendChild(logRow)
719
1902
 
720
1903
 
721
1904
  })
722
-
723
- //await populateMessages(allMessages)
724
-
1905
+
1906
+ addCSV(allMessages)
725
1907
 
726
1908
  }
727
1909
 
@@ -744,11 +1926,42 @@ function numberWithCommas(x) {
744
1926
  const btnUpdateSubnetworkLogs = document.getElementById("btnUpdateSubnetworkLogs");
745
1927
  btnUpdateSubnetworkLogs.addEventListener("click", e => loadUpdateSubnetworkLogs())
746
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
+
747
1950
 
748
1951
  const btnSQLLogs = document.getElementById("btnSQLLogs");
749
1952
  btnSQLLogs.addEventListener("click", e => loadSQLLogs())
750
1953
  btnSQLLogs.disabled = true
751
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
+
752
1965
  const btnAR = document.getElementById("btnAR");
753
1966
  btnAR.addEventListener("click", e => loadAttributeRules())
754
1967
  btnAR.disabled = true
@@ -756,13 +1969,24 @@ function numberWithCommas(x) {
756
1969
  function filterMessages (allMessages) {
757
1970
  const txtFilter = document.getElementById("txtFilter")
758
1971
  const txtUser = document.getElementById("txtUser")
759
- 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
+
760
1979
  //const filtered= allMessages.filter(m => m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) > 0 && m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) > 0)
761
1980
  const filtered= allMessages.filter(m => {
762
1981
 
763
1982
  if (m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) >= 0
764
- &&
765
- 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
+ )
766
1990
  return true
767
1991
 
768
1992
  return false
@@ -770,6 +1994,86 @@ function numberWithCommas(x) {
770
1994
  return filtered
771
1995
  }
772
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
+ }
773
2077
  async function populateMessages(allTheMessages) {
774
2078
 
775
2079
  //sort messages
@@ -779,7 +2083,7 @@ function numberWithCommas(x) {
779
2083
  delete newMessage.machine;
780
2084
  delete newMessage.type;
781
2085
  delete newMessage.code;
782
- delete newMessage.requestID;
2086
+ //delete newMessage.requestID;
783
2087
  delete newMessage.process;
784
2088
  delete newMessage.thread;
785
2089
  newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
@@ -804,7 +2108,7 @@ function numberWithCommas(x) {
804
2108
  const cMethod = document.createElement("th");
805
2109
  cMethod.textContent = "Method"
806
2110
  const cElapsedMS = document.createElement("th");
807
- cElapsedMS.textContent = "Elapsed (ms)"
2111
+ cElapsedMS.textContent = "Elapsed"
808
2112
  const cLog = document.createElement("th");
809
2113
  cLog.textContent = "Full Log"
810
2114
  header.appendChild (cService)
@@ -825,7 +2129,7 @@ function numberWithCommas(x) {
825
2129
  const cMethod = document.createElement("td");
826
2130
  cMethod.textContent = m.methodName
827
2131
  const cElapsedMS = document.createElement("td");
828
- cElapsedMS.textContent = m.elapsedms
2132
+ cElapsedMS.textContent = msToMinSecMs(m.elapsedms)
829
2133
  const cLog = document.createElement("td");
830
2134
  cLog.textContent = "..."
831
2135
  cLog.fullLog = m.message;
@@ -841,8 +2145,16 @@ function numberWithCommas(x) {
841
2145
  }
842
2146
 
843
2147
 
844
- async function adminLogQueryWithPaging(mins, theService, code, filter, level){
845
- 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;
846
2158
  let stop = false;
847
2159
  const prg = document.createTextNode("Loading.... 0%");
848
2160
  const btn = document.createElement("button")
@@ -862,23 +2174,42 @@ function numberWithCommas(x) {
862
2174
  if (txtEndTime.value != "")
863
2175
  endTime = new Date(txtEndTime.value).getTime()
864
2176
 
865
- let services = [theService + ".MapServer"]
2177
+ let services = []
2178
+ if (!theService.includes(".GPServer"))
2179
+ services = [theService + ".MapServer"]
2180
+ else
2181
+ services = [theService]
2182
+
866
2183
  if (theService == "(All Services)")
867
2184
  services = "*"
2185
+
2186
+ if (theService == "Server")
2187
+ services = "Server"
2188
+
868
2189
  let result= await adminLog.query(code, services, topLogCount, startTime ,endTime , level)
869
2190
  let jsonRes = await result.json()
870
2191
  let allMessages = [].concat(jsonRes.logMessages)
871
- 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;
872
2196
  while (jsonRes.hasMore && !stop)
873
2197
  {
874
2198
  //start paging
875
- prg.textContent = "Loading ... " + parseInt((( (startTime - endTime) - (jsonRes.endTime - endTime) ) /((startTime - endTime)))*100) + "%"
876
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
877
- 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)
878
2208
  jsonRes = await result.json()
879
-
880
- 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))
881
2211
  }
2212
+ logger.info(`Completed aggregation total messages ${allMessages.length}`);
882
2213
 
883
2214
  return allMessages
884
2215