un-cli 0.0.70 → 0.0.73
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 +246 -179
- package/index.mjs +100 -87
- package/logger.mjs +16 -2
- package/package.json +1 -1
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
|
-
|
|
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 = '
|
|
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,23 +56,42 @@
|
|
|
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
|
-
|
|
62
|
+
let parameters = {
|
|
44
63
|
"user": "unadmin",
|
|
45
|
-
"password": "
|
|
64
|
+
"password": "",
|
|
46
65
|
"portal": "https://utilitynetwork.esri.com/portal",
|
|
47
|
-
"service": "
|
|
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
|
+
|
|
91
|
+
const opt = document.createElement("option")
|
|
92
|
+
opt.textContent = "(All Services)"
|
|
93
|
+
cmbService.appendChild (opt)
|
|
94
|
+
|
|
59
95
|
token = await getToken(parameters);
|
|
60
96
|
const services = await portal.services()
|
|
61
97
|
const featureServices = services.services.filter(s => s.type == "FeatureServer")
|
|
@@ -64,6 +100,20 @@
|
|
|
64
100
|
o.text = s.name;
|
|
65
101
|
cmbService.appendChild(o);
|
|
66
102
|
})
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
document.getElementById("btnTraceLogs").disabled = false
|
|
107
|
+
document.getElementById("btnValidateLogs").disabled = false
|
|
108
|
+
document.getElementById("btnUpdateSubnetworkLogs").disabled = false
|
|
109
|
+
document.getElementById("btnAR").disabled = false
|
|
110
|
+
document.getElementById("btnSQLLogs").disabled = false
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
catch(ex){
|
|
115
|
+
alert(`Failed to login to ${parameters.portal} check the user/password and make sure its an admin`)
|
|
116
|
+
}
|
|
67
117
|
}
|
|
68
118
|
|
|
69
119
|
|
|
@@ -82,42 +132,17 @@
|
|
|
82
132
|
const tblResult = document.getElementById("tblResult");
|
|
83
133
|
//clear
|
|
84
134
|
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
85
|
-
tblResult.appendChild(document.createTextNode("Loading...."));
|
|
86
135
|
|
|
87
136
|
|
|
88
137
|
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
|
-
|
|
138
|
+
|
|
99
139
|
let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
|
|
100
140
|
|
|
101
141
|
console.log(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
142
|
+
|
|
143
|
+
//page query the admin log
|
|
144
|
+
let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102002], "------ Trace Parameters ----", "VERBOSE")
|
|
145
|
+
|
|
121
146
|
await populateMessages(allMessages)
|
|
122
147
|
|
|
123
148
|
|
|
@@ -126,49 +151,23 @@
|
|
|
126
151
|
|
|
127
152
|
|
|
128
153
|
async function loadValidateLogs () {
|
|
129
|
-
|
|
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)
|
|
154
|
+
//build table
|
|
155
|
+
const tblResult = document.getElementById("tblResult");
|
|
156
|
+
//clear
|
|
157
|
+
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
140
158
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const topLogCount = 1000;
|
|
145
|
-
const pageSize = 10000
|
|
159
|
+
parameters.service = cmbService.options[cmbService.selectedIndex].text
|
|
146
160
|
|
|
161
|
+
|
|
147
162
|
let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
|
|
148
163
|
|
|
149
164
|
console.log(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
165
|
+
|
|
166
|
+
//-1 && m.message.indexOf("The network is built.") > -1 && m.methodName == 'BuildEngineLog')
|
|
167
|
+
//page query the admin log
|
|
168
|
+
let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "The network is built.", "VERBOSE")
|
|
169
|
+
|
|
170
|
+
|
|
172
171
|
//validate logs missing elapsed populate it
|
|
173
172
|
allMessages = allMessages.map( m => {
|
|
174
173
|
try{
|
|
@@ -195,45 +194,21 @@ tblResult.appendChild(document.createTextNode("Loading...."));
|
|
|
195
194
|
|
|
196
195
|
|
|
197
196
|
async function loadUpdateSubnetworkLogs () {
|
|
198
|
-
|
|
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)
|
|
197
|
+
//build table
|
|
198
|
+
const tblResult = document.getElementById("tblResult");
|
|
199
|
+
//clear
|
|
200
|
+
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
207
201
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const pageSize = 10000
|
|
202
|
+
parameters.service = cmbService.options[cmbService.selectedIndex].text
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
|
|
213
206
|
|
|
214
|
-
|
|
207
|
+
|
|
208
|
+
console.log(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
209
|
+
let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "---- Subnetwork Parameters ----", "VERBOSE")
|
|
215
210
|
|
|
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
|
-
|
|
211
|
+
|
|
237
212
|
//update subnetwork missing elapsed populate it
|
|
238
213
|
allMessages = allMessages.map( m => {
|
|
239
214
|
try{
|
|
@@ -265,41 +240,20 @@ async function loadAttributeRules () {
|
|
|
265
240
|
|
|
266
241
|
//build table
|
|
267
242
|
const tblResult = document.getElementById("tblResult");
|
|
268
|
-
tblResult.
|
|
269
|
-
|
|
243
|
+
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
244
|
+
|
|
270
245
|
let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
|
|
271
246
|
|
|
272
247
|
parameters.service = cmbService.options[cmbService.selectedIndex].text
|
|
273
|
-
|
|
274
|
-
adminLog = new AdminLog(token, portal.serverUrl)
|
|
275
|
-
|
|
248
|
+
|
|
276
249
|
let showMaxGuid = true
|
|
277
|
-
let showMinGuid = false
|
|
278
|
-
|
|
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
|
|
250
|
+
let showMinGuid = false
|
|
251
|
+
|
|
286
252
|
logger.info(`Querying attribute rules logs for ${parameters.service} in the past ${mins} minutes...`)
|
|
287
|
-
let
|
|
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
|
-
}
|
|
253
|
+
let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule execution complete:", "DEBUG")
|
|
301
254
|
|
|
302
|
-
|
|
255
|
+
|
|
256
|
+
const arMessages = filterMessages(allMessages)
|
|
303
257
|
.filter(m => m.message.indexOf("Attribute rule execution complete:") > -1)
|
|
304
258
|
.map (m => JSON.parse(m.message.replace("Attribute rule execution complete:", "")))
|
|
305
259
|
.map( m => {
|
|
@@ -370,7 +324,8 @@ async function loadAttributeRules () {
|
|
|
370
324
|
│ Min execution time (m
|
|
371
325
|
|
|
372
326
|
*/
|
|
373
|
-
|
|
327
|
+
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
328
|
+
|
|
374
329
|
const header = document.createElement("tr");
|
|
375
330
|
const cAttributeRule = document.createElement("th");
|
|
376
331
|
cAttributeRule.textContent = "Attribute Rule"
|
|
@@ -439,48 +394,70 @@ async function loadSQLLogs () {
|
|
|
439
394
|
const tblResult = document.getElementById("tblResult");
|
|
440
395
|
//clear
|
|
441
396
|
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
442
|
-
|
|
443
|
-
|
|
397
|
+
|
|
444
398
|
|
|
445
399
|
parameters.service = cmbService.options[cmbService.selectedIndex].text
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
logger.info("Connected.")
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
|
|
451
403
|
|
|
404
|
+
|
|
405
|
+
console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
452
406
|
|
|
453
|
-
|
|
454
|
-
|
|
407
|
+
//startTime is the most recent
|
|
408
|
+
//endTime is the oldest
|
|
455
409
|
|
|
456
|
-
|
|
410
|
+
|
|
457
411
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const startTime = Date.now()
|
|
461
|
-
const endTime = Date.now()
|
|
462
|
-
let services = [
|
|
463
|
-
if (
|
|
412
|
+
/*
|
|
413
|
+
const topLogCount = 100;
|
|
414
|
+
const startTime = Date.now()
|
|
415
|
+
const endTime = Date.now() - mins*60*1000
|
|
416
|
+
let services = [theService + ".MapServer"]
|
|
417
|
+
if (theService == "(All Services)")
|
|
464
418
|
services = "*"
|
|
465
|
-
let result= await adminLog.query([
|
|
419
|
+
let result= await adminLog.query([code], services, topLogCount, startTime ,endTime , "DEBUG")
|
|
466
420
|
let jsonRes = await result.json()
|
|
467
421
|
let allMessages = [].concat(jsonRes.logMessages)
|
|
468
422
|
allMessages = allMessages.filter(m => m.message.indexOf("EndCursor;") > -1)
|
|
469
423
|
while (jsonRes.hasMore)
|
|
470
424
|
{
|
|
471
425
|
//start paging
|
|
472
|
-
logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs
|
|
473
|
-
result= await adminLog.query([102023], services, pageSize, jsonRes.endTime,
|
|
426
|
+
logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
|
|
427
|
+
result= await adminLog.query([102023], services, pageSize, jsonRes.endTime, endTime, "DEBUG")
|
|
474
428
|
jsonRes = await result.json()
|
|
475
429
|
|
|
476
430
|
allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
|
|
477
431
|
}
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
//page query the admin log
|
|
435
|
+
let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102023], "EndCursor;", "DEBUG")
|
|
436
|
+
|
|
437
|
+
|
|
478
438
|
console.log ("Filtering messages...")
|
|
479
439
|
|
|
480
|
-
allMessages = allMessages
|
|
440
|
+
allMessages = filterMessages(allMessages)
|
|
481
441
|
.map( m=> {
|
|
482
|
-
m.dataAccessElapsed =
|
|
483
|
-
m.executeQueryElapsed =
|
|
442
|
+
m.dataAccessElapsed =0;
|
|
443
|
+
m.executeQueryElapsed = 0;
|
|
444
|
+
const sDataAccess = "DataAccess "
|
|
445
|
+
const idxDataAccess = m.message.indexOf(sDataAccess)
|
|
446
|
+
if (idxDataAccess >=0) {
|
|
447
|
+
const idxNext = m.message.indexOf(" ",idxDataAccess + sDataAccess.length )
|
|
448
|
+
m.dataAccessElapsed = parseInt(m.message.substr( idxDataAccess + sDataAccess.length, idxNext - idxDataAccess - sDataAccess.length))
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const sExecuteQuery = "ExecuteQuery "
|
|
452
|
+
const idxExecuteQuery = m.message.indexOf(sExecuteQuery)
|
|
453
|
+
if (idxExecuteQuery >=0) {
|
|
454
|
+
const idxNext = m.message.indexOf(" ",idxExecuteQuery + sExecuteQuery.length)
|
|
455
|
+
m.executeQueryElapsed = parseInt(m.message.substr( idxExecuteQuery + sExecuteQuery.length, idxNext - idxExecuteQuery - sExecuteQuery.length))
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
//m.dataAccessElapsed = parseFloat(m.message.split(";")[1].split(" ")[1])
|
|
460
|
+
//m.executeQueryElapsed = parseFloat(m.message.split(";")[2].split(" ")[1])
|
|
484
461
|
m.totalExecutionElapsed = m.dataAccessElapsed + m.executeQueryElapsed
|
|
485
462
|
m.elapsed = parseFloat(m.elapsed); return m;
|
|
486
463
|
|
|
@@ -489,7 +466,7 @@ tblResult.appendChild(document.createTextNode("Loading...."));
|
|
|
489
466
|
.slice(0, 100) ;//first 100
|
|
490
467
|
|
|
491
468
|
|
|
492
|
-
console.log("-----Top
|
|
469
|
+
console.log("-----Top SQL----")
|
|
493
470
|
while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
|
|
494
471
|
|
|
495
472
|
let i =0;
|
|
@@ -501,8 +478,8 @@ tblResult.appendChild(document.createTextNode("Loading...."));
|
|
|
501
478
|
cTime.textContent = "Time"
|
|
502
479
|
const cUser = document.createElement("th");
|
|
503
480
|
cUser.textContent = "User"
|
|
504
|
-
const
|
|
505
|
-
|
|
481
|
+
const cVersion = document.createElement("th");
|
|
482
|
+
cVersion.textContent = "Version"
|
|
506
483
|
const cQueryTime = document.createElement("th");
|
|
507
484
|
cQueryTime.textContent = "Query Time (ms)"
|
|
508
485
|
cQueryTime.title = "includes search + data access nextRow"
|
|
@@ -514,7 +491,7 @@ tblResult.appendChild(document.createTextNode("Loading...."));
|
|
|
514
491
|
header.appendChild (cService)
|
|
515
492
|
header.appendChild (cTime)
|
|
516
493
|
header.appendChild (cUser)
|
|
517
|
-
header.appendChild (
|
|
494
|
+
header.appendChild (cVersion)
|
|
518
495
|
header.appendChild (cQueryTime)
|
|
519
496
|
header.appendChild (cTotalTime)
|
|
520
497
|
header.appendChild (cLog)
|
|
@@ -544,21 +521,32 @@ tblResult.appendChild(document.createTextNode("Loading...."));
|
|
|
544
521
|
|
|
545
522
|
const cUser = document.createElement("td");
|
|
546
523
|
cUser.textContent = m.user
|
|
547
|
-
const
|
|
548
|
-
|
|
524
|
+
const cVersion = document.createElement("td");
|
|
525
|
+
const idxVersion = m.message.indexOf("Version: ")
|
|
526
|
+
if (idxVersion >=0) {
|
|
527
|
+
const idxNext = m.message.indexOf(";",idxVersion)
|
|
528
|
+
cVersion.textContent = m.message.substr( idxVersion + 9, idxNext - idxVersion - 9 )
|
|
529
|
+
}
|
|
549
530
|
const cQueryTime = document.createElement("td");
|
|
550
531
|
cQueryTime.textContent = numberWithCommas(m.totalExecutionElapsed)
|
|
551
532
|
const cTotalTime = document.createElement("td");
|
|
552
533
|
cTotalTime.textContent = numberWithCommas(Math.round(m.elapsed*1000))
|
|
553
534
|
const cLog = document.createElement("td");
|
|
554
|
-
|
|
535
|
+
const cLogText = document.createElement("input")
|
|
536
|
+
cLogText.type = "text"
|
|
537
|
+
cLogText.style = "width:500px"
|
|
538
|
+
cLogText.value = m.message.substr( m.message.indexOf("SQL: ") + 5, m.message.length)
|
|
539
|
+
cLogText.readOnly= true;
|
|
540
|
+
cLog.appendChild(cLogText)
|
|
541
|
+
//cLog.textContent = m.message.substr( m.message.indexOf("SQL: ") + 5, 50) + "..."
|
|
555
542
|
cLog.fullLog = m.message;
|
|
556
543
|
cLog.title = m.message + "\nClick to copy"
|
|
557
|
-
cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog);
|
|
544
|
+
cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
|
|
545
|
+
/* alert("Copied to clipboard") */})
|
|
558
546
|
logRow.appendChild (cService)
|
|
559
547
|
logRow.appendChild (cTime)
|
|
560
548
|
logRow.appendChild (cUser)
|
|
561
|
-
logRow.appendChild (
|
|
549
|
+
logRow.appendChild (cVersion)
|
|
562
550
|
logRow.appendChild (cQueryTime)
|
|
563
551
|
logRow.appendChild (cTotalTime)
|
|
564
552
|
logRow.appendChild (cLog)
|
|
@@ -584,30 +572,50 @@ function numberWithCommas(x) {
|
|
|
584
572
|
return x.toLocaleString()
|
|
585
573
|
}
|
|
586
574
|
|
|
587
|
-
init();
|
|
575
|
+
//init();
|
|
588
576
|
|
|
589
577
|
const btnTraceLogs = document.getElementById("btnTraceLogs");
|
|
590
578
|
btnTraceLogs.addEventListener("click", e => loadTraceLogs())
|
|
579
|
+
btnTraceLogs.disabled = true
|
|
591
580
|
|
|
592
581
|
const btnValidateLogs = document.getElementById("btnValidateLogs");
|
|
593
582
|
btnValidateLogs.addEventListener("click", e => loadValidateLogs())
|
|
583
|
+
btnValidateLogs.disabled = true
|
|
594
584
|
|
|
595
585
|
const btnUpdateSubnetworkLogs = document.getElementById("btnUpdateSubnetworkLogs");
|
|
596
586
|
btnUpdateSubnetworkLogs.addEventListener("click", e => loadUpdateSubnetworkLogs())
|
|
597
|
-
|
|
587
|
+
btnUpdateSubnetworkLogs.disabled = true
|
|
588
|
+
|
|
598
589
|
const btnSQLLogs = document.getElementById("btnSQLLogs");
|
|
599
590
|
btnSQLLogs.addEventListener("click", e => loadSQLLogs())
|
|
600
|
-
|
|
591
|
+
btnSQLLogs.disabled = true
|
|
592
|
+
|
|
601
593
|
const btnAR = document.getElementById("btnAR");
|
|
602
594
|
btnAR.addEventListener("click", e => loadAttributeRules())
|
|
603
|
-
|
|
604
|
-
|
|
595
|
+
btnAR.disabled = true
|
|
596
|
+
|
|
597
|
+
function filterMessages (allMessages) {
|
|
598
|
+
const txtFilter = document.getElementById("txtFilter")
|
|
599
|
+
const txtUser = document.getElementById("txtUser")
|
|
600
|
+
if (txtFilter.value == "" && txtUser.value == "") return allMessages;
|
|
601
|
+
//const filtered= allMessages.filter(m => m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) > 0 && m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) > 0)
|
|
602
|
+
const filtered= allMessages.filter(m => {
|
|
603
|
+
|
|
604
|
+
if (m.message.toUpperCase().indexOf(txtFilter.value.toUpperCase()) >= 0
|
|
605
|
+
&&
|
|
606
|
+
m.user.toUpperCase().indexOf(txtUser.value.toUpperCase()) >= 0)
|
|
607
|
+
return true
|
|
608
|
+
|
|
609
|
+
return false
|
|
610
|
+
})
|
|
611
|
+
return filtered
|
|
612
|
+
}
|
|
605
613
|
|
|
606
614
|
async function populateMessages(allTheMessages) {
|
|
607
615
|
|
|
608
616
|
//sort messages
|
|
609
617
|
|
|
610
|
-
const allMessages = allTheMessages.map(m => {
|
|
618
|
+
const allMessages = filterMessages (allTheMessages).map(m => {
|
|
611
619
|
const newMessage = Object.assign({}, m);
|
|
612
620
|
delete newMessage.machine;
|
|
613
621
|
delete newMessage.type;
|
|
@@ -672,6 +680,65 @@ function numberWithCommas(x) {
|
|
|
672
680
|
tblResult.appendChild(logRow)
|
|
673
681
|
})
|
|
674
682
|
}
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
async function adminLogQueryWithPaging(mins, theService, code, filter, level){
|
|
686
|
+
const topLogCount = 1000;
|
|
687
|
+
let stop = false;
|
|
688
|
+
const prg = document.createTextNode("Loading.... 0%");
|
|
689
|
+
const btn = document.createElement("button")
|
|
690
|
+
btn.textContent = '🛑'
|
|
691
|
+
btn.addEventListener("click", ()=> stop = true )
|
|
692
|
+
//create a new admin object (user might not be admin we won't use it until the user call log )
|
|
693
|
+
let adminLog = new AdminLog(token, portal.serverUrl)
|
|
694
|
+
tblResult.appendChild(prg);
|
|
695
|
+
tblResult.appendChild(btn)
|
|
696
|
+
const startTime = Date.now()
|
|
697
|
+
const endTime = Date.now() - mins*60*1000
|
|
698
|
+
let services = [theService + ".MapServer"]
|
|
699
|
+
if (theService == "(All Services)")
|
|
700
|
+
services = "*"
|
|
701
|
+
let result= await adminLog.query(code, services, topLogCount, startTime ,endTime , level)
|
|
702
|
+
let jsonRes = await result.json()
|
|
703
|
+
let allMessages = [].concat(jsonRes.logMessages)
|
|
704
|
+
allMessages = allMessages.filter(m => m.message.indexOf(filter) > -1)
|
|
705
|
+
while (jsonRes.hasMore && !stop)
|
|
706
|
+
{
|
|
707
|
+
//start paging
|
|
708
|
+
prg.textContent = "Loading ... " + parseInt((( (startTime - endTime) - (jsonRes.endTime - endTime) ) /((startTime - endTime)))*100) + "%"
|
|
709
|
+
logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
|
|
710
|
+
result= await adminLog.query(code, services, topLogCount, jsonRes.endTime, endTime, level)
|
|
711
|
+
jsonRes = await result.json()
|
|
712
|
+
|
|
713
|
+
allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf(filter) > -1))
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return allMessages
|
|
717
|
+
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
/*
|
|
722
|
+
const topLogCount = 100;f
|
|
723
|
+
const startTime = Date.now()
|
|
724
|
+
const endTime = Date.now() - mins*60*1000
|
|
725
|
+
let services = [theService + ".MapServer"]
|
|
726
|
+
if (theService == "(All Services)")
|
|
727
|
+
services = "*"
|
|
728
|
+
let result= await adminLog.query([code], services, topLogCount, startTime ,endTime , "DEBUG")
|
|
729
|
+
let jsonRes = await result.json()
|
|
730
|
+
let allMessages = [].concat(jsonRes.logMessages)
|
|
731
|
+
allMessages = allMessages.filter(m => m.message.indexOf("EndCursor;") > -1)
|
|
732
|
+
while (jsonRes.hasMore)
|
|
733
|
+
{
|
|
734
|
+
//start paging
|
|
735
|
+
logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
|
|
736
|
+
result= await adminLog.query([102023], services, pageSize, jsonRes.endTime, endTime, "DEBUG")
|
|
737
|
+
jsonRes = await result.json()
|
|
738
|
+
|
|
739
|
+
allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
|
|
740
|
+
}
|
|
741
|
+
*/
|
|
675
742
|
</script>
|
|
676
743
|
</body>
|
|
677
744
|
</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.
|
|
10
|
+
let version = "0.0.73";
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
282
|
+
logger.info("Building Evaluation Blocks ...");
|
|
283
283
|
//return evaluation blocks for layer 5
|
|
284
284
|
const blocks = await buildEvaluationBlocks(5);
|
|
285
285
|
|
|
286
|
-
|
|
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 =>
|
|
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
|
-
|
|
292
|
+
logger.info("done sending all requests.. now waiting for response ")
|
|
293
293
|
|
|
294
|
-
Promise.all(promises).then(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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
385
|
+
logger.info (`${numberWithCommas(rowCount)} rows returned.`)
|
|
386
386
|
},
|
|
387
387
|
|
|
388
388
|
"^update subnetworks --deleted$" : async () => {
|
|
389
|
-
|
|
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
|
-
|
|
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
|
-
|
|
394
|
+
logger.info("Updating Subnetwork " + v(f.attributes,"subnetworkName"));
|
|
395
395
|
|
|
396
396
|
const fromDate = new Date();
|
|
397
397
|
|
|
@@ -404,34 +404,46 @@ const inputs = {
|
|
|
404
404
|
subnetworkResult.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
|
|
405
405
|
|
|
406
406
|
|
|
407
|
-
|
|
407
|
+
logger.info(`Result ${JSON.stringify(subnetworkResult)}`)
|
|
408
408
|
}
|
|
409
409
|
},
|
|
410
410
|
|
|
411
411
|
"^update subnetworks --all" : async input => {
|
|
412
412
|
|
|
413
|
+
let subnetworks;
|
|
414
|
+
let more = false;
|
|
415
|
+
let failedSubnetworks = []
|
|
413
416
|
do {
|
|
414
417
|
|
|
415
418
|
let sort = "asc";
|
|
416
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(",") + ")"
|
|
417
424
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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.`);
|
|
421
428
|
|
|
422
429
|
for (let i = 0; i < subnetworks.features.length; i++) {
|
|
423
430
|
const f = subnetworks.features[i]
|
|
424
|
-
|
|
431
|
+
const subnetworkName = v(f.attributes,"subnetworkName")
|
|
432
|
+
logger.info("Updating Subnetwork " + subnetworkName);
|
|
425
433
|
|
|
426
434
|
const fromDate = new Date();
|
|
427
435
|
|
|
428
436
|
const subnetworkResult = await un.updateSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
|
|
429
|
-
|
|
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
|
+
|
|
430
442
|
const toDate = new Date();
|
|
431
443
|
const timeEnable = toDate.getTime() - fromDate.getTime();
|
|
432
444
|
subnetworkResult.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
|
|
433
445
|
|
|
434
|
-
|
|
446
|
+
logger.info(`Result ${JSON.stringify(subnetworkResult)}`)
|
|
435
447
|
}
|
|
436
448
|
|
|
437
449
|
}
|
|
@@ -439,18 +451,19 @@ const inputs = {
|
|
|
439
451
|
|
|
440
452
|
},
|
|
441
453
|
"^update subnetworks --all --async$" : async () => {
|
|
442
|
-
|
|
454
|
+
logger.info("Querying all subnetworks that are dirty.");
|
|
443
455
|
let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=1", "domainnetworkname,tiername,subnetworkname");
|
|
444
|
-
|
|
456
|
+
logger.info(`Discovered ${subnetworks.features.length} dirty subnetworks.`);
|
|
445
457
|
for (let i = 0; i < subnetworks.features.length; i++) {
|
|
446
458
|
const f = subnetworks.features[i]
|
|
447
|
-
|
|
459
|
+
logger.info("Sending job for " + v(f.attributes,"subnetworkName"));
|
|
448
460
|
const subnetworkResult = await un.updateSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),true);
|
|
449
|
-
|
|
461
|
+
logger.info(`Result from submitting job ${JSON.stringify(subnetworkResult)}`)
|
|
450
462
|
}
|
|
451
463
|
},
|
|
452
464
|
"^export subnetworks --all --folder .*$|^export subnetworks --all$" : async input => {
|
|
453
465
|
|
|
466
|
+
let subnetworks
|
|
454
467
|
//create folder
|
|
455
468
|
const file = input.match(/--folder .*/gm)
|
|
456
469
|
let inputDir = "Exported"
|
|
@@ -461,13 +474,13 @@ const inputs = {
|
|
|
461
474
|
|
|
462
475
|
do {
|
|
463
476
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
477
|
+
logger.info("Querying all subnetworks that are clean.");
|
|
478
|
+
subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=0","domainnetworkname,tiername,subnetworkname");
|
|
479
|
+
logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
|
|
467
480
|
for (let i = 0; i < subnetworks.features.length; i++) {
|
|
468
481
|
const f = subnetworks.features[i]
|
|
469
482
|
const subnetworkName = v(f.attributes,"subnetworkName")
|
|
470
|
-
|
|
483
|
+
logger.info("Exporting subnetworks " + v(f.attributes,"subnetworkName"));
|
|
471
484
|
|
|
472
485
|
const fromDate = new Date();
|
|
473
486
|
|
|
@@ -482,7 +495,7 @@ const inputs = {
|
|
|
482
495
|
//if undefined exit
|
|
483
496
|
if (!subnetworkResult.url)
|
|
484
497
|
{
|
|
485
|
-
|
|
498
|
+
logger.info("Export subnetwork failed " + JSON.stringify(subnetworkResult))
|
|
486
499
|
continue;
|
|
487
500
|
}
|
|
488
501
|
|
|
@@ -495,7 +508,7 @@ const inputs = {
|
|
|
495
508
|
fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, jsonExport)
|
|
496
509
|
|
|
497
510
|
|
|
498
|
-
|
|
511
|
+
logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
|
|
499
512
|
|
|
500
513
|
}
|
|
501
514
|
}
|
|
@@ -515,20 +528,20 @@ const inputs = {
|
|
|
515
528
|
if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
|
|
516
529
|
|
|
517
530
|
|
|
518
|
-
|
|
531
|
+
logger.info("Querying all subnetworks that are clean and not exported.");
|
|
519
532
|
let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty = 0 and (LASTACKEXPORTSUBNETWORK is null or LASTACKEXPORTSUBNETWORK < LASTUPDATESUBNETWORK)","domainnetworkname,tiername,subnetworkname");
|
|
520
|
-
|
|
533
|
+
logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
|
|
521
534
|
for (let i = 0; i < subnetworks.features.length; i++) {
|
|
522
535
|
const f = subnetworks.features[i]
|
|
523
536
|
const subnetworkName = v(f.attributes,"subnetworkName")
|
|
524
|
-
|
|
537
|
+
logger.info(`Exporting subnetwork ${subnetworkName}` );
|
|
525
538
|
const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
|
|
526
539
|
//fetch the json and write it to disk
|
|
527
540
|
const subContent = await fetch(subnetworkResult.url);
|
|
528
541
|
const jsonExport = await subContent.text();
|
|
529
542
|
fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, JSON.stringify(jsonExport))
|
|
530
543
|
|
|
531
|
-
|
|
544
|
+
logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
|
|
532
545
|
}
|
|
533
546
|
|
|
534
547
|
|
|
@@ -538,7 +551,7 @@ const inputs = {
|
|
|
538
551
|
"^ia$": async input => {
|
|
539
552
|
|
|
540
553
|
const result = await un.returnInvalidAssociations();
|
|
541
|
-
|
|
554
|
+
logger.info("Invalid Associations " + JSON.stringify(result))
|
|
542
555
|
},
|
|
543
556
|
"^connect --service": async input =>{
|
|
544
557
|
|
|
@@ -561,10 +574,10 @@ const inputs = {
|
|
|
561
574
|
if (inputParam != null && inputParam.length > 0)
|
|
562
575
|
subnetworkName = inputParam[0].replace("--subnetwork ", "")
|
|
563
576
|
|
|
564
|
-
|
|
577
|
+
logger.info(`Tracing subnetwork ${subnetworkName}`);
|
|
565
578
|
const result = await un.subnetworkTraceSimple(subnetworkName)
|
|
566
579
|
if (result == null) {
|
|
567
|
-
|
|
580
|
+
logger.info(`Subnetwork ${subnetworkName} doesn't exist`);
|
|
568
581
|
return null;
|
|
569
582
|
}
|
|
570
583
|
const toDate = new Date();
|
|
@@ -586,19 +599,19 @@ const inputs = {
|
|
|
586
599
|
if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
|
|
587
600
|
|
|
588
601
|
|
|
589
|
-
|
|
602
|
+
logger.info("Querying all subnetworks that are clean and deleted.");
|
|
590
603
|
let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty = 0 and isdeleted=1");
|
|
591
|
-
|
|
604
|
+
logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
|
|
592
605
|
for (let i = 0; i < subnetworks.features.length; i++) {
|
|
593
606
|
const f = subnetworks.features[i]
|
|
594
607
|
const subnetworkName = v(f.attributes,"subnetworkName")
|
|
595
|
-
|
|
608
|
+
logger.info(`Exporting subnetwork ${subnetworkName}` );
|
|
596
609
|
const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
|
|
597
610
|
|
|
598
611
|
//if undefined exit
|
|
599
612
|
if (!subnetworkResult.url)
|
|
600
613
|
{
|
|
601
|
-
|
|
614
|
+
logger.info("Export subnetwork failed " + JSON.stringify(subnetworkResult))
|
|
602
615
|
continue;
|
|
603
616
|
}
|
|
604
617
|
|
|
@@ -607,7 +620,7 @@ const inputs = {
|
|
|
607
620
|
const jsonExport = await subContent.text();
|
|
608
621
|
fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, JSON.stringify(jsonExport))
|
|
609
622
|
|
|
610
|
-
|
|
623
|
+
logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
|
|
611
624
|
}
|
|
612
625
|
|
|
613
626
|
|
|
@@ -616,7 +629,7 @@ const inputs = {
|
|
|
616
629
|
"^cwd$" : async input => {
|
|
617
630
|
|
|
618
631
|
|
|
619
|
-
|
|
632
|
+
logger.info(process.cwd())
|
|
620
633
|
|
|
621
634
|
},
|
|
622
635
|
|
|
@@ -628,14 +641,14 @@ const inputs = {
|
|
|
628
641
|
//create directory if doesn't exists
|
|
629
642
|
if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
|
|
630
643
|
fs.writeFileSync(`${inputDir}/${Math.random()}`, Math.random())
|
|
631
|
-
|
|
644
|
+
logger.info(inputDir)
|
|
632
645
|
|
|
633
646
|
|
|
634
647
|
},
|
|
635
648
|
|
|
636
649
|
|
|
637
650
|
"^count$": async () => {
|
|
638
|
-
|
|
651
|
+
logger.info("Querying all layers....")
|
|
639
652
|
const layerProperties = [
|
|
640
653
|
"id",
|
|
641
654
|
"name",
|
|
@@ -669,12 +682,12 @@ const inputs = {
|
|
|
669
682
|
|
|
670
683
|
|
|
671
684
|
console.table(layerCount)
|
|
672
|
-
|
|
685
|
+
logger.info(`Total number of rows in all layers : ${numberWithCommas(totalRows)} .`)
|
|
673
686
|
},
|
|
674
687
|
|
|
675
688
|
|
|
676
689
|
"^count --system$": async () => {
|
|
677
|
-
|
|
690
|
+
logger.info("Querying all system layers....")
|
|
678
691
|
|
|
679
692
|
const systemLayers = un.getSystemLayers();
|
|
680
693
|
let totalRows = 0;
|
|
@@ -697,7 +710,7 @@ const inputs = {
|
|
|
697
710
|
}
|
|
698
711
|
|
|
699
712
|
console.table(layerCount)
|
|
700
|
-
|
|
713
|
+
logger.info(`Total number of rows in all system layers : ${numberWithCommas(totalRows)} .`)
|
|
701
714
|
|
|
702
715
|
},
|
|
703
716
|
|
|
@@ -712,7 +725,7 @@ const inputs = {
|
|
|
712
725
|
mins = inputParam[0].replace("--age ", "")
|
|
713
726
|
|
|
714
727
|
|
|
715
|
-
|
|
728
|
+
logger.info(`Querying attribute rules logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
716
729
|
|
|
717
730
|
const startTime = Date.now() - mins*60*1000
|
|
718
731
|
const endTime = Date.now();
|
|
@@ -762,7 +775,7 @@ const inputs = {
|
|
|
762
775
|
if (inputParam != null && inputParam.length > 0)
|
|
763
776
|
mins = inputParam[0].replace("--age ", "")
|
|
764
777
|
|
|
765
|
-
|
|
778
|
+
logger.info(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
766
779
|
const startTime = Date.now() - mins*60*1000
|
|
767
780
|
const endTime = Date.now();
|
|
768
781
|
let result= await adminLog.query([102002], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "VERBOSE")
|
|
@@ -803,7 +816,7 @@ const inputs = {
|
|
|
803
816
|
delete newMessage.message
|
|
804
817
|
|
|
805
818
|
console.table([newMessage])
|
|
806
|
-
|
|
819
|
+
logger.info(m.message)
|
|
807
820
|
})
|
|
808
821
|
|
|
809
822
|
},
|
|
@@ -821,7 +834,7 @@ const inputs = {
|
|
|
821
834
|
mins = inputParam[0].replace("--age ", "")
|
|
822
835
|
|
|
823
836
|
|
|
824
|
-
|
|
837
|
+
logger.info(`Querying validate logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
825
838
|
const startTime = Date.now() - mins*60*1000
|
|
826
839
|
const endTime = Date.now();
|
|
827
840
|
let result= await adminLog.query([102003], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "VERBOSE")
|
|
@@ -886,7 +899,7 @@ const inputs = {
|
|
|
886
899
|
delete newMessage.message
|
|
887
900
|
|
|
888
901
|
console.table([newMessage])
|
|
889
|
-
|
|
902
|
+
logger.info(m.message)
|
|
890
903
|
})
|
|
891
904
|
|
|
892
905
|
|
|
@@ -905,7 +918,7 @@ const inputs = {
|
|
|
905
918
|
if (inputParam != null && inputParam.length > 0)
|
|
906
919
|
mins = inputParam[0].replace("--age ", "")
|
|
907
920
|
|
|
908
|
-
|
|
921
|
+
logger.info(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
909
922
|
const startTime = Date.now() - mins*60*1000
|
|
910
923
|
const endTime = Date.now();
|
|
911
924
|
let result= await adminLog.query([102003], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "VERBOSE")
|
|
@@ -970,7 +983,7 @@ const inputs = {
|
|
|
970
983
|
delete newMessage.message
|
|
971
984
|
|
|
972
985
|
console.table([newMessage])
|
|
973
|
-
|
|
986
|
+
logger.info(m.message)
|
|
974
987
|
})
|
|
975
988
|
|
|
976
989
|
|
|
@@ -987,7 +1000,7 @@ const inputs = {
|
|
|
987
1000
|
if (inputParam != null && inputParam.length > 0)
|
|
988
1001
|
mins = inputParam[0].replace("--age ", "")
|
|
989
1002
|
|
|
990
|
-
|
|
1003
|
+
logger.info(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
|
|
991
1004
|
const startTime = Date.now() - mins*60*1000
|
|
992
1005
|
const endTime = Date.now();
|
|
993
1006
|
let result= await adminLog.query([102023], [parameters.service+ ".MapServer"], topLogCount, startTime ,endTime , "DEBUG")
|
|
@@ -1003,7 +1016,7 @@ const inputs = {
|
|
|
1003
1016
|
|
|
1004
1017
|
allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
|
|
1005
1018
|
}
|
|
1006
|
-
|
|
1019
|
+
logger.info ("Filtering messages...")
|
|
1007
1020
|
|
|
1008
1021
|
allMessages = allMessages
|
|
1009
1022
|
.map( m=> {
|
|
@@ -1017,21 +1030,21 @@ const inputs = {
|
|
|
1017
1030
|
.slice(0, 10) ;//first 10
|
|
1018
1031
|
|
|
1019
1032
|
|
|
1020
|
-
|
|
1033
|
+
logger.info("-----Top 10 SQL----")
|
|
1021
1034
|
let i =0;
|
|
1022
1035
|
allMessages= allMessages.forEach(m =>
|
|
1023
1036
|
{
|
|
1024
1037
|
|
|
1025
1038
|
const x = m.message.split(";")
|
|
1026
1039
|
x.shift()
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
x.forEach(a =>
|
|
1034
|
-
|
|
1040
|
+
logger.info(`id: ${i++}`)
|
|
1041
|
+
logger.info(`\tAt: ${new Date(m.time)} (${m.time})`)
|
|
1042
|
+
logger.info(`\tUser: ${m.user}`)
|
|
1043
|
+
logger.info(`\tTotal Time: ${numberWithCommas(Math.round(m.elapsed*1000))} ms (Total time the cursor was opened)`)
|
|
1044
|
+
logger.info(`\tQuery Time: ${numberWithCommas(m.totalExecutionElapsed)} ms (includes search + data access nextRow)`)
|
|
1045
|
+
logger.info(`\tQuery:`)
|
|
1046
|
+
x.forEach(a => logger.info(`\t${a}`))
|
|
1047
|
+
logger.info(`\n`)
|
|
1035
1048
|
|
|
1036
1049
|
})
|
|
1037
1050
|
|
|
@@ -1143,11 +1156,11 @@ const inputs = {
|
|
|
1143
1156
|
console.table(rules)
|
|
1144
1157
|
|
|
1145
1158
|
const totalARExecution = rules.reduce( (prev, cur) => prev + cur["Total Cost (ms)"], 0)
|
|
1146
|
-
|
|
1159
|
+
logger.info(`Total time spend executing attribute rules (${Math.round(totalARExecution)} ms) (${Math.round(totalARExecution/1000)} s) (${Math.round(totalARExecution/(1000*60))} m)`)
|
|
1147
1160
|
|
|
1148
1161
|
},
|
|
1149
1162
|
|
|
1150
|
-
"^version$": () =>
|
|
1163
|
+
"^version$": () => logger.info(version),
|
|
1151
1164
|
"^clear$|^cls$": () => console.clear(),
|
|
1152
1165
|
"^quit$": () => {
|
|
1153
1166
|
if (rl) rl.close();
|
|
@@ -1172,7 +1185,7 @@ const inputs = {
|
|
|
1172
1185
|
|
|
1173
1186
|
while(true) {
|
|
1174
1187
|
const result = await un.query(layerId, `1=1`, undefined, undefined, ["globalId"], "sde.DEFAULT", offset, recordCount)
|
|
1175
|
-
|
|
1188
|
+
logger.info(`Processing ${recordCount} rows`)
|
|
1176
1189
|
//for each assocaition check if its valid
|
|
1177
1190
|
for (let i = 0 ; i < result.features.length; i++){
|
|
1178
1191
|
const row = result.features[i]
|
|
@@ -1287,7 +1300,7 @@ function numberWithCommas(x) {
|
|
|
1287
1300
|
/*
|
|
1288
1301
|
rl.question("What is your name ? ", function(name) {
|
|
1289
1302
|
rl.question("Where do you live ? ", function(country) {
|
|
1290
|
-
|
|
1303
|
+
logger.info(`${name}, is a citizen of ${country}`);
|
|
1291
1304
|
rl.close();
|
|
1292
1305
|
});
|
|
1293
1306
|
});
|
|
@@ -1300,7 +1313,7 @@ function setupReadLine() {
|
|
|
1300
1313
|
});
|
|
1301
1314
|
|
|
1302
1315
|
rl.on("close", function() {
|
|
1303
|
-
|
|
1316
|
+
logger.info("\nbye");
|
|
1304
1317
|
process.exit(0);
|
|
1305
1318
|
});
|
|
1306
1319
|
|
|
@@ -1322,7 +1335,7 @@ export async function run (){
|
|
|
1322
1335
|
console.error(`Minimum required node js is ${minVer} your version is ${process.version}`)
|
|
1323
1336
|
process.exit(0);
|
|
1324
1337
|
}
|
|
1325
|
-
|
|
1338
|
+
logger.info(`uncli ${version} is experimental command line utility for basic utility network services. Use as is.`)
|
|
1326
1339
|
parameters = await parseInput( )
|
|
1327
1340
|
//set certificate verification
|
|
1328
1341
|
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
|
|