un-cli 0.0.84 → 0.0.86

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/README.md CHANGED
@@ -1,17 +1,68 @@
1
1
  # uncli
2
- utility network javascript command line works on Windows and Linux
2
+ Server Log Parser and utility network javascript command line works on Windows and Linux
3
3
 
4
- ## Download Node JS 13.5 or later
4
+
5
+
6
+ ## Server Log web parser
7
+ This tool also provides a way to parse server logs and view them for each utility network and geodatabase functions. (Note you do not need to install nodejs for the web parser)
8
+
9
+ ### IIS
10
+ To install on IIS follow these steps: This server assume your machine name where the Webadaptor lives is `utilitynetwork.esri.com`
11
+
12
+ - Login to machine where you have the webadaptor
13
+ - Create a folder called `log` in `c:\inetpub\wwwroot`
14
+ - Copy the entire content of the repro https://github.com/hussein-nasser/uncli to c:\inetpub\wwwroot\log
15
+ - Open IIS (Internet Information Services)
16
+ - Open MIME Types
17
+ - Under action click Add
18
+ - under file extension type `.mjs` and under MIME Type write `application/javascript`
19
+ - Restart IIS
20
+ - (OPTIONAL only change when your webadaptor is not /portal) In c:\inetpub\wwwroot\log edit the `index.html` and find this line of code
21
+ - Update the JSON object with the correct URL, for example if your webadaptor is https://utilitynetwork.esri.com/portal set the "portal" to be that. You don't have to update the referer it will be automatically calculated it.
22
+ - (Optional) if you have multiple federated server , you have to set the correct one you want to query admin api for in the `"server"` parameter below.
23
+
24
+ ```js
25
+ let parameters = {
26
+ "user": "unadmin",
27
+ "password": "",
28
+ "portal": "",
29
+ "service": "",
30
+ "referer": "",
31
+ "server": undefined
32
+ }
33
+ ```
34
+ - Save the HTML and then visit `https://utilitynetwork.esri.com/log` put in your username and password and login to use the parser
35
+
36
+
37
+ ### Tomcat or any other similar Webservers
38
+ -Create a folder under tomcat/webapps/ call it log
39
+ -Then copy the content there.
40
+ -Then go to /home/tomcat/conf/web.xml
41
+ -And add this entry if doesn’t exist
42
+ ```xml
43
+ <mime-mapping>
44
+ <extension>mjs</extension>
45
+ <mime-type>text/javascript</mime-type>
46
+ </mime-mapping>
47
+ ```
48
+
49
+ -Restart tomcat and visit the page/log should work
50
+
51
+
52
+
53
+
54
+ ## Utility Network Command Line tool (Utility Network Only)
55
+ ### Download Node JS 13.5 or later
5
56
 
6
57
  https://nodejs.org/en/
7
58
 
8
- ## Open command prompt and run this command
59
+ ### Open command prompt and run this command
9
60
 
10
61
  ```bash
11
62
  npm install -g un-cli
12
63
  ```
13
64
 
14
- ## Once installed here is how you connect
65
+ ### Once installed here is how you connect
15
66
 
16
67
  ```bash
17
68
  > uncli --portal https://utilitynetwork.esri.com/portal --service NapervilleElectric_SQLServer --user tester --password tester.108 --verify true
@@ -67,7 +118,7 @@ uncli> help
67
118
 
68
119
 
69
120
 
70
- ## Execute bulk of commands
121
+ ### Execute bulk of commands
71
122
  Create a commands.txt file and type in the commands in that file
72
123
  command.txt
73
124
  ```text
@@ -77,32 +128,3 @@ export subnetworks --new
77
128
 
78
129
 
79
130
  > uncli --portal https://utilitynetwork.esri.com/portal --service NapervilleElectric_SQLServer --user tester --password tester.108 --file commands.txt --verify true
80
-
81
- ## Server Log web parser
82
- This tool also provides a way to parse server logs and view them for each utility network and geodatabase function
83
-
84
- To install on IIS follow these steps: This server assume your machine name where the Webadaptor lives is `utilitynetwork.esri.com`
85
-
86
- - Login to machine where you have the webadaptor
87
- - Create a folder called `log` in `c:\inetpub\wwwroot`
88
- - Copy the entire content of the repro https://github.com/hussein-nasser/uncli to c:\inetpub\wwwroot\log
89
- - Open IIS (Internet Information Services)
90
- - Open MIME Types
91
- - Under action click Add
92
- - under file extension type `.mjs` and under MIME Type write `application/javascript`
93
- - Restart IIS
94
- - (OPTIONAL only change when your webadaptor is not /portal) In c:\inetpub\wwwroot\log edit the `index.html` and find this line of code
95
- - Update the JSON object with the correct URL, for example if your webadaptor is https://utilitynetwork.esri.com/portal set the "portal" to be that. You don't have to update the referer it will be automatically calculated it.
96
- - (Optional) if you have multiple federated server , you have to set the correct one you want to query admin api for in the `"server"` parameter below.
97
-
98
- ```js
99
- let parameters = {
100
- "user": "unadmin",
101
- "password": "",
102
- "portal": "",
103
- "service": "",
104
- "referer": "",
105
- "server": undefined
106
- }
107
- ```
108
- - Save the HTML and then visit `https://utilitynetwork.esri.com/log` put in your username and password and login to use the parser
package/examples.txt ADDED
@@ -0,0 +1,4 @@
1
+ export subnetworks --all --resulttype [{"type":"features","includeGeometry":true,"includePropagatedValues":false,"includeDomainDescriptions":true,"networkAttributeNames":["Source ID","E:Riser"],"diagramTemplateName":"","resultTypeFields":[{"networkSourceId":14,"fieldName":"GLOBALID"},{"networkSourceId":15,"fieldName":"CLUSTERKEY"},{"networkSourceId":9,"fieldName":"LIFECYCLESTATUS"},{"networkSourceId":4,"fieldName":"ASSETGROUP"},{"networkSourceId":12,"fieldName":"ASSETGROUP"}]},{"type":"connectivity","includeGeometry":true,"includePropagatedValues":false,"includeDomainDescriptions":true,"networkAttributeNames":[],"diagramTemplateName":"","resultTypeFields":[]},{"type":"associations","includeGeometry":false,"includePropagatedValues":false,"includeDomainDescriptions":true,"networkAttributeNames":[],"diagramTemplateName":"","resultTypeFields":[]}]
2
+ update subnewtorks --all
3
+ topology --validate
4
+ trace --subnetwork test
package/index.html CHANGED
@@ -54,7 +54,7 @@
54
54
  <td>Method Name</td>
