un-cli 0.0.71 → 0.0.74

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.
Files changed (5) hide show
  1. package/cmd.txt +1 -1
  2. package/index.html +237 -200
  3. package/index.mjs +110 -92
  4. package/logger.mjs +16 -2
  5. package/package.json +1 -1
package/cmd.txt CHANGED
@@ -1,2 +1,2 @@
1
- update subnetworks --all --desc
1
+ export subnetworks --all
2
2
  exit
package/index.html CHANGED
@@ -9,16 +9,32 @@
9
9
  <body>
10
10
 
11
11
  <table>
12
+ <tr>
13
+ <td>
14
+ Admin User
15
+ </td>
16
+ <td colspan =3><input type = 'text' id = 'txtAdmin' value = 'admin'></td>
17
+ </tr>
18
+ <tr>
19
+ <td>
20
+ Admin Password
21
+ </td>
22
+ <td colspan =3><input type = 'password' id = 'txtPassword' value = ''></td>
23
+ </tr>
24
+ <tr>
25
+
26
+ <td colspan =5><button id = 'btnLogin'>Login</button></td>
27
+ </tr>
12
28
  <tr><td>Service</td>
13
29
  <td colspan =3 ><select id ='cmbService'>
14
- <option>(All Services)</option>
30
+
15
31
  </select>
16
32
  </td>
17
33
  </tr>
18
34
 
19
35
  <tr>
20
36
  <td >Age</td>
21
- <td colspan =3><input type ='text' id = 'txtAge' value = '30' style="width:30px"> minutes</td>
37
+ <td colspan =3><input type ='text' id = 'txtAge' value = '10' style="width:30px"> minutes</td>
22
38
  </tr>
23
39
  <tr colspan =4>
24
40
  <td><button id = 'btnTraceLogs'>Trace Logs</button></td>
@@ -26,7 +42,8 @@
26
42
  <td><button id = 'btnUpdateSubnetworkLogs'>Update Subnetwork Logs</button></td>
27
43
  <td><button id = 'btnAR'>Attribute Rules Logs</button></td>
28
44
  <td><button id = 'btnSQLLogs'>SQL Logs</button></td>
29
-
45
+ <td>Message<input id = 'txtFilter' type = 'text'></td>
46
+ <td>User<input id = 'txtUser' type = 'text'></td>
30
47
  </tr>
31
48
 
32
49
  </table>
@@ -39,24 +56,45 @@
39
56
  import { UtilityNetwork } from "./utilitynetwork.node.mjs"
40
57
  import { AdminLog } from "./adminlog.mjs"
41
58
  import logger from "./logger.mjs"
59
+
60
+
42
61
 
43
- const parameters = {
62
+ let parameters = {
44
63
  "user": "unadmin",
45
- "password": "unadmin.109",
64
+ "password": "",
46
65
  "portal": "https://utilitynetwork.esri.com/portal",
47
- "service": "RedTrolley_SQLServer",
66
+ "service": "",
48
67
  "referer": "https://utilitynetwork.esri.com/log"
49
68
  }
69
+
50
70
 
51
71
  let portal;
52
72
  let adminLog = null;
53
73
  let cmbService
54
74
  let token;
75
+ const btnLogin = document.getElementById("btnLogin")
76
+ const txtAdmin = document.getElementById("txtAdmin");
77
+ const txtPassword = document.getElementById("txtPassword")
78
+
79
+ btnLogin.addEventListener("click", () => init())
55
80
  async function init() {
56
-
81
+ try {
82
+
83
+
84
+ parameters.user = txtAdmin.value;
85
+ parameters.password = txtPassword.value;
86
+ parameters.referer = window.location.href;
87
+
57
88
  cmbService = document.getElementById("cmbService")
58
-
89
+ while (cmbService.firstChild) cmbService.removeChild(cmbService.firstChild)
90
+
59
91
  token = await getToken(parameters);
92
+
93
+ //if we logged in successfully
94
+ const opt = document.createElement("option")
95
+ opt.textContent = "(All Services)"
96
+ cmbService.appendChild (opt)
97
+
60
98
  const services = await portal.services()
61
99
  const featureServices = services.services.filter(s => s.type == "FeatureServer")
62
100
  featureServices.forEach(s=> {
@@ -64,6 +102,20 @@
64
102
  o.text = s.name;
65
103
  cmbService.appendChild(o);
66
104
  })
105
+
106
+
107
+
108
+ document.getElementById("btnTraceLogs").disabled = false
109
+ document.getElementById("btnValidateLogs").disabled = false
110
+ document.getElementById("btnUpdateSubnetworkLogs").disabled = false
111
+ document.getElementById("btnAR").disabled = false
112
+ document.getElementById("btnSQLLogs").disabled = false
113
+
114
+
115
+ }
116
+ catch(ex){
117
+ alert(`Failed to login to ${parameters.portal} check the user/password and make sure its an admin`)
118
+ }
67
119
  }
68
120
 
69
121
 
@@ -82,42 +134,17 @@
82
134
  const tblResult = document.getElementById("tblResult");
83
135
  //clear
84
136
  while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
85
- tblResult.appendChild(document.createTextNode("Loading...."));
86
137
 
87
138
 
88
139
  parameters.service = cmbService.options[cmbService.selectedIndex].text
89
-
90
- //create a new admin object (user might not be admin we won't use it until the user call log )
91
- adminLog = new AdminLog(token, portal.serverUrl)
92
-
93
- logger.info("Connected.")
94
-
95
-
96
- const topLogCount = 1000;
97
- const pageSize = 10000
98
-
140
+
99
141
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
100
142
 
101
143
  console.log(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
102
- const startTime = Date.now() - mins*60*1000
103
- const endTime = Date.now();
104
- let services = [parameters.service+ ".MapServer"]
105
- if (parameters.service == "(All Services)")
106
- services = "*"
107
- let result= await adminLog.query([102002], services, topLogCount, startTime ,endTime , "VERBOSE")
108
- let jsonRes = await result.json()
109
- let allMessages = [].concat(jsonRes.logMessages)
110
- allMessages = allMessages.filter(m => m.message.indexOf("------ Trace Parameters ----") > -1)
111
- while (jsonRes.hasMore)
112
- {
113
- //start paging
114
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs before ${new Date(jsonRes.endTime)}`)
115
- result= await adminLog.query([102002], services, pageSize, jsonRes.endTime, null, "VERBOSE")
116
- jsonRes = await result.json()
117
-
118
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("------ Trace Parameters ----") > -1))
119
- }
120
-
144
+
145
+ //page query the admin log
146
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102002], "------ Trace Parameters ----", "VERBOSE")
147
+
121
148
  await populateMessages(allMessages)
122
149
 
123
150
 
@@ -126,49 +153,23 @@
126
153
 
127
154
 
128
155
  async function loadValidateLogs () {
129
- //build table
130
- const tblResult = document.getElementById("tblResult");
131
- //clear
132
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
133
- tblResult.appendChild(document.createTextNode("Loading...."));
134
-
135
- parameters.service = cmbService.options[cmbService.selectedIndex].text
136
-
137
-
138
- //create a new admin object (user might not be admin we won't use it until the user call log )
139
- adminLog = new AdminLog(token, portal.serverUrl)
156
+ //build table
157
+ const tblResult = document.getElementById("tblResult");
158
+ //clear
159
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
140
160
 
141
- logger.info("Connected.")
142
-
143
-
144
- const topLogCount = 1000;
145
- const pageSize = 10000
161
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
146
162
 
163
+
147
164
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
148
165
 
149
166
  console.log(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
150
- const startTime = Date.now() - mins*60*1000
151
- const endTime = Date.now();
152
- let services = [parameters.service+ ".MapServer"]
153
- if (parameters.service == "(All Services)")
154
- services = "*"
155
- let result= await adminLog.query([102003], services, topLogCount, startTime ,endTime , "VERBOSE")
156
- let jsonRes = await result.json()
157
- let allMessages = [].concat(jsonRes.logMessages)
158
- allMessages = allMessages.filter(m => m.message.indexOf("-------- Environment ---") > -1 && m.message.indexOf("The network is built.") > -1 && m.methodName == 'BuildEngineLog')
159
- while (jsonRes.hasMore)
160
- {
161
- //start paging
162
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs before ${new Date(jsonRes.endTime)}`)
163
- result= await adminLog.query([102003], services, pageSize, jsonRes.endTime, null, "VERBOSE")
164
- jsonRes = await result.json()
165
-
166
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("-------- Environment ---") > -1 && m.message.indexOf("------ Trace Parameters ----") == -1))
167
- }
168
-
169
-
170
-
171
-
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")
171
+
172
+
172
173
  //validate logs missing elapsed populate it
