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.
- package/cmd.txt +1 -1
- package/index.html +237 -200
- package/index.mjs +110 -92
- package/logger.mjs +16 -2
- package/package.json +1 -1
package/cmd.txt
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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,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
|
-
|
|
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
|
+
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
274
|
-
adminLog = new AdminLog(token, portal.serverUrl)
|
|
275
|
-
|
|
250
|
+
|
|
276
251
|
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
|
|
252
|
+
let showMinGuid = false
|
|
253
|
+
|
|
286
254
|
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
|
-
}
|
|
255
|
+
let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "Attribute rule execution complete:", "DEBUG")
|
|
301
256
|
|
|
302
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
454
|
-
|
|
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 =
|
|
483
|
-
m.executeQueryElapsed =
|
|
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
|
|
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
|
|
505
|
-
|
|
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 (
|
|
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
|
|
548
|
-
|
|
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
|
-
|
|
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);
|
|
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 (
|
|
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.
|
|
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
|
-
|
|
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,35 +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
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
|
-
|
|
420
|
-
subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=1", `domainnetworkname ${sort},tiername ${sort},subnetworkname ${sort}`);
|
|
421
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
518
|
+
logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
|
|
501
519
|
|
|
502
520
|
}
|
|
503
521
|
}
|
|
504
|
-
while (subnetworks
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
584
|
+
logger.info(`Tracing subnetwork ${subnetworkName}`);
|
|
567
585
|
const result = await un.subnetworkTraceSimple(subnetworkName)
|
|
568
586
|
if (result == null) {
|
|
569
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
651
|
+
logger.info(inputDir)
|
|
634
652
|
|
|
635
653
|
|
|
636
654
|
},
|
|
637
655
|
|
|
638
656
|
|
|
639
657
|
"^count$": async () => {
|
|
640
|
-
|
|
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
|
-
|
|
692
|
+
logger.info(`Total number of rows in all layers : ${numberWithCommas(totalRows)} .`)
|
|
675
693
|
},
|
|
676
694
|
|
|
677
695
|
|
|
678
696
|
"^count --system$": async () => {
|
|
679
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
x.forEach(a =>
|
|
1036
|
-
|
|
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
|
-
|
|
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$": () =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|