55
55
  <td><input id = 'txtMethodName' type = 'text'></td>
56
56
  <td>RequestID</td>
57
- <td colspan =3><input id = 'txtRequestId' type = 'text'></td>
57
+ <td colspan =3><input id = 'txtRequestId' type = 'text' style="width:250px"></td>
58
58
  </tr>
59
59
  </table>
60
60
 
@@ -69,13 +69,15 @@
69
69
  <button id = 'btnApplyEditsLogs'>ApplyEdits Logs</button>
70
70
  <button id = 'btnQueryLogs'>Query Logs</button>
71
71
  <button id = 'btnReconcileLogs'>Reconcile Logs</button>
72
+ <button id = 'btnstartEditingLogs'>StartEditing Logs</button>
72
73
  <button id = 'btnstopEditingLogs'>StopEditing Logs</button>
73
- <button id = 'btnWaitLogs'>Wait Logs</button>
74
+ <button id = 'btnWaitLogs'>Startup and Wait Logs</button>
74
75
  <button id = 'btnDownloadLogs'>Raw Logs</button>
75
76
  </td>
76
77
 
77
78
  </tr>
78
79
  <tr><td colspan=9><small>Elapsed time is in minutes:seconds:milliseconds</small></td></tr>
80
+ <tr><td colspan=9><small>To capture the logs effectively, enable debug logging from server manager, login as admin, run the operation (e.g. edit in Pro) and click the corresponding logs to load.</small></td></tr>
79
81
  </table>
80
82
 
81
83
  <table id = 'tblResult' border =1 cellpadding = 4 cellspacing = 4 style="text-align:left">
@@ -170,6 +172,7 @@
170
172
  document.getElementById("btnDownloadLogs").disabled = false
171
173
  document.getElementById("btnReconcileLogs").disabled = false
172
174
  document.getElementById("btnstopEditingLogs").disabled = false
175
+ document.getElementById("btnstartEditingLogs").disabled = false
173
176
  document.getElementById("btnWaitLogs").disabled = false
174
177
 
175
178
 
@@ -239,7 +242,9 @@
239
242
 
240
243
  x = /Moment:.*\r\n/.exec(m.message);
241
244
  if (x && x.length > 0) newMessage.moment = x[0].replace("Moment:", "").replace("\r\n", "") * 1000000
242
-
245
+
246
+ x = /Moment:\s*([\d.]+)/.exec(m.message);
247
+ if (x) newMessage.moment = parseFloat(x[1]) * 1000000;
243
248
 
244
249
  }
245
250
  catch(ex){
@@ -261,8 +266,6 @@
261
266
  cTime.textContent = "Time"
262
267
  const cUser = document.createElement("th");
263
268
  cUser.textContent = "User"
264
- const cMethod = document.createElement("th");
265
- cMethod.textContent = "Method"
266
269
  const cVersion = document.createElement("th");
267
270
  cVersion.textContent = "Version"
268
271
  const cMoment = document.createElement("th");
@@ -273,6 +276,8 @@
273
276
  cTraceType.textContent = "Trace Type"
274
277
  const cTraceTime = document.createElement("th");
275
278
  cTraceTime.textContent = "Trace Time"
279
+ const cReadAmp = document.createElement("th");
280
+ cReadAmp.textContent = "Elements / Pages"
276
281
  const cRequestId = document.createElement("th");
277
282
  cRequestId.textContent = "RequestId"
278
283
  const cLog = document.createElement("th");
@@ -280,11 +285,11 @@
280
285
  header.appendChild (cService)
281
286
  header.appendChild (cTime)
282
287
  header.appendChild (cUser)
283
- header.appendChild (cMethod)
284
288
  header.appendChild (cVersion)
285
289
  header.appendChild (cMoment)
286
290
  header.appendChild (cTraceType)
287
291
  header.appendChild (cTraceTime)
292
+ header.appendChild (cReadAmp)
288
293
  header.appendChild (cRequestId)
289
294
  header.appendChild (cElapsedMS)
290
295
 
@@ -306,6 +311,8 @@
306
311
  cTraceType.textContent = m.traceType
307
312
  const cTraceTime = document.createElement("td");
308
313
  cTraceTime.textContent = msToMinSecMs(m.traceTime)
314
+ const cReadAmp = document.createElement("td");
315
+ cReadAmp.textContent = ParseTraceReadAmplication(m.message)
309
316
  const cRequestId = document.createElement("td");
310
317
  cRequestId.textContent = m.requestID
311
318
  const cVersion = document.createElement("td");
@@ -319,11 +326,11 @@
319
326
  logRow.appendChild (cService)
320
327
  logRow.appendChild (cTime)
321
328
  logRow.appendChild (cUser)
322
- logRow.appendChild (cMethod)
323
329
  logRow.appendChild (cVersion)
324
330
  logRow.appendChild (cMoment)
325
331
  logRow.appendChild (cTraceType)
326
332
  logRow.appendChild (cTraceTime)
333
+ logRow.appendChild (cReadAmp)
327
334
  logRow.appendChild (cRequestId)
328
335
  logRow.appendChild (cElapsedMS)
329
336
 
@@ -379,9 +386,16 @@
379
386
  let x ;
380
387
  x = /Extent:.*\r\n/.exec(m.message);
381
388
  if (x && x.length > 0) m.extent = x[0].replace("Extent:", "").replace("\r\n", "")
389
+
390
+ x = /"extent":\{[^}]+\}/.exec(m.message);
391
+ if (x) m.extent = x[0].replace(`"extent":`,"")
392
+
382
393
  x = /Version name:.*\r\n/.exec(m.message);
383
394
  if (x && x.length > 0) m.versionName = x[0].replace("Version name:", "").replace("\r\n", "")
384
395
 
396
+ x = /Version name:(.*)/.exec(m.message);
397
+ if (x) m.versionName = x[1].trim();
398
+
385
399
  let re = new RegExp(`Network built. [-+]?([0-9]*\\.[0-9]+|[0-9]+) seconds \\([-+]?([0-9]*\\.[0-9]+|[0-9]+) total\\)`)
386
400
  let res = re.exec(m.message)
387
401
 
@@ -510,6 +524,7 @@
510
524
 
511
525
  const cRequestId = document.createElement("th");