173
174
  allMessages = allMessages.map( m => {
174
175
  try{
@@ -195,45 +196,21 @@ tblResult.appendChild(document.createTextNode("Loading...."));
195
196
 
196
197
 
197
198
  async function loadUpdateSubnetworkLogs () {
198
- //build table
199
- const tblResult = document.getElementById("tblResult");
200
- //clear
201
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
202
- tblResult.appendChild(document.createTextNode("Loading...."));
203
-
204
- parameters.service = cmbService.options[cmbService.selectedIndex].text
205
- //create a new admin object (user might not be admin we won't use it until the user call log )
206
- adminLog = new AdminLog(token, portal.serverUrl)
199
+ //build table
200
+ const tblResult = document.getElementById("tblResult");
201
+ //clear
202
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
207
203
 
208
- logger.info("Connected.")
209
-
210
-
211
- const topLogCount = 1000;
212
- const pageSize = 10000
204
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
205
+
206
+
207
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
213
208
 
214
- let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
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")
215
212
 
216
-
217
- console.log(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
218
- const startTime = Date.now() - mins*60*1000
219
- const endTime = Date.now();
220
- let services = [parameters.service+ ".MapServer"]
221
- if (parameters.service == "(All Services)")
222
- services = "*"
223
- let result= await adminLog.query([102003], services, topLogCount, startTime ,endTime , "VERBOSE")
224
- let jsonRes = await result.json()
225
- let allMessages = [].concat(jsonRes.logMessages)
226
- allMessages = allMessages.filter(m => m.message.indexOf("---- Subnetwork Parameters ----") > -1)
227
- while (jsonRes.hasMore)
228
- {
229
- //start paging
230
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs before ${new Date(jsonRes.endTime)}`)
231
- result= await adminLog.query([102003], services, pageSize, jsonRes.endTime, null, "VERBOSE")
232
- jsonRes = await result.json()
233
-
234
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("---- Subnetwork Parameters ----") > -1))
235
- }
236
-
213
+
237
214
  //update subnetwork missing elapsed populate it
238
215
  allMessages = allMessages.map( m => {
239
216
  try{
@@ -265,41 +242,20 @@ async function loadAttributeRules () {
265
242
 
266
243
  //build table
267
244
  const tblResult = document.getElementById("tblResult");
268
- tblResult.appendChild(document.createTextNode("Loading...."));
269
-
245
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
246
+
270
247
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
271
248
 
272
249
  parameters.service = cmbService.options[cmbService.selectedIndex].text
273
- //create a new admin object (user might not be admin we won't use it until the user call log )
274
- adminLog = new AdminLog(token, portal.serverUrl)
275
-
250
+
276
251
  let showMaxGuid = true
277
- let showMinGuid = false
278
- const startTime = Date.now() - mins*60*1000
279
- const endTime = Date.now();
280
-
281
- let services = [parameters.service+ ".MapServer"]
282
- if (parameters.service == "(All Services)")
283
- services = "*"
284
-
285
- const pageSize = 10000 //maximum messages per page
252
+ let showMinGuid = false
253
+
286
254
  logger.info(`Querying attribute rules logs for ${parameters.service} in the past ${mins} minutes...`)
287
- let result= await adminLog.query([102003], services, pageSize, startTime ,endTime , "DEBUG")
288
- let jsonRes = await result.json()
289
- let allMessages = [].concat(jsonRes.logMessages)
290
-
291
- while (jsonRes.hasMore && jsonRes.endTime > startTime)
292
- {
293
- //start paging
294
- logger.info(`Aggregating messages... total so far ${allMessages.length} debug entries but more left, pulling logs before ${new Date(jsonRes.endTime)}`)
295
-
296
-
297
- result= await adminLog.query([102003], services, pageSize, jsonRes.endTime )
298
- jsonRes = await result.json()
299
- allMessages = allMessages.concat(jsonRes.logMessages)
300
- }
255
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule execution complete:", "DEBUG")
301
256
 
302
- const arMessages = allMessages
257
+
258
+ const arMessages = filterMessages(allMessages)
303
259
  .filter(m => m.message.indexOf("Attribute rule execution complete:") > -1)
304
260
  .map (m => JSON.parse(m.message.replace("Attribute rule execution complete:", "")))
305
261
  .map( m => {
@@ -370,7 +326,8 @@ async function loadAttributeRules () {
370
326
  │ Min execution time (m
371
327
 
372
328
  */
373
-
329
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
330
+
374
331
  const header = document.createElement("tr");
375
332
  const cAttributeRule = document.createElement("th");
376
333
  cAttributeRule.textContent = "Attribute Rule"
@@ -435,52 +392,51 @@ async function loadAttributeRules () {
435
392
  }
436
393
  async function loadSQLLogs () {
437
394
 
438
- //build table
439
- const tblResult = document.getElementById("tblResult");
440
- //clear
441
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
442
- tblResult.appendChild(document.createTextNode("Loading...."));
395
+ //build table
396
+ const tblResult = document.getElementById("tblResult");
397
+ //clear
398
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
399
+
443
400
 
401
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
402
+
403
+
404
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
444
405
 
445
- parameters.service = cmbService.options[cmbService.selectedIndex].text
446
-
447
- //create a new admin object (user might not be admin we won't use it until the user call log )
448
- adminLog = new AdminLog(token, portal.serverUrl)
449
-
450
- logger.info("Connected.")
406
+
407
+ console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
451
408
 
409
+ //startTime is the most recent
410
+ //endTime is the oldest
452
411
 
453
- const topLogCount = 1000;
454
- const pageSize = 10000
412
+
413
+ //page query the admin log
414
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102023], "EndCursor;", "DEBUG")
455
415
 
456
- let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
457
416
 
458
-
459
- console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
460
- const startTime = Date.now() - mins*60*1000
461
- const endTime = Date.now();
462
- let services = [parameters.service+ ".MapServer"]
463
- if (parameters.service == "(All Services)")
464
- services = "*"
465
- let result= await adminLog.query([102023], services, topLogCount, startTime ,endTime , "DEBUG")
466
- let jsonRes = await result.json()
467
- let allMessages = [].concat(jsonRes.logMessages)
468
- allMessages = allMessages.filter(m => m.message.indexOf("EndCursor;") > -1)
469
- while (jsonRes.hasMore)
470
- {
471
- //start paging
472
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs before ${new Date(jsonRes.endTime)}`)
473
- result= await adminLog.query([102023], services, pageSize, jsonRes.endTime, null, "DEBUG")
474
- jsonRes = await result.json()
475
-
476
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
477
- }
478
417
  console.log ("Filtering messages...")
479
418
 
480
- allMessages = allMessages
419
+ allMessages = filterMessages(allMessages)
481
420
  .map( m=> {
482
- m.dataAccessElapsed = parseFloat(m.message.split(";")[1].split(" ")[1])
483
- m.executeQueryElapsed = parseFloat(m.message.split(";")[2].split(" ")[1])
421
+ m.dataAccessElapsed =0;
422
+ m.executeQueryElapsed = 0;
423
+ const sDataAccess = "DataAccess "
424
+ const idxDataAccess = m.message.indexOf(sDataAccess)
425
+ if (idxDataAccess >=0) {
426
+ const idxNext = m.message.indexOf(" ",idxDataAccess + sDataAccess.length )
427
+ m.dataAccessElapsed = parseInt(m.message.substr( idxDataAccess + sDataAccess.length, idxNext - idxDataAccess - sDataAccess.length))
428
+ }
429
+
430
+ const sExecuteQuery = "ExecuteQuery "
431
+ const idxExecuteQuery = m.message.indexOf(sExecuteQuery)
432
+ if (idxExecuteQuery >=0) {
433
+ const idxNext = m.message.indexOf(" ",idxExecuteQuery + sExecuteQuery.length)
434
+ m.executeQueryElapsed = parseInt(m.message.substr( idxExecuteQuery + sExecuteQuery.length, idxNext - idxExecuteQuery - sExecuteQuery.length))
435
+ }
436
+
437
+
438
+ //m.dataAccessElapsed = parseFloat(m.message.split(";")[1].split(" ")[1])
439
+ //m.executeQueryElapsed = parseFloat(m.message.split(";")[2].split(" ")[1])
484
440
  m.totalExecutionElapsed = m.dataAccessElapsed + m.executeQueryElapsed
485
441
  m.elapsed = parseFloat(m.elapsed); return m;
486
442
 
@@ -489,20 +445,22 @@ tblResult.appendChild(document.createTextNode("Loading...."));
489
445
  .slice(0, 100) ;//first 100
490
446
 
491
447
 
492
- console.log("-----Top 10 SQL----")
448
+ console.log("-----Top SQL----")
493
449
  while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
494
450
 
495
451
  let i =0;
496
452
 
497
453
  const header = document.createElement("tr");
454
+ const thead = docuemnt.createElement("thead")
455
+ thead.appendChild(header)
498
456
  const cService = document.createElement("th");
499
457
  cService.textContent = "Source"
500
458
  const cTime = document.createElement("th");
501
459
  cTime.textContent = "Time"
502
460
  const cUser = document.createElement("th");
503
461
  cUser.textContent = "User"
504
- const cMethod = document.createElement("th");
505
- cMethod.textContent = "Method"
462
+ const cVersion = document.createElement("th");
463
+ cVersion.textContent = "Version"
506
464
  const cQueryTime = document.createElement("th");
507
465
  cQueryTime.textContent = "Query Time (ms)"
508
466
  cQueryTime.title = "includes search + data access nextRow"
@@ -514,7 +472,7 @@ tblResult.appendChild(document.createTextNode("Loading...."));
514
472
  header.appendChild (cService)
515
473
  header.appendChild (cTime)
516
474
  header.appendChild (cUser)
517
- header.appendChild (cMethod)
475
+ header.appendChild (cVersion)
518
476
  header.appendChild (cQueryTime)
519
477
  header.appendChild (cTotalTime)
520
478
  header.appendChild (cLog)
@@ -544,21 +502,32 @@ tblResult.appendChild(document.createTextNode("Loading...."));
544
502
 
545
503
  const cUser = document.createElement("td");
546
504
  cUser.textContent = m.user
547
- const cMethod = document.createElement("td");
548
- cMethod.textContent = "Cursor"
505
+ const cVersion = document.createElement("td");
506
+ const idxVersion = m.message.indexOf("Version: ")
507
+ if (idxVersion >=0) {
508
+ const idxNext = m.message.indexOf(";",idxVersion)
509
+ cVersion.textContent = m.message.substr( idxVersion + 9, idxNext - idxVersion - 9 )
510
+ }
549
511
  const cQueryTime = document.createElement("td");
550
512
  cQueryTime.textContent = numberWithCommas(m.totalExecutionElapsed)
551
513
  const cTotalTime = document.createElement("td");
552
514
  cTotalTime.textContent = numberWithCommas(Math.round(m.elapsed*1000))
553
515
  const cLog = document.createElement("td");
554
- cLog.textContent = m.message.substr( m.message.indexOf("SQL: ") + 5, 50) + "..."
516
+ const cLogText = document.createElement("input")
517
+ cLogText.type = "text"
518
+ cLogText.style = "width:800px"
519
+ cLogText.value = m.message.substr( m.message.indexOf("SQL: ") + 5, m.message.length)
520
+ cLogText.readOnly= true;
521
+ cLog.appendChild(cLogText)
522
+ //cLog.textContent = m.message.substr( m.message.indexOf("SQL: ") + 5, 50) + "..."
555
523
  cLog.fullLog = m.message;
556
524
  cLog.title = m.message + "\nClick to copy"
557
- cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
525
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
526
+ /* alert("Copied to clipboard") */})
558
527
  logRow.appendChild (cService)
559
528
  logRow.appendChild (cTime)
560
529
  logRow.appendChild (cUser)
561
- logRow.appendChild (cMethod)
530
+ logRow.appendChild (cVersion)
562
531
  logRow.appendChild (cQueryTime)
563
532
  logRow.appendChild (cTotalTime)
564
533
  logRow.appendChild (cLog)
@@ -567,12 +536,6 @@ tblResult.appendChild(document.createTextNode("Loading...."));
567
536
 
568
537
  })
569
538
 
570
-
571
-
572
-
573
-
574
-
575
-
576
539
  //await populateMessages(allMessages)
577
540
 
578
541
 
@@ -584,30 +547,50 @@ function numberWithCommas(x) {
584
547
  return x.toLocaleString()
585
548
  }
586
549
 
587
- init();
550
+ //init();
588
551
 
589
552
  const btnTraceLogs = document.getElementById("btnTraceLogs");
590
553
  btnTraceLogs.addEventListener("click", e => loadTraceLogs())
554
+ btnTraceLogs.disabled = true
591
555
 
592
556
  const btnValidateLogs = document.getElementById("btnValidateLogs");
593
557
  btnValidateLogs.addEventListener("click", e => loadValidateLogs())
558
+ btnValidateLogs.disabled = true
594
559
 
595
560
  const btnUpdateSubnetworkLogs = document.getElementById("btnUpdateSubnetworkLogs");
596
561
  btnUpdateSubnetworkLogs.addEventListener("click", e => loadUpdateSubnetworkLogs())
597
-
562
+ btnUpdateSubnetworkLogs.disabled = true
563
+
598
564
  const btnSQLLogs = document.getElementById("btnSQLLogs");
599
565
  btnSQLLogs.addEventListener("click", e => loadSQLLogs())
600
-
566
+ btnSQLLogs.disabled = true
567
+
601
568
  const btnAR = document.getElementById("btnAR");
602
569
  btnAR.addEventListener("click", e => loadAttributeRules())
603
-
604
-
570
+ btnAR.disabled = true
571
+
572
+ function filterMessages (allMessages) {
573
+ const txtFilter = document.getElementById("txtFilter")
574
+ const txtUser = document.getElementById("txtUser")
575
+ if (txtFilter.value == "" && txtUser.value == "") return allMessages;
576
+ //const filtered= allMessages.filter(m => m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) > 0 && m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) > 0)
577
+ const filtered= allMessages.filter(m => {
578
+
579
+ if (m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) >= 0
580
+ &&
581
+ m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) >= 0)
582
+ return true
583
+
584
+ return false
585
+ })
586
+ return filtered
587
+ }
605
588
 