512
526
  cRequestId.textContent = "RequestId"
527
+
513
528
  const cLog = document.createElement("th");
514
529
  cLog.textContent = "Full Log"
515
530
 
@@ -547,6 +562,12 @@
547
562
 
548
563
  const cRequestId = document.createElement("td");
549
564
  cRequestId.textContent = m.requestID;
565
+ cRequestId.style.color = "blue";
566
+ cRequestId.style.textDecoration = "underline";
567
+ cRequestId.style.cursor = "pointer";
568
+ cRequestId.style.fontOpticalSizing
569
+ cRequestId.addEventListener("click", e=> viewRawLogs( m.requestID ) );
570
+
550
571
  const cLog = document.createElement("td");
551
572
  cLog.textContent = "..."
552
573
  cLog.fullLog = m.message;
@@ -678,6 +699,12 @@ async function loadUpdateSubnetworkLogs () {
678
699
  cSubnetworkName.textContent = m.subnetworkName
679
700
  const cRequestId = document.createElement("td");
680
701
  cRequestId.textContent = m.requestID
702
+ cRequestId.style.color = "blue";
703
+ cRequestId.style.textDecoration = "underline";
704
+ cRequestId.style.cursor = "pointer";
705
+ cRequestId.style.fontOpticalSizing
706
+ cRequestId.addEventListener("click", e=> viewRawLogs( m.requestID ) );
707
+
681
708
  const cLog = document.createElement("td");
682
709
  cLog.textContent = "..."
683
710
  cLog.fullLog = m.message;
@@ -719,7 +746,7 @@ async function loadAttributeRules () {
719
746
 
720
747
  const arMessages = filterMessages(allMessages)
721
748
  .filter(m => m.message.indexOf("Attribute rule executed: ") > -1)
722
- .map (m => JSON.parse(m.message.replace("Attribute rule executed: ", "")))
749
+ .map (m => decodeAndParseJSON(m.message.replace("Attribute rule executed: ", "")))
723
750
  .map( m => {
724
751
  m["Elapsed Time (ms)"] = Math.round(m["Elapsed Time"]*1000000)/1000
725
752
  // m["Arcade Evaluation Time:"] = Math.round(m["Arcade Evaluation Time:"]*1000,6)
@@ -1016,7 +1043,8 @@ console.log(`Querying applyEdits logs for ${parameters.service} for the last ${m
1016
1043
  if (m.message.indexOf("GraphicFeatureServer::HandleRESTRequest ## inputJSON ") > -1)
1017
1044
  {
1018
1045
  applyEditslogs[m.requestID].message = m.message.replace("GraphicFeatureServer::HandleRESTRequest ## inputJSON = ","")
1019
- const applyEditsPayload = JSON.parse(applyEditslogs[m.requestID].message)
1046
+ applyEditslogs[m.requestID].message = decodeHTMLEntities(applyEditslogs[m.requestID].message)
1047
+ const applyEditsPayload = decodeAndParseJSON(applyEditslogs[m.requestID].message)
1020
1048
  applyEditslogs[m.requestID].gdbVersion = applyEditsPayload.gdbVersion
1021
1049
  applyEditslogs[m.requestID].ids = [...new Set(applyEditsPayload.edits.reduce ( (prev, cur) => {prev.push(cur.id); return prev}, []) )];
1022
1050
  }
@@ -1066,6 +1094,13 @@ console.log(`Querying applyEdits logs for ${parameters.service} for the last ${m
1066
1094
  const cRequestId = document.createElement("td");
1067
1095
  cRequestId.textContent = m.requestID
1068
1096
 
1097
+ cRequestId.style.color = "blue";
1098
+ cRequestId.style.textDecoration = "underline";
1099
+ cRequestId.style.cursor = "pointer";
1100
+ cRequestId.style.fontOpticalSizing
1101
+ cRequestId.addEventListener("click", e=> viewRawLogs( m.requestID ) );
1102
+
1103
+
1069
1104
  const cLog = document.createElement("td");
1070
1105
  const cLogText = document.createElement("input")
1071
1106
  cLogText.type = "text"
@@ -1097,6 +1132,7 @@ console.log(`Querying applyEdits logs for ${parameters.service} for the last ${m
1097
1132
 
1098
1133
  async function stopEditingLogs () {
1099
1134
 
1135
+
1100
1136
  //build table
1101
1137
  const tblResult = document.getElementById("tblResult");
1102
1138
  //clear
@@ -1109,7 +1145,7 @@ parameters.service = cmbService.options[cmbService.selectedIndex].text
1109
1145
  let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1110
1146
 
1111
1147
 
1112
- console.log(`Querying stop editing logs for ${parameters.service} for the last ${mins} minutes ...`)
1148
+ console.log(`Querying start editing logs for ${parameters.service} for the last ${mins} minutes ...`)
1113
1149
 
1114
1150
  //startTime is the most recent
1115
1151
  //endTime is the oldest
@@ -1158,20 +1194,22 @@ console.log(`Querying stop editing logs for ${parameters.service} for the last $
1158
1194
  const queryLogs = {}
1159
1195
  //sort by time
1160
1196
  allMessages = allMessages.sort ( (m1, m2) => m2.time - m1.time )
1197
+ // allMessages = allMessages.filter( m => m.methodName.indexOf("Geodatabase.FeatureDataset.StartEditing") > -1 )
1161
1198
  allMessages.forEach (m => {
1162
1199
 
1163
1200
  if (!queryLogs[m.requestID])
1164
1201
  queryLogs[m.requestID] = {"message": "Time,Method,Elapsed_ms,Message"}
1165
1202
 
1166
- queryLogs[m.requestID].message += "\r\n" + m.time + "," + m.methodName + "," + Math.round(m.elapsed*1000) + "," + m.message
1203
+ if (m.methodName.indexOf("Geodatabase.FeatureDataset.StopEditing") > -1)
1204
+ queryLogs[m.requestID].message += "\r\n" + m.time + "," + m.methodName + "," + Math.round(m.elapsed*1000) + "," + m.message
1167
1205
 
1168
1206
  //get elapsed
1169
1207
  //check for async (method GPReconcileVersionAsync::Execute)
1170
1208
  //sync
1171
1209
  //VersionManagementServer::HandleREST_ReconcileOperation
1172
1210
  //message Returned moment:
1173
- if ( m.methodName.indexOf("VersionManagementServer::HandleREST_StopEditingOperation") > -1
1174
- && m.message.indexOf("End StopEditing") > -1
1211
+ if ( m.methodName.indexOf("Geodatabase.FeatureDataset.StopEditing") > -1
1212
+ && m.message.indexOf("Starting editing") > -1
1175
1213
  )
1176
1214
  {
1177
1215
  queryLogs[m.requestID].elapsed = m.elapsed
@@ -1180,13 +1218,13 @@ console.log(`Querying stop editing logs for ${parameters.service} for the last $
1180
1218
  queryLogs[m.requestID].time = m.time
1181
1219
  queryLogs[m.requestID].requestID = m.requestID
1182
1220
  queryLogs[m.requestID].methodName = m.methodName.replace("VersionManagementServer::HandleREST_","")
1183
-
1221
+ queryLogs[m.requestID].textMessage = m.message
1184
1222
  }
1185
1223
 
1186
1224
  if (m.message.indexOf("In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=") > -1)
1187
1225
  {
1188
- let v = m.message.replace(": In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=","")
1189
- v = v.substr(v.indexOf("{"))
1226
+ let v = m.message.replace(" In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=","")
1227
+ v = v.substr(v.indexOf(":")+1)
1190
1228
  queryLogs[m.requestID].gdbVersion =v
1191
1229
 
1192
1230
  }
@@ -1195,6 +1233,7 @@ console.log(`Querying stop editing logs for ${parameters.service} for the last $
1195
1233
 
1196
1234
  })
1197
1235
 
1236
+ /*
1198
1237
  allMessages = []
1199
1238
 
1200
1239
  Object.keys(queryLogs).forEach(k =>
@@ -1205,14 +1244,17 @@ console.log(`Querying stop editing logs for ${parameters.service} for the last $
1205
1244
 
1206
1245
  })
1207
1246
 
1208
-
1247
+ */
1209
1248
 
1210
1249
  console.log ("Filtering messages...")
1211
-
1250
+ allMessages = allMessages.filter( m => m.methodName.indexOf("Geodatabase.FeatureDataset.StopEditing") > -1 )
1251
+
1212
1252
  allMessages = filterMessages(allMessages)
1213
1253
  .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
1214
1254
 
1215
1255
  allMessages.forEach (m => {
1256
+
1257
+
1216
1258
  const logRow = document.createElement("tr");
1217
1259
 
1218
1260
  const cService = document.createElement("th");
@@ -1225,21 +1267,27 @@ console.log(`Querying stop editing logs for ${parameters.service} for the last $
1225
1267
  cUser.textContent = m.user
1226
1268
 
1227
1269
  const cVersion = document.createElement("td");
1228
- cVersion.textContent = m.gdbVersion
1270
+ cVersion.textContent = queryLogs[m.requestID].gdbVersion
1229
1271
 
1230
1272
  const cMethodName = document.createElement("td");
1231
1273
  cMethodName.textContent = m.methodName
1232
1274
 
1233
1275
  const cRequestId = document.createElement("td");
1234
- cRequestId.textContent = m.requestID
1235
-
1276
+ cRequestId.textContent = m.requestID
1277
+
1278
+ cRequestId.style.color = "blue";
1279
+ cRequestId.style.textDecoration = "underline";
1280
+ cRequestId.style.cursor = "pointer";
1281
+ cRequestId.style.fontOpticalSizing
1282
+ cRequestId.addEventListener("click", e=> viewRawLogs( m.requestID ) );
1283
+
1236
1284
  const cTotalTime = document.createElement("td");
1237
1285
  cTotalTime.textContent = msToMinSecMs(m.elapsed*1000 )
1238
1286
  const cLog = document.createElement("td");
1239
- cLog.textContent = "..."
1240
- cLog.title = "Click to copy full stopediting log"
1241
- cLog.fullLog = m.message;
1242
- cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
1287
+ cLog.textContent = m.message
1288
+ // cLog.title = "Click to copy full startediting log"
1289
+ // cLog.fullLog = m.message;
1290
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
1243
1291
 
1244
1292
  //cLog.fullLog = m.payLoad;
1245
1293
  //cLog.title = m.payLoad + "\nClick to copy"
@@ -1267,6 +1315,197 @@ console.log(`Querying stop editing logs for ${parameters.service} for the last $
1267
1315
 
1268
1316
 
1269
1317
 
1318
+ async function viewRawLogs(requestId){
1319
+
1320
+ const txtRequestId = document.getElementById("txtRequestId")
1321
+ txtRequestId.value = requestId;
1322
+ document.getElementById("btnDownloadLogs").click();
1323
+
1324
+
1325
+ }
1326
+
1327
+
1328
+ async function startEditingLogs () {
1329
+
1330
+ //build table
1331
+ const tblResult = document.getElementById("tblResult");
1332
+ //clear
1333
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1334
+
1335
+
1336
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
1337
+
1338
+
1339
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
1340
+
1341
+
1342
+ console.log(`Querying start editing logs for ${parameters.service} for the last ${mins} minutes ...`)
1343
+
1344
+ //startTime is the most recent
1345
+ //endTime is the oldest
1346
+
1347
+
1348
+ //page query the admin log , search for /stopediting logs by methodname
1349
+ let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003,17003], "", "DEBUG")
1350
+
1351
+
1352
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
1353
+
1354
+ let i =0;
1355
+
1356
+ const header = document.createElement("tr");
1357
+ const cService = document.createElement("th");
1358
+ cService.textContent = "Source"
1359
+ const cTime = document.createElement("th");
1360
+ cTime.textContent = "Time"
1361
+ const cUser = document.createElement("th");
1362
+ cUser.textContent = "User"
1363
+ const cVersion = document.createElement("th");
1364
+ cVersion.textContent = "Version"
1365
+ const cMethodName = document.createElement("th");
1366
+ cMethodName.textContent = "MethodName"
1367
+ const cRequestId = document.createElement("th");
1368
+ cRequestId.textContent = "RequestId"
1369
+ const cTotalTime = document.createElement("th");
1370
+ cTotalTime.title = "Total time startEditing took"
1371
+ cTotalTime.textContent = "Total Time"
1372
+
1373
+
1374
+ const cLog = document.createElement("th");
1375
+ cLog.textContent = "StartEditing details"
1376
+ header.appendChild (cService)
1377
+ header.appendChild (cTime)
1378
+ header.appendChild (cUser)
1379
+ header.appendChild (cVersion)
1380
+ header.appendChild (cMethodName)
1381
+ header.appendChild (cRequestId)
1382
+ header.appendChild (cTotalTime)
1383
+
1384
+ header.appendChild (cLog)
1385
+ tblResult.appendChild(header)
1386
+
1387
+ //build out the dictionary, key is request id, value is another dictionary
1388
+ const queryLogs = {}
1389
+ //sort by time
1390
+ allMessages = allMessages.sort ( (m1, m2) => m2.time - m1.time )
1391
+ // allMessages = allMessages.filter( m => m.methodName.indexOf("Geodatabase.FeatureDataset.StartEditing") > -1 )
1392
+ allMessages.forEach (m => {
1393
+
1394
+ if (!queryLogs[m.requestID])
1395
+ queryLogs[m.requestID] = {"message": "Time,Method,Elapsed_ms,Message"}
1396
+
1397
+ if (m.methodName.indexOf("Geodatabase.FeatureDataset.StartEditing") > -1)
1398
+ queryLogs[m.requestID].message += "\r\n" + m.time + "," + m.methodName + "," + Math.round(m.elapsed*1000) + "," + m.message
1399
+
1400
+ //get elapsed
1401
+ //check for async (method GPReconcileVersionAsync::Execute)
1402
+ //sync
1403
+ //VersionManagementServer::HandleREST_ReconcileOperation
1404
+ //message Returned moment:
1405
+ if ( m.methodName.indexOf("Geodatabase.FeatureDataset.StartEditing") > -1
1406
+ && m.message.indexOf("Starting editing") > -1
1407
+ )
1408
+ {
1409
+ queryLogs[m.requestID].elapsed = m.elapsed
1410
+ queryLogs[m.requestID].source = m.source.replace(".MapServer", "")
1411
+ queryLogs[m.requestID].user = m.user
1412
+ queryLogs[m.requestID].time = m.time
1413
+ queryLogs[m.requestID].requestID = m.requestID
1414
+ queryLogs[m.requestID].methodName = m.methodName.replace("VersionManagementServer::HandleREST_","")
1415
+ queryLogs[m.requestID].textMessage = m.message
1416
+ }
1417
+
1418
+ if (m.message.indexOf("In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=") > -1)
1419
+ {
1420
+ let v = m.message.replace(" In WorkspaceInfo::GetVersionedWorkspaceInfo : Cache hit for versionOrBranchName=","")
1421
+ v = v.substr(v.indexOf(":")+1)
1422
+ queryLogs[m.requestID].gdbVersion =v
1423
+
1424
+ }
1425
+
1426
+
1427
+
1428
+ })
1429
+
1430
+ /*
1431
+ allMessages = []
1432
+
1433
+ Object.keys(queryLogs).forEach(k =>
1434
+ {
1435
+ const m = queryLogs[k]
1436
+ if (m.methodName)
1437
+ allMessages.push(m)
1438
+
1439
+ })
1440
+
1441
+ */
1442
+
1443
+ console.log ("Filtering messages...")
1444
+ allMessages = allMessages.filter( m => m.methodName.indexOf("Geodatabase.FeatureDataset.StartEditing") > -1 )
1445
+
1446
+ allMessages = filterMessages(allMessages)
1447
+ .sort( (m1,m2) => Math.round(m2.elapsed*1000) -Math.round(m1.elapsed*1000))
1448
+
1449
+ allMessages.forEach (m => {
1450
+
1451
+
1452
+ const logRow = document.createElement("tr");
1453
+
1454
+ const cService = document.createElement("th");
1455
+ cService.textContent = m.source
1456
+
1457
+ const cTime = document.createElement("td");
1458
+ cTime.textContent = new Date(m.time).toLocaleString()
1459
+
1460
+ const cUser = document.createElement("td");
1461
+ cUser.textContent = m.user
1462
+
1463
+ const cVersion = document.createElement("td");
1464
+ cVersion.textContent = queryLogs[m.requestID].gdbVersion
1465
+
1466
+ const cMethodName = document.createElement("td");
1467
+ cMethodName.textContent = m.methodName
1468
+
1469
+ const cRequestId = document.createElement("td");
1470
+ cRequestId.textContent = m.requestID
1471
+ cRequestId.style.color = "blue";
1472
+ cRequestId.style.textDecoration = "underline";
1473
+ cRequestId.style.cursor = "pointer";
1474
+ cRequestId.style.fontOpticalSizing
1475
+ cRequestId.addEventListener("click", e=> viewRawLogs( m.requestID ) );
1476
+
1477
+ const cTotalTime = document.createElement("td");
1478
+ cTotalTime.textContent = msToMinSecMs(m.elapsed*1000 )
1479
+ const cLog = document.createElement("td");
1480
+ cLog.textContent = m.message
1481
+ // cLog.title = "Click to copy full startediting log"
1482
+ // cLog.fullLog = m.message;
1483
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
1484
+
1485
+ //cLog.fullLog = m.payLoad;
1486
+ //cLog.title = m.payLoad + "\nClick to copy"
1487
+ // cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); e.target.selectionStart = 0; e.target.selectionEnd = e.target.value.length;
1488
+ // alert("Copied to clipboard") })
1489
+ logRow.appendChild (cService)
1490
+ logRow.appendChild (cTime)
1491
+ logRow.appendChild (cUser)
1492
+ logRow.appendChild (cVersion)
1493
+ logRow.appendChild (cMethodName)
1494
+ logRow.appendChild (cRequestId)
1495
+ logRow.appendChild (cTotalTime)
1496
+
1497
+ logRow.appendChild (cLog)
1498
+ tblResult.appendChild(logRow)
1499
+ });
1500
+
1501
+ addCSV(allMessages)
1502
+
1503
+
1504
+
1505
+ }
1506
+
1507
+
1508
+
1270
1509
 
1271
1510
 
1272
1511
  async function waitLogs () {
@@ -1642,7 +1881,8 @@ console.log(`Querying query logs for ${parameters.service} for the last ${mins}
1642
1881
  if (m.message.indexOf("GraphicFeatureServer::HandleRESTRequest ## inputJSON = ") > -1)
1643
1882
  {
1644
1883
  queryLogs[m.requestID].message = m.message.replace("GraphicFeatureServer::HandleRESTRequest ## inputJSON = ","")
1645
- const queryPayload = JSON.parse(queryLogs[m.requestID].message)
1884
+ queryLogs[m.requestID].message = decodeHTMLEntities(queryLogs[m.requestID].message)
1885
+ const queryPayload = decodeAndParseJSON(queryLogs[m.requestID].message)
1646
1886
  queryLogs[m.requestID].gdbVersion = queryPayload.gdbVersion
1647
1887
  queryLogs[m.requestID].moment = queryPayload.historicMoment
1648
1888
  queryLogs[m.requestID].methodName = m.methodName;
@@ -1942,6 +2182,9 @@ function numberWithCommas(x) {
1942
2182
  btnstopEditingLogs.disabled = true
1943
2183
 
1944
2184
 
2185
+ const btnstartEditingLogs = document.getElementById("btnstartEditingLogs");
2186
+ btnstartEditingLogs.addEventListener("click", e => startEditingLogs())
2187
+ btnstartEditingLogs.disabled = true
1945
2188
 
1946
2189
  const btnWait = document.getElementById("btnWaitLogs");
1947
2190
  btnWait.addEventListener("click", e => waitLogs())
@@ -2144,6 +2387,12 @@ function numberWithCommas(x) {
2144
2387
  })
2145
2388
  }
2146
2389
 
2390
+
2391
+ function decodeAndParseJSON (x) {
2392
+ const y = decodeHTMLEntities(x);
2393
+ return JSON.parse(y);
2394
+ }
2395
+
2147
2396
  function decodeHTMLEntities (x) {
2148
2397
  const decodedString = document.createElement('div');
2149
2398
  decodedString.innerHTML = x;
@@ -2218,6 +2467,14 @@ function numberWithCommas(x) {
2218
2467
 
2219
2468
  allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf(messageFilter) > -1 && m.methodName.indexOf(methodFilter) > -1))
2220
2469
  }
2470
+ //DECODE html for all messages.
2471
+ logger.info(`Decoding HTML entities ${allMessages.length}`);
2472
+
2473
+ allMessages = allMessages.map(m=> {
2474
+ m.message = decodeHTMLEntities(m.message)
2475
+ return m
2476
+ })
2477
+
2221
2478
  logger.info(`Completed aggregation total messages ${allMessages.length}`);
2222
2479
 
2223
2480
  return allMessages
@@ -2225,6 +2482,58 @@ function numberWithCommas(x) {
2225
2482
  }
2226
2483
 
2227
2484
 
2485
+
2486
+ function ParseTraceReadAmplication (traceLog) {
2487
+
2488
+ try {
2489
+
2490
+
2491
+ const text = traceLog;
2492
+ const traversedMatch = text.match(/Total\s+#\s*Traversed\s+Elements:\s*([\d,]+)/i);
2493
+
2494
+ const traversedElements = traversedMatch
2495
+ ? parseInt(traversedMatch[1].replace(/,/g, ''), 10)
2496
+ : 0;
2497
+
2498
+ let minPagesRead = traversedElements / 1024;
2499
+ if (minPagesRead <= 1024) minPagesRead =1;
2500
+
2501
+
2502
+ // -------------------------------------------------------------------
2503
+ // Sum all Cache misses values
2504
+ // -------------------------------------------------------------------
2505
+ let actualPagesRead = 0;
2506
+
2507
+ // Match rows that begin with a table name and then a cache miss number
2508
+ const cacheMissRegex =
2509
+ /^\s*[A-Za-z0-9:#()\-\s]+?\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+/gm;
2510
+
2511
+ let match;
2512
+
2513
+ while ((match = cacheMissRegex.exec(text)) !== null) {
2514
+ actualPagesRead += parseInt(match[1], 10);
2515
+ }
2516
+
2517
+
2518
+ let readAmp;
2519
+ if (actualPagesRead < minPagesRead)
2520
+ readAmp= "0%"
2521
+ else
2522
+ readAmp= Math.floor((actualPagesRead-minPagesRead)/actualPagesRead *100) + "%"
2523
+
2524
+ readAmp= numberWithCommas(traversedElements) + " / " + numberWithCommas(actualPagesRead)
2525
+
2526
+ console.log(`traversedElements = ${traversedElements}, minPagesRead = ${minPagesRead}, actualPagesRead = ${actualPagesRead} ,, readAmp=${readAmp}` );
2527
+
2528
+ return readAmp
2529
+ }
2530
+ catch(ex){
2531
+ console.error(ex)
2532
+ return "n/a";
2533
+ }
2534
+ }
2535
+
2536
+
2228
2537
 
2229
2538
 
2230
2539
  </script>
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.84";
10
+ let version = "0.0.86";
11
11
  const GENERATE_TOKEN_TIME_MIN = 30;
12
12
 
13
13
  let rl = null;
@@ -166,17 +166,21 @@ const inputs = {
166
166
  "subnetworks --deleted" : "Lists dirty and deleted subnetworks",
167
167
  "evaluate" : "Evaluate in parallel",
168
168
  "trace --subnetwork <subnetwork>": "Traces input subnetwork and returns the time and number of elements returned .",
169
+ "trace --all": "Traces all subnetworks.",
169
170
  "topology" : "Displays the topology status",
170
171
  "topology --disable" : "Disable topology",
171
172
  "topology --enable" : "Enable topology",
172
173
  "topology --validate" : "Validate topology (full extent)",
173
174
  "update subnetworks --subnetwork": "Update the input subnetwork synchronously",
174
175
  "update subnetworks --all": "Update all dirty subnetworks synchronously",
176
+ "update subnetworks --all --async": "Update all dirty subnetworks asynchronously",
175
177
  "update subnetworks --deleted": "Update all deleted dirty subnetworks synchronously",
176
178
  "update subnetworks --all --async": "Update all dirty subnetworks asynchronously",
177
179
  "export subnetworks --all [--folder]": "Export all subnetworks with ACK --folder where exported files are saved",
178
180
  "export subnetworks --new [--folder]": "Export all subnetworks with ACK that haven't been exported --folder where exported files are saved",
179
181
  "export subnetworks --deleted": "Export all subnetworks with ACK that are deleted ",
182
+ "export subnetworks --all [--resulttype]": "Export all subnetworks with ACK --resulttype is a json configuration",
183
+
180
184
  "updateisconnected": "Run update is connected ",
181
185
  "versions": "List all versions available to the current logged in user.",
182
186
  "versions --summary": "Summary of versions.",
@@ -792,8 +796,8 @@ const inputs = {
792
796
  logger.info(`Result from submitting job ${JSON.stringify(subnetworkResult)}`)
793
797
  }
794
798
  },
795
- "^export subnetworks --all --folder .*$|^export subnetworks --all$" : async input => {
796
-
799
+ "^export subnetworks --all --folder .*$|^export subnetworks --all$|^export subnetworks --all --resulttype .*$" : async input => {
800
+
797
801
  let subnetworks
798
802
  let sort = "asc";
799
803
  if (input.indexOf("--desc") > 0) sort = "desc"
@@ -802,6 +806,27 @@ const inputs = {
802
806
  let inputDir = "Exported"
803
807
  if (file != null && file.length > 0)
804
808
  inputDir = file[0].replace("--folder ", "")
809
+
810
+ //default resulttype
811
+ let resultType = null;
812
+
813
+ const rt = input.match(/--resulttype .*/gm)
814
+ if (rt != null && v.length > 0)
815
+ resultType = rt[0].replace("--resulttype ", "")
816
+
817
+ logger.info(resultType)
818
+
819
+ try
820
+ {
821
+ resultType = JSON.parse(resultType)
822
+ }
823
+ catch(ex)
824
+ {
825
+ logger.error("Can't parse resulttype" + ex)
826
+ return;
827
+ }
828
+
829
+
805
830
  //create directory if doesn't exists
806
831
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
807
832
  let exportedSubnetworks = [];
@@ -823,7 +848,7 @@ const inputs = {
823
848
 
824
849
  const fromDate = new Date();
825
850
 
826
- const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
851
+ const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false, resultType);
827
852
 
828
853
  //code
829
854
  exportedSubnetworks.push("'" + v(f.attributes,"subnetworkName") + "'")
@@ -845,10 +870,10 @@ const inputs = {
845
870
  //although the response is json, its easier to treat it as text (handle error cases) since we will only write it to disk.
846
871
  // if we want to do something with the response then make it json
847
872
  const jsonExport = await subContent.text();
848
- fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, jsonExport)
873
+ fs.writeFileSync(`${inputDir}/${v(f.attributes,"domainNetworkName")}_${v(f.attributes,"tierName")}_${subnetworkName}.json`, jsonExport)
849
874
 
850
875
 
851
- logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
876
+ logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${v(f.attributes,"domainNetworkName")}_${v(f.attributes,"tierName")}_${subnetworkName}.json`)
852
877
 
853
878
  }
854
879
  }
@@ -856,7 +881,55 @@ const inputs = {
856
881
 
857
882
  },
858
883
 
884
+ "^export subnetworks --all --async --folder .*$|^export subnetworks --all --async$|^export subnetworks --all --async --resulttype .*$" : async input => {
885
+
886
+ let subnetworks
887
+ let sort = "asc";
888
+ if (input.indexOf("--desc") > 0) sort = "desc"
889
+ //create folder
890
+ const file = input.match(/--folder .*/gm)
891
+ let inputDir = "Exported"
892
+ if (file != null && file.length > 0)
893
+ inputDir = file[0].replace("--folder ", "")
894
+
895
+
896
+ //default resulttype
897
+ let resultType = null;
898
+
899
+ const rt = input.match(/--resulttype .*/gm)
900
+ if (rt != null && v.length > 0)
901
+ resultType = rt[0].replace("--resulttype ", "")
902
+
903
+ logger.info(resultType)
904
+
905
+ //create directory if doesn't exists
906
+ if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
907
+ let exportedSubnetworks = [];
908
+
909
+ do {
910
+
911
+ let exportedSubnetworksWhereClause = ""
912
+
913
+ if (exportedSubnetworks.length > 0 )
914
+ exportedSubnetworksWhereClause = " AND SUBNETWORKNAME NOT IN (" + exportedSubnetworks.join(",") + ")"
915
+
916
+ logger.info("Querying all subnetworks that are clean.");
917
+ subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=0 " + exportedSubnetworksWhereClause,`domainnetworkname ${sort},tiername ${sort},subnetworkname ${sort}`);
918
+ logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
919
+ for (let i = 0; i < subnetworks.features.length; i++) {
920
+ const f = subnetworks.features[i]
921
+ const subnetworkName = v(f.attributes,"subnetworkName")
922
+ logger.info("Exporting subnetworks " + subnetworkName);
923
+
924
+
925
+ const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),true);
926
+ logger.info(`Result from submitting job ${JSON.stringify(subnetworkResult)}`)
859
927
 
928
+ }
929
+ }
930
+ while (subnetworks?.features?.length > 0)
931
+
932
+ },
860
933
  "^export subnetworks --new --folder .*$|^export subnetworks --new$" : async input => {
861
934
 
862
935
  //create folder
@@ -879,9 +952,11 @@ const inputs = {
879
952
  //fetch the json and write it to disk
880
953
  const subContent = await fetch(subnetworkResult.url);
881
954
  const jsonExport = await subContent.text();
882
- fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, JSON.stringify(jsonExport))
883
-
884
- logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
955
+ fs.writeFileSync(`${inputDir}/${v(f.attributes,"domainNetworkName")}_${v(f.attributes,"tierName")}_${subnetworkName}.json`, jsonExport)
956
+
957
+
958
+ logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${v(f.attributes,"domainNetworkName")}_${v(f.attributes,"tierName")}_${subnetworkName}.json`)
959
+
885
960
  }
886
961
 
887
962
 
@@ -968,19 +1043,68 @@ const inputs = {
968
1043
  logger.error(JSON.stringify(ex))
969
1044
  }
970
1045
  },
971
- "^export subnetworks --deleted$" : async input => {
1046
+
1047
+
1048
+
1049
+ "^trace --all": async input => {
1050
+ //get subnetwork name
1051
+ try {
1052
+
1053
+
1054
+ const inputDir= "Exported"
1055
+ let full = true;
1056
+
1057
+
1058
+ const subnetworks = await un.getSubnetworks();
1059
+ if (subnetworks.features.length === 0) {
1060
+ logger.info("No dirty subnetworks found.")
1061
+ return;
1062
+ }
1063
+
1064
+ const subs = subnetworks.features.map(a => a.attributes)
1065
+ const rowCount = subs.length;
1066
+ logger.info (`${numberWithCommas(rowCount)} subnetworks returned.`)
1067
+ for (let i = 0; i < subs.length ; i++)
1068
+ {
1069
+ const fromDate = new Date();
1070
+ const subnetworkName = v(subs[i],"subnetworkname")
1071
+ logger.info(`Tracing subnetwork ${subnetworkName}`);
1072
+ const result = await un.subnetworkTraceSimple(subnetworkName)
1073
+ if (result == null) {
1074
+ logger.info(`Subnetwork ${subnetworkName} doesn't exist`);
1075
+ return null;
1076
+ }
1077
+ const toDate = new Date();
1078
+ const timeRun = toDate.getTime() - fromDate.getTime();
1079
+ const newResult = {}
1080
+ newResult.duration = numberWithCommas(Math.round(timeRun)) + " ms"
1081
+ newResult.elementsCount = result.traceResults.elements.length;
1082
+ console.table(newResult)
1083
+
1084
+ }
1085
+
1086
+
1087
+
1088
+ }
1089
+ catch(ex){
1090
+ logger.error(JSON.stringify(ex))
1091
+ }
1092
+ },
1093
+
1094
+
1095
+ "^export subnetworks --deleted --folder" : async input => {
972
1096
 
973
1097
  //create folder
974
- const file = input.match(/-f .*/gm)
1098
+ const file = input.match(/--folder .*/gm)
975
1099
  let inputDir = "Exported"
976
1100
  if (file != null && file.length > 0)
977
- inputDir = file[0].replace("-f ", "")
1101
+ inputDir = file[0].replace("--folder ", "")
978
1102
  //create directory if doesn't exists
979
1103
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
980
1104
 
981
1105
 
982
1106
  logger.info("Querying all subnetworks that are clean and deleted.");
983
- let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty = 0 and isdeleted=1");
1107
+ let subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdeleted=1", "subnetworkname");
984
1108
  logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
985
1109
  for (let i = 0; i < subnetworks.features.length; i++) {
986
1110
  const f = subnetworks.features[i]
@@ -998,9 +1122,11 @@ const inputs = {
998
1122
  //fetch the json and write it to disk
999
1123
  const subContent = await fetch(subnetworkResult.url);
1000
1124
  const jsonExport = await subContent.text();
1001
- fs.writeFileSync(`${inputDir}/${subnetworkName}.json`, JSON.stringify(jsonExport))
1002
-
1003
- logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${subnetworkName}.json`)
1125
+ fs.writeFileSync(`${inputDir}/${v(f.attributes,"domainNetworkName")}_${v(f.attributes,"tierName")}_${subnetworkName}.json`, jsonExport)
1126
+
1127
+
1128
+ logger.info(`Result ${JSON.stringify(subnetworkResult)} written to file ${process.cwd()}/${inputDir}/${v(f.attributes,"domainNetworkName")}_${v(f.attributes,"tierName")}_${subnetworkName}.json`)
1129
+
1004
1130
  }
1005
1131
 
1006
1132
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "un-cli",
3
- "version": "0.0.84",
3
+ "version": "0.0.86",
4
4
  "description": "Command line interface for working with ArcGIS Utility Network Extension",
5
5
  "main": "index.mjs",
6
6
  "bin": {
@@ -280,6 +280,7 @@ export class UtilityNetwork {
280
280
  orderByFields: "DOMAINNETWORKNAME, TIERNAME, SUBNETWORKNAME",
281
281
  gdbVersion:this.gdbVersion,
282
282
  returnDistinctValues: true,
283
+ resultRecordCount: 20000,
283
284
  f: "json"
284
285
  }
285
286
 
@@ -1180,7 +1181,7 @@ export class UtilityNetwork {
1180
1181
  }
1181
1182
 
1182
1183
 
1183
- exportSubnetworks(domainNetworkName, tierName, subnetworkName, async=false) {
1184
+ exportSubnetworks(domainNetworkName, tierName, subnetworkName, async=false,resultTypes=null) {
1184
1185
 
1185
1186
  let thisObj = this;
1186
1187
  let tier = this.getTier(domainNetworkName, tierName);
@@ -1190,37 +1191,9 @@ export class UtilityNetwork {
1190
1191
  let ar = thisObj.featureServiceUrl.split("/");
1191
1192
  ar[ar.length-1]="UtilityNetworkServer";
1192
1193
  let exportsubnetworkUrl = ar.join("/") + "/exportSubnetwork"
1193
- const resultTypes = [
1194
- {
1195
- "type": "features",
1196
- "includeGeometry": true,
1197
- "includePropagatedValues": false,
1198
- "includeDomainDescriptions": true,
1199
- "networkAttributeNames": [
1200
- "Is subnetwork controller"
1201
- ],
1202
- "diagramTemplateName": "",
1203
- "resultTypeFields": []
1204
- },
1205
- {
1206
- "type": "connectivity",
1207
- "includeGeometry": true,
1208
- "includePropagatedValues": false,
1209
- "includeDomainDescriptions": true,
1210
- "networkAttributeNames": [],
1211
- "diagramTemplateName": "",
1212
- "resultTypeFields": []
1213
- },
1214
- {
1215
- "type": "associations",
1216
- "includeGeometry": false,
1217
- "includePropagatedValues": false,
1218
- "includeDomainDescriptions": true,
1219
- "networkAttributeNames": [],
1220
- "diagramTemplateName": "",
1221
- "resultTypeFields": []
1222
- }
1223
- ]
1194
+ if (!resultTypes)
1195
+ resultTypes = [{"type":"features","includeGeometry":true,"includePropagatedValues":false,"includeDomainDescriptions":true,"networkAttributeNames":["Is subnetwork controller"],"diagramTemplateName":"","resultTypeFields":[]},{"type":"connectivity","includeGeometry":true,"includePropagatedValues":false,"includeDomainDescriptions":true,"networkAttributeNames":[],"diagramTemplateName":"","resultTypeFields":[]},{"type":"associations","includeGeometry":false,"includePropagatedValues":false,"includeDomainDescriptions":true,"networkAttributeNames":[],"diagramTemplateName":"","resultTypeFields":[]}]
1196
+
1224
1197
  //traceConfiguration: JSON.stringify(subnetworkDef),
1225
1198
  let exportsubnetworkJson = {
1226
1199
  f: "json",
@@ -1231,7 +1204,7 @@ export class UtilityNetwork {
1231
1204
  exportAcknowledgement: true,
1232
1205
  allSubnetworksInTier: false,
1233
1206
  continueOnFailure: false,
1234
- traceConfiguration: subnetworkDef,
1207
+ traceConfiguration: JSON.stringify(subnetworkDef),
1235
1208
  async: async,
1236
1209
  gdbVersion:this.gdbVersion,
1237
1210
  resultTypes: JSON.stringify(resultTypes)