606
589
  async function populateMessages(allTheMessages) {
607
590
 
608
591
  //sort messages
609
592
 
610
- const allMessages = allTheMessages.map(m => {
593
+ const allMessages = filterMessages (allTheMessages).map(m => {
611
594
  const newMessage = Object.assign({}, m);
612
595
  delete newMessage.machine;
613
596
  delete newMessage.type;
@@ -672,6 +655,60 @@ function numberWithCommas(x) {
672
655
  tblResult.appendChild(logRow)
673
656
  })
674
657
  }
658
+
659
+
660
+ async function adminLogQueryWithPaging(mins, theService, code, filter, level){
661
+ const topLogCount = 1000;
662
+ let stop = false;
663
+ const prg = document.createTextNode("Loading.... 0%");
664
+ const btn = document.createElement("button")
665
+ btn.textContent = '🛑'
666
+ btn.addEventListener("click", ()=> stop = true )
667
+ //create a new admin object (user might not be admin we won't use it until the user call log )
668
+ let adminLog = new AdminLog(token, portal.serverUrl)
669
+ tblResult.appendChild(prg);
670
+ tblResult.appendChild(btn)
671
+ const startTime = Date.now()
672
+ const endTime = Date.now() - mins*60*1000
673
+ let services = [theService + ".MapServer"]
674
+ if (theService == "(All Services)")
675
+ services = "*"
676
+ let result= await adminLog.query(code, services, topLogCount, startTime ,endTime , level)
677
+ let jsonRes = await result.json()
678
+ let allMessages = [].concat(jsonRes.logMessages)
679
+ allMessages = allMessages.filter(m => m.message.indexOf(filter) > -1)
680
+ while (jsonRes.hasMore && !stop)
681
+ {
682
+ //start paging
683
+ prg.textContent = "Loading ... " + parseInt((( (startTime - endTime) - (jsonRes.endTime - endTime) ) /((startTime - endTime)))*100) + "%"
684
+ logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
685
+ result= await adminLog.query(code, services, topLogCount, jsonRes.endTime, endTime, level)
686
+ jsonRes = await result.json()
687
+
688
+ allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf(filter) > -1))
689
+ }
690
+
691
+ return allMessages
692
+
693
+ }
694
+
695
+
696
+
697
+ function sortTable(table, col, reverse) {
698
+ var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
699
+ tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
700
+ i;
701
+ reverse = -((+reverse) || -1);
702
+ tr = tr.sort(function (a, b) { // sort rows
703
+ return reverse // `-1 *` if want opposite order
704
+ * (a.cells[col].textContent.trim() // using `.textContent.trim()` for test
705
+ .localeCompare(b.cells[col].textContent.trim())
706
+ );
707
+ });
708
+ for(i = 0; i < tr.length; ++i) tb.appendChild(tr[i]); // append each row in order
709
+ }
710
+
711
+
675
712
  </script>
676
713
  </body>
677
714
  </html>
package/index.mjs CHANGED
@@ -7,7 +7,7 @@ import { AdminLog } from "./adminlog.mjs"
7
7
  import logger from "./logger.mjs"
8
8
  import fetch from "node-fetch"
9
9
  //update version
10
- let version = "0.0.71";
10
+ let version = "0.0.74";
11
11
  const GENERATE_TOKEN_TIME_MIN = 30;
12
12
 
13
13
  let rl = null;
@@ -53,10 +53,10 @@ function parseInput(){
53
53
 
54
54
  if (Object.values(params).includes(null))
55
55
  {
56
- console.log ("HELP: uncli --portal https://unportal.domain.com/portal --service servicename --user username --password password [--gdbversion* user.version --server https://federatedserver.domain.com/server --file commandfile* --verify true|false]")
57
- console.log("--file commandfile is optional and you can pass a path to a file with a list of command to execute. ")
58
- console.log("--gdbversion is optional and allows the UN to be opened in that version. When not specified sde.DEFAULT is used.")
59
- console.log("--server is optional except when there are more than one federated server sites to the portal. If the portal only has one server it will be selected.")
56
+ logger.info ("HELP: uncli --portal https://unportal.domain.com/portal --service servicename --user username --password password [--gdbversion* user.version --server https://federatedserver.domain.com/server --file commandfile* --verify true|false]")
57
+ logger.info("--file commandfile is optional and you can pass a path to a file with a list of command to execute. ")
58
+ logger.info("--gdbversion is optional and allows the UN to be opened in that version. When not specified sde.DEFAULT is used.")
59
+ logger.info("--server is optional except when there are more than one federated server sites to the portal. If the portal only has one server it will be selected.")
60
60
  process.exit();
61
61
  }
62
62
 
@@ -73,7 +73,7 @@ async function getToken(parameters) {
73
73
  }
74
74
 
75
75
  async function regenerateToken(parameters) {
76
- console.log("Regenerating token.")
76
+ logger.info("Regenerating token.")
77
77
  const token = await getToken(parameters);
78
78
  un.token = token;
79
79
  executeInput("clear");
@@ -193,7 +193,7 @@ const inputs = {
193
193
  },
194
194
  "^whoami$": async () => {
195
195
 
196
- console.log(`${parameters.user}@${parameters.service}@${parameters.gdbversion}`)
196
+ logger.info(`${parameters.user}@${parameters.service}@${parameters.gdbversion}`)
197
197
 
198
198
  },
199
199
  "^def --layers$|^layers$": async () => {
@@ -231,20 +231,20 @@ const inputs = {
231
231
 
232
232
  const subnetworks = await un.getSubnetworks();
233
233
  if (subnetworks.features.length === 0) {
234
- console.log("No dirty subnetworks found.")
234
+ logger.info("No dirty subnetworks found.")
235
235
  return;
236
236
  }
237
237
  const subs = subnetworks.features.map(a => a.attributes)
238
238
  console.table(subs)
239
239
  const rowCount = subs.length;
240
- console.log (`${numberWithCommas(rowCount)} rows returned.`)
240
+ logger.info (`${numberWithCommas(rowCount)} rows returned.`)
241
241
  },
242
242
  "^topology$": async () => {
243
243
  const moments = ["initialEnableTopology","fullValidateTopology","partialValidateTopology","enableTopology","disableTopology","definitionModification","updateIsConnected"]
244
244
  const networkMoments = await un.queryMoment(moments)
245
245
  // networkMoments.forEach (m => momentsText += `\n${m.moment} : ${m.time === 0 ? "N/A": new Date(m.time*1000)} ${m.duration === 0 ? "" : ` Duration: ${Math.round(m.duration/1000)}s `} `)
246
246
  // networkMoments.forEach (m => momentsText += `\n${m.moment} : ${m.time === 0 ? "N/A": new Date(m.time*1000)} ${m.duration === 0 ? "" : ` Duration: ${Math.round(m.duration/1000)}s `} `)
247
- // console.log('\x1b[36m%s\x1b[0m', 'I am cyan'); //cyan
247
+ // logger.info('\x1b[36m%s\x1b[0m', 'I am cyan'); //cyan
248
248
  const topoMoments = networkMoments.networkMoments.map(m => {
249
249
  const t = m.time === 0 ? "N/A": new Date(m.time*1000)
250
250
  const d = m.duration === 0 ? "N/A" : numberWithCommas(Math.round(m.duration)) + " ms"
@@ -260,7 +260,7 @@ const inputs = {
260
260
  console.table(topoMoments)
261
261
  },
262
262
  "^topology --enable$": async () => {
263
- console.log("Enabling topology ...");
263
+ logger.info("Enabling topology ...");
264
264
  const fromDate = new Date();
265
265
  const result = await un.enableTopology()
266
266
  const toDate = new Date();
@@ -270,7 +270,7 @@ const inputs = {
270
270
  },
271
271
  "^topology --disable$": async () => {
272
272
  const fromDate = new Date();
273
- console.log("Disabling topology ...");
273
+ logger.info("Disabling topology ...");
274
274
  const result = await un.disableTopology()
275
275
  const toDate = new Date();
276
276
  const timeEnable = toDate.getTime() - fromDate.getTime();
@@ -279,25 +279,25 @@ const inputs = {
279
279
  },
280
280
  "^evaluate$": async () => {
281
281
  const fromDate = new Date();
282
- console.log("Building Evaluation Blocks ...");
282
+ logger.info("Building Evaluation Blocks ...");
283
283
  //return evaluation blocks for layer 5
284
284
  const blocks = await buildEvaluationBlocks(5);
285
285
 
286
- console.log("Evaluating Attribute Rules ...");
286
+ logger.info("Evaluating Attribute Rules ...");
287
287
  //blocks.forEach(b => un.evaluate (null, b, ["validationRules", "calculationRules"], async = false, gdbVersion = "sde.DEFAULT"))
288
- //Object.keys(blocks).forEach(k => console.log(blocks[k]))
288
+ //Object.keys(blocks).forEach(k => logger.info(blocks[k]))
289
289
  const promises = []
290
290
  Object.keys(blocks).forEach(k => promises.push(un.evaluate (null, blocks[k], ["validationRules", "calculationRules"] )))
291
291
 
292
- console.log("done sending all requests.. now waiting for response ")
292
+ logger.info("done sending all requests.. now waiting for response ")
293
293
 
294
- Promise.all(promises).then(a=>console.log("done")).catch(a=>console.log("failed" + JSON.stringify(a)))
294
+ Promise.all(promises).then(a=>logger.info("done")).catch(a=>logger.info("failed" + JSON.stringify(a)))
295
295
 
296
296
  const result = {}
297
297
  const toDate = new Date();
298
298
  const timeEnable = toDate.getTime() - fromDate.getTime();
299
299
  result.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
300
- console.log(result)
300
+ logger.info(result)
301
301
  },
302
302
 
303
303
  //partition so that we can run and commit incrementally..
@@ -305,7 +305,7 @@ const inputs = {
305
305
  //timeouts
306
306
  //in case failure you don't lose everything
307
307
  "^topology --validate -fn$": async () => {
308
- console.log("Validating Network topology ...");
308
+ logger.info("Validating Network topology ...");
309
309
 
310
310
  const fullExtent = un.featureServiceJson.fullExtent;
311
311
  /*
@@ -343,7 +343,7 @@ const inputs = {
343
343
  const timeEnable = toDate.getTime() - fromDate.getTime();
344
344
  const duration = numberWithCommas(Math.round(timeEnable)) + " ms"
345
345
  console.clear()
346
- console.log("Validating extent " + e.xmin)
346
+ logger.info("Validating extent " + e.xmin)
347
347
  console.table({duration})
348
348
 
349
349
  })
@@ -352,7 +352,7 @@ const inputs = {
352
352
  },
353
353
 
354
354
  "^topology --validate$": async () => {
355
- console.log("Validating Network topology ...");
355
+ logger.info("Validating Network topology ...");
356
356
  const fromDate = new Date();
357
357
  const result = await un.validateNetworkTopology()
358
358
  const toDate = new Date();
@@ -363,35 +363,35 @@ const inputs = {
363
363
  "^subnetworks --dirty$": async () => {
364
364
  const subnetworks = await un.getSubnetworks("isdirty=1");
365
365
  if (subnetworks.features.length === 0) {
366
- console.log("No dirty subnetworks found.")
366
+ logger.info("No dirty subnetworks found.")
367
367
  return;
368
368
  }
369
369
 
370
370
  const subs = subnetworks.features.map(a => a.attributes)
371
371
  console.table(subs)
372
372
  const rowCount = subs.length;
373
- console.log (`${numberWithCommas(rowCount)} rows returned.`)
373
+ logger.info (`${numberWithCommas(rowCount)} rows returned.`)
374
374
  },
375
375
  "^subnetworks --deleted$": async () => {
376
376
  const subnetworks = await un.getSubnetworks("isdirty=1 and isdeleted=1");
377
377
  if (subnetworks.features.length === 0) {
378
- console.log("No dirty and deleted subnetworks found.")
378
+ logger.info("No dirty and deleted subnetworks found.")
379
379
  return;
380
380
  }
381
381
 
382
382
  const subs = subnetworks.features.map(a => a.attributes)
383
383
  console.table(subs)
384
384
  const rowCount = subs.length;
385
- console.log (`${numberWithCommas(rowCount)} rows returned.`)
385
+ logger.info (`${numberWithCommas(rowCount)} rows returned.`)
386
386
  },
387
387
 
388
388
  "^update subnetworks --deleted$" : async () => {
389
- console.log("Querying all subnetworks that are dirty and deleted.");
389
+ logger.info("Querying all subnetworks that are dirty and deleted.");
390
390
  let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=1 and isdeleted=1","domainnetworkname,tiername,subnetworkname");
391
- console.log(`Discovered ${subnetworks.features.length} dirty deleted subnetworks.`);
391
+ logger.info(`Discovered ${subnetworks.features.length} dirty deleted subnetworks.`);
392
392
  for (let i = 0; i < subnetworks.features.length; i++) {
393
393
  const f = subnetworks.features[i]
394
- console.log("Updating Subnetwork " + v(f.attributes,"subnetworkName"));
394
+ logger.info("Updating Subnetwork " + v(f.attributes,"subnetworkName"));
395
395
 
396
396
  const fromDate = new Date();
397
397
 
@@ -404,35 +404,46 @@ const inputs = {
404
404
  subnetworkResult.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
405
405
 
406
406
 
407
- console.log(`Result ${JSON.stringify(subnetworkResult)}`)
407
+ logger.info(`Result ${JSON.stringify(subnetworkResult)}`)
408
408
  }
409
409
  },
410
410
 
411
411
  "^update subnetworks --all" : async input => {
412
412
 
413
413
  let subnetworks;
414
+ let more = false;
415
+ let failedSubnetworks = []
414
416
  do {
415
417
 
416
418
  let sort = "asc";
417
419
  if (input.indexOf("--desc") > 0) sort = "desc"
420
+ let failedSubWhereClause = ""
421
+
422
+ if (failedSubnetworks.length > 0 )
423
+ failedSubWhereClause = " AND SUBNETWORKNAME NOT IN (" + failedSubnetworks.join(",") + ")"
418
424
 
419
- console.log("Querying all subnetworks that are dirty.");
420
- subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=1", `domainnetworkname ${sort},tiername ${sort},subnetworkname ${sort}`);
421
- console.log(`Discovered ${subnetworks.features.length} dirty subnetworks.`);
425
+ logger.info("Querying all subnetworks that are dirty.");
426
+ subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=1 " + failedSubWhereClause, `domainnetworkname ${sort},tiername ${sort},subnetworkname ${sort}`);
427
+ logger.info(`Discovered ${subnetworks.features.length} dirty subnetworks.`);
422
428
 
423
429
  for (let i = 0; i < subnetworks.features.length; i++) {
424
430
  const f = subnetworks.features[i]
425
- console.log("Updating Subnetwork " + v(f.attributes,"subnetworkName"));
431
+ const subnetworkName = v(f.attributes,"subnetworkName")
432
+ logger.info("Updating Subnetwork " + subnetworkName);
426
433
 
427
434
  const fromDate = new Date();
428
435
 
429
436
  const subnetworkResult = await un.updateSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
430
-
437
+ //check if we have processed this subnetwork (maybe be an error)
438
+ const tier = un.getTier(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"))
439
+ if (subnetworkResult.success == false || tier.manageSubnetwork?.propertySetItems?.includes("IsDirty"))
440
+ failedSubnetworks.push("'" + subnetworkName + "'")
441
+
431
442
  const toDate = new Date();
432
443
  const timeEnable = toDate.getTime() - fromDate.getTime();
433
444
  subnetworkResult.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
434
445
 
435
- console.log(`Result ${JSON.stringify(subnetworkResult)}`)
446
+ logger.info(`Result ${JSON.stringify(subnetworkResult)}`)
436
447
  }
437
448
 
438
449
  }
@@ -440,14 +451,14 @@ const inputs = {
440
451
 
441
452
  },
442
453
  "^update subnetworks --all --async$" : async () => {
443
- console.log("Querying all subnetworks that are dirty.");
454
+ logger.info("Querying all subnetworks that are dirty.");
444
455
  let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=1", "domainnetworkname,tiername,subnetworkname");
445
- console.log(`Discovered ${subnetworks.features.length} dirty subnetworks.`);
456
+ logger.info(`Discovered ${subnetworks.features.length} dirty subnetworks.`);
446
457
  for (let i = 0; i < subnetworks.features.length; i++) {
447
458
  const f = subnetworks.features[i]
448
- console.log("Sending job for " + v(f.attributes,"subnetworkName"));
459
+ logger.info("Sending job for " + v(f.attributes,"subnetworkName"));
449
460
  const subnetworkResult = await un.updateSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),true);
450
- console.log(`Result from submitting job ${JSON.stringify(subnetworkResult)}`)
461
+ logger.info(`Result from submitting job ${JSON.stringify(subnetworkResult)}`)
451
462
  }
452
463
  },
453
464
  "^export subnetworks --all --folder .*$|^export subnetworks --all$" : async input => {
@@ -460,33 +471,40 @@ const inputs = {
460
471
  inputDir = file[0].replace("--folder ", "")
461
472
  //create directory if doesn't exists
462
473
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
463
-
474
+ let exportedSubnetworks = [];
475
+
464
476
  do {
465
477
 
466
- console.log("Querying all subnetworks that are clean.");
467
- subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=0","domainnetworkname,tiername,subnetworkname");
468
- console.log(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
478
+ let exportedSubnetworksWhereClause = ""
479
+
480
+ if (exportedSubnetworks.length > 0 )
481
+ exportedSubnetworksWhereClause = " AND SUBNETWORKNAME NOT IN (" + exportedSubnetworks.join(",") + ")"
482
+
483
+ logger.info("Querying all subnetworks that are clean.");
484
+ subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=0 " + exportedSubnetworksWhereClause,"domainnetworkname,tiername,subnetworkname");
485
+ logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
469
486
  for (let i = 0; i < subnetworks.features.length; i++) {
470
487
  const f = subnetworks.features[i]
471
488
  const subnetworkName = v(f.attributes,"subnetworkName")
472
- console.log("Exporting subnetworks " + v(f.attributes,"subnetworkName"));
489
+ logger.info("Exporting subnetworks " + v(f.attributes,"subnetworkName"));
473
490
 
474
491
  const fromDate = new Date();
475
492
 
476
493
  const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
477
-
478
-
494
+
479
495
  //code
480
-
496
+ exportedSubnetworks.push("'" + v(f.attributes,"subnetworkName") + "'")
497
+
481
498
  const toDate = new Date();
482
499
  const timeEnable = toDate.getTime() - fromDate.getTime();
483
500
  subnetworkResult.duration = numberWithCommas(timeEnable) + " ms"
484
501
  //if undefined exit
485
502
  if (!subnetworkResult.url)
486
503
  {
487
- console.log("Export subnetwork failed " + JSON.stringify(subnetworkResult))
504
+ logger.info("Export subnetwork failed " + JSON.stringify(subnetworkResult))
488
505
  continue;
489
506
  }
507
+
490
508
 
491
509
  //fetch the json and write it to disk
492
510
  const subContent = await fetch(subnetworkResult.url);
@@ -497,11 +515,11 @@ const inputs = {
497
515
  fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, jsonExport)
498
516
 
499
517
 
500
- console.log(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
518
+ logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
501
519
 
502
520
  }
503
521
  }
504
- while (subnetworks.features.length > 0)
522
+ while (subnetworks?.features?.length > 0)
505
523
 
506
524
  },
507
525
 
@@ -517,20 +535,20 @@ const inputs = {
517
535
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
518
536
 
519
537
 
520
- console.log("Querying all subnetworks that are clean and not exported.");
538
+ logger.info("Querying all subnetworks that are clean and not exported.");
521
539
  let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty = 0 and (LASTACKEXPORTSUBNETWORK is null or LASTACKEXPORTSUBNETWORK < LASTUPDATESUBNETWORK)","domainnetworkname,tiername,subnetworkname");
522
- console.log(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
540
+ logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
523
541
  for (let i = 0; i < subnetworks.features.length; i++) {
524
542
  const f = subnetworks.features[i]
525
543
  const subnetworkName = v(f.attributes,"subnetworkName")
526
- console.log(`Exporting subnetwork ${subnetworkName}` );
544
+ logger.info(`Exporting subnetwork ${subnetworkName}` );
527
545
  const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
528
546
  //fetch the json and write it to disk
529
547
  const subContent = await fetch(subnetworkResult.url);
530
548
  const jsonExport = await subContent.text();
531
549
  fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, JSON.stringify(jsonExport))
532
550
 
533
- console.log(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
551
+ logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
534
552
  }
535
553
 
536
554
 
@@ -540,7 +558,7 @@ const inputs = {
540
558
  "^ia$": async input => {
541
559
 
542
560
  const result = await un.returnInvalidAssociations();
543
- console.log("Invalid Associations " + JSON.stringify(result))
561
+ logger.info("Invalid Associations " + JSON.stringify(result))
544
562
  },
545
563
  "^connect --service": async input =>{
546
564
 
@@ -563,10 +581,10 @@ const inputs = {
563
581
  if (inputParam != null && inputParam.length > 0)
564
582
  subnetworkName = inputParam[0].replace("--subnetwork ", "")
565
583
 
566
- console.log(`Tracing subnetwork ${subnetworkName}`);
584
+ logger.info(`Tracing subnetwork ${subnetworkName}`);
567
585
  const result = await un.subnetworkTraceSimple(subnetworkName)
568
586
  if (result == null) {
569
- console.log(`Subnetwork ${subnetworkName} doesn't exist`);
587
+ logger.info(`Subnetwork ${subnetworkName} doesn't exist`);
570
588
  return null;
571
589
  }
572
590
  const toDate = new Date();
@@ -588,19 +606,19 @@ const inputs = {
588
606
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
589
607
 
590
608
 
591
- console.log("Querying all subnetworks that are clean and deleted.");
609
+ logger.info("Querying all subnetworks that are clean and deleted.");
592
610
  let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty = 0 and isdeleted=1");
593
- console.log(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
611
+ logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
594
612
  for (let i = 0; i < subnetworks.features.length; i++) {
595
613
  const f = subnetworks.features[i]
596
614
  const subnetworkName = v(f.attributes,"subnetworkName")
597
- console.log(`Exporting subnetwork ${subnetworkName}` );
615
+ logger.info(`Exporting subnetwork ${subnetworkName}` );
598
616
  const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
599
617
 
600
618
  //if undefined exit
601
619
  if (!subnetworkResult.url)
602
620
  {
603
- console.log("Export subnetwork failed " + JSON.stringify(subnetworkResult))
621
+ logger.info("Export subnetwork failed " + JSON.stringify(subnetworkResult))
604
622
  continue;
605
623
  }
606
624
 
@@ -609,7 +627,7 @@ const inputs = {
609
627
  const jsonExport = await subContent.text();
610
628
  fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, JSON.stringify(jsonExport))
611
629
 
612
- console.log(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
630
+ logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
613
631
  }
614
632
 
615
633
 
@@ -618,7 +636,7 @@ const inputs = {
618
636
  "^cwd$" : async input => {
619
637
 
620
638
 
621
- console.log(process.cwd())
639
+ logger.info(process.cwd())
622
640
 
623
641
  },
624
642
 
@@ -630,14 +648,14 @@ const inputs = {
630
648
  //create directory if doesn't exists
631
649
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
632
650
  fs.writeFileSync(`${inputDir}/${Math.random()}`, Math.random())
633
- console.log(inputDir)
651
+ logger.info(inputDir)
634
652
 
635
653
 
636
654
  },
637
655
 
638
656
 
639
657
  "^count$": async () => {
640
- console.log("Querying all layers....")
658
+ logger.info("Querying all layers....")
641
659
  const layerProperties = [
642
660
  "id",
643
661
  "name",
@@ -671,12 +689,12 @@ const inputs = {
671
689
 
672
690
 
673
691
  console.table(layerCount)
674
- console.log(`Total number of rows in all layers : ${numberWithCommas(totalRows)} .`)
692
+ logger.info(`Total number of rows in all layers : ${numberWithCommas(totalRows)} .`)
675
693
  },
676
694
 
677
695
 
678
696
  "^count --system$": async () => {
679
- console.log("Querying all system layers....")
697
+ logger.info("Querying all system layers....")
680
698
 
681
699
  const systemLayers = un.getSystemLayers();
682
700
  let totalRows = 0;
@@ -699,7 +717,7 @@ const inputs = {
699
717
  }
700
718
 
701
719
  console.table(layerCount)
702
- console.log(`Total number of rows in all system layers : ${numberWithCommas(totalRows)} .`)
720
+ logger.info(`Total number of rows in all system layers : ${numberWithCommas(totalRows)} .`)
703
721
 
704
722
  },
705
723
 
@@ -714,7 +732,7 @@ const inputs = {
714
732
  mins = inputParam[0].replace("--age ", "")
715
733
 
716
734
 
717
- console.log(`Querying attribute rules logs for ${parameters.service} for the last ${mins} minutes ...`)
735
+ logger.info(`Querying attribute rules logs for ${parameters.service} for the last ${mins} minutes ...`)
718
736
 
719
737
  const startTime = Date.now() - mins*60*1000
720
738
  const endTime = Date.now();
@@ -764,7 +782,7 @@ const inputs = {
764
782
  if (inputParam != null && inputParam.length > 0)
765
783
  mins = inputParam[0].replace("--age ", "")
766
784
 
767
- console.log(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
785
+ logger.info(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
768
786
  const startTime = Date.now() - mins*60*1000
769
787
  const endTime = Date.now();
770
788
  let result= await adminLog.query([102002], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "VERBOSE")
@@ -805,7 +823,7 @@ const inputs = {
805
823
  delete newMessage.message
806
824
 
807
825
  console.table([newMessage])
808
- console.log(m.message)
826
+ logger.info(m.message)
809
827
  })
810
828
 
811
829
  },
@@ -823,7 +841,7 @@ const inputs = {
823
841
  mins = inputParam[0].replace("--age ", "")
824
842
 
825
843
 
826
- console.log(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
844
+ logger.info(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
827
845
  const startTime = Date.now() - mins*60*1000
828
846
  const endTime = Date.now();
829
847
  let result= await adminLog.query([102003], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "VERBOSE")
@@ -888,7 +906,7 @@ const inputs = {
888
906
  delete newMessage.message
889
907
 
890
908
  console.table([newMessage])
891
- console.log(m.message)
909
+ logger.info(m.message)
892
910
  })
893
911
 
894
912
 
@@ -907,7 +925,7 @@ const inputs = {
907
925
  if (inputParam != null && inputParam.length > 0)
908
926
  mins = inputParam[0].replace("--age ", "")
909
927
 
910
- console.log(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
928
+ logger.info(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
911
929
  const startTime = Date.now() - mins*60*1000
912
930
  const endTime = Date.now();
913
931
  let result= await adminLog.query([102003], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "VERBOSE")
@@ -972,7 +990,7 @@ const inputs = {
972
990
  delete newMessage.message
973
991
 
974
992
  console.table([newMessage])
975
- console.log(m.message)
993
+ logger.info(m.message)
976
994
  })
977
995
 
978
996
 
@@ -989,7 +1007,7 @@ const inputs = {
989
1007
  if (inputParam != null && inputParam.length > 0)
990
1008
  mins = inputParam[0].replace("--age ", "")
991
1009
 
992
- console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
1010
+ logger.info(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
993
1011
  const startTime = Date.now() - mins*60*1000
994
1012
  const endTime = Date.now();
995
1013
  let result= await adminLog.query([102023], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "DEBUG")
@@ -1005,7 +1023,7 @@ const inputs = {
1005
1023
 
1006
1024
  allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
1007
1025
  }
1008
- console.log ("Filtering messages...")
1026
+ logger.info ("Filtering messages...")
1009
1027
 
1010
1028
  allMessages = allMessages
1011
1029
  .map( m=> {
@@ -1019,21 +1037,21 @@ const inputs = {
1019
1037
  .slice(0, 10) ;//first 10
1020
1038
 
1021
1039
 
1022
- console.log("-----Top 10 SQL----")
1040
+ logger.info("-----Top 10 SQL----")
1023
1041
  let i =0;
1024
1042
  allMessages= allMessages.forEach(m =>
1025
1043
  {
1026
1044
 
1027
1045
  const x = m.message.split(";")
1028
1046
  x.shift()
1029
- console.log(`id: ${i++}`)
1030
- console.log(`\tAt: ${new Date(m.time)} (${m.time})`)
1031
- console.log(`\tUser: ${m.user}`)
1032
- console.log(`\tTotal Time: ${numberWithCommas(Math.round(m.elapsed*1000))} ms (Total time the cursor was opened)`)
1033
- console.log(`\tQuery Time: ${numberWithCommas(m.totalExecutionElapsed)} ms (includes search + data access nextRow)`)
1034
- console.log(`\tQuery:`)
1035
- x.forEach(a => console.log(`\t${a}`))
1036
- console.log(`\n`)
1047
+ logger.info(`id: ${i++}`)
1048
+ logger.info(`\tAt: ${new Date(m.time)} (${m.time})`)
1049
+ logger.info(`\tUser: ${m.user}`)
1050
+ logger.info(`\tTotal Time: ${numberWithCommas(Math.round(m.elapsed*1000))} ms (Total time the cursor was opened)`)
1051
+ logger.info(`\tQuery Time: ${numberWithCommas(m.totalExecutionElapsed)} ms (includes search + data access nextRow)`)
1052
+ logger.info(`\tQuery:`)
1053
+ x.forEach(a => logger.info(`\t${a}`))
1054
+ logger.info(`\n`)
1037
1055
 
1038
1056
  })
1039
1057
 
@@ -1145,11 +1163,11 @@ const inputs = {
1145
1163
  console.table(rules)
1146
1164
 
1147
1165
  const totalARExecution = rules.reduce( (prev, cur) => prev + cur["Total Cost (ms)"], 0)
1148
- console.log(`Total time spend executing attribute rules (${Math.round(totalARExecution)} ms) (${Math.round(totalARExecution/1000)} s) (${Math.round(totalARExecution/(1000*60))} m)`)
1166
+ logger.info(`Total time spend executing attribute rules (${Math.round(totalARExecution)} ms) (${Math.round(totalARExecution/1000)} s) (${Math.round(totalARExecution/(1000*60))} m)`)
1149
1167
 
1150
1168
  },
1151
1169
 
1152
- "^version$": () => console.log(version),
1170
+ "^version$": () => logger.info(version),
1153
1171
  "^clear$|^cls$": () => console.clear(),
1154
1172
  "^quit$": () => {
1155
1173
  if (rl) rl.close();
@@ -1174,7 +1192,7 @@ const inputs = {
1174
1192
 
1175
1193
  while(true) {
1176
1194
  const result = await un.query(layerId, `1=1`, undefined, undefined, ["globalId"], "sde.DEFAULT", offset, recordCount)
1177
- console.log(`Processing ${recordCount} rows`)
1195
+ logger.info(`Processing ${recordCount} rows`)
1178
1196
  //for each assocaition check if its valid
1179
1197
  for (let i = 0 ; i < result.features.length; i++){
1180
1198
  const row = result.features[i]
@@ -1289,7 +1307,7 @@ function numberWithCommas(x) {
1289
1307
  /*
1290
1308
  rl.question("What is your name ? ", function(name) {
1291
1309
  rl.question("Where do you live ? ", function(country) {
1292
- console.log(`${name}, is a citizen of ${country}`);
1310
+ logger.info(`${name}, is a citizen of ${country}`);
1293
1311
  rl.close();
1294
1312
  });
1295
1313
  });
@@ -1302,7 +1320,7 @@ function setupReadLine() {
1302
1320
  });
1303
1321
 
1304
1322
  rl.on("close", function() {
1305
- console.log("\nbye");
1323
+ logger.info("\nbye");
1306
1324
  process.exit(0);
1307
1325
  });
1308
1326
 
@@ -1324,7 +1342,7 @@ export async function run (){
1324
1342
  console.error(`Minimum required node js is ${minVer} your version is ${process.version}`)
1325
1343
  process.exit(0);
1326
1344
  }
1327
- console.log(`uncli ${version} is experimental command line utility for basic utility network services. Use as is.`)
1345
+ logger.info(`uncli ${version} is experimental command line utility for basic utility network services. Use as is.`)
1328
1346
  parameters = await parseInput( )
1329
1347
  //set certificate verification
1330
1348
  const verifyCert = parameters["verify"] === 'true' ? 1 : 0;
package/logger.mjs CHANGED
@@ -1,9 +1,23 @@
1
1
  const logger = {}
2
- logger.info = console.log
3
- logger.error = console.error
2
+ logger.info = m => console.log (`${shortDate()}: ${m}`)
3
+ logger.error =m => console.error (`${shortDate()}: ${m}`)
4
4
 
5
5
  export default logger;
6
6
 
7
+ function shortDate()
8
+ {
9
+
10
+ const t = new Date();
11
+ const date = ('0' + t.getDate()).slice(-2);
12
+ const month = ('0' + (t.getMonth() + 1)).slice(-2);
13
+ const year = t.getFullYear();
14
+ const hours = ('0' + t.getHours()).slice(-2);
15
+ const minutes = ('0' + t.getMinutes()).slice(-2);
16
+ const seconds = ('0' + t.getSeconds()).slice(-2);
17
+ const time = `${month}/${date}/${year}:${hours}:${minutes}:${seconds}`;
18
+ return time;
19
+ }
20
+
7
21
  /*
8
22
  import winston from "winston"
9
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "un-cli",
3
- "version": "0.0.71",
3
+ "version": "0.0.74",
4
4
  "description": "Command line interface for working with ArcGIS Utility Network Extension",
5
5
  "main": "index.mjs",
6
6
  "bin": {