iguazio.dashboard-controls 1.2.0 → 1.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iguazio.dashboard-controls",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "main": "dist/js/iguazio.dashboard-controls.js",
5
5
  "description": "Collection of resources (such as CSS styles, fonts and images) and AngularJs 1.x components and services to share among different Iguazio repos.",
6
6
  "repository": {
@@ -169,6 +169,7 @@
169
169
  "LOGGER_DESTINATION": "Logger destination",
170
170
  "LOGGER_LEVEL": "Logger level",
171
171
  "LOGGING": "Logging",
172
+ "LOGS_LINES_LIMITATION": "Only the latest 10000 lines are displayed. <br> To access the full log history, download the complete log file.",
172
173
  "MAX": "Max",
173
174
  "MAX_REPLICAS": "Maximum number of replicas (default: {{default}})",
174
175
  "MAX_WORKERS": "Max Workers",
@@ -4,8 +4,9 @@
4
4
  angular.module('iguazio.dashboard-controls')
5
5
  .factory('ControlPanelLogsDataService', ControlPanelLogsDataService);
6
6
 
7
- function ControlPanelLogsDataService($q, lodash, ElasticsearchService) {
7
+ function ControlPanelLogsDataService($q, lodash, ElasticsearchService, ElasticSearchDataService) {
8
8
  return {
9
+ collectLogs: collectLogs,
9
10
  entriesPaginated: search,
10
11
  logsPaginated: logsWidthReplicas
11
12
  };
@@ -52,8 +53,8 @@
52
53
  if (queryParams.timeFrame) {
53
54
  searchFrom = 'now-' + queryParams.timeFrame;
54
55
  } else {
55
- searchFrom = queryParams.customTimeFrame.from
56
- searchTo = lodash.get(queryParams, 'customTimeFrame.to', 'now')
56
+ searchFrom = lodash.get(queryParams, 'customTimeFrame.from');
57
+ searchTo = lodash.get(queryParams, 'customTimeFrame.to', 'now');
57
58
  }
58
59
  }
59
60
 
@@ -140,6 +141,53 @@
140
141
  });
141
142
  }
142
143
 
144
+ /**
145
+ * Collects all the logs using chunks, and saved them as an array of strings.
146
+ * @param {Object} queryParams - additional parameters
147
+ * @param {string} queryParams.query - search query text
148
+ * @param {string} queryParams.timeFrame - selected time period to show results for
149
+ * @param {string} [queryParams.lastEntryTimestamp] - time stamp of the last item in a list, used with auto
150
+ * @returns {Promise.<Array>} a promise resolving to an array of logs.
151
+ */
152
+ function collectLogs(queryParams) {
153
+ var keepAlive = '5m';
154
+ var size = 10000;
155
+ var downloadLogsData = [];
156
+ var MAX_DOWNLOAD_LOGS = 100000;
157
+
158
+ return ElasticSearchDataService.createPit(keepAlive).then(function (pitId) {
159
+ return getNextChunk(pitId, null);
160
+ });
161
+
162
+ function getNextChunk(pit, searchAfter) {
163
+ return getNextPitLogs(size, queryParams, keepAlive, pit, searchAfter)
164
+ .then(function (response) {
165
+ var hits = response.hits.hits;
166
+
167
+ if (hits.length > 0 && downloadLogsData.length < MAX_DOWNLOAD_LOGS - size) {
168
+ var lastHit = lodash.last(hits);
169
+
170
+ downloadLogsData = downloadLogsData.concat(prepareLogs(hits));
171
+
172
+ return getNextChunk(response.pit_id, lastHit.sort);
173
+ } else {
174
+ return downloadLogsData;
175
+ }
176
+ }).catch(function (error) {
177
+ throw error;
178
+ });
179
+ }
180
+
181
+ function prepareLogs(logs) {
182
+ return logs.map(function (logData) {
183
+ var log = lodash.get(logData, '_source', {});
184
+
185
+ return log['@timestamp'] + ' ' + log.name + ' (' + log.level + ') ' +
186
+ lodash.get(log, 'message', '') + ' ' + JSON.stringify(lodash.get(log, 'more', {}));
187
+ });
188
+ }
189
+ }
190
+
143
191
  /**
144
192
  * Mocks the real search function without the need for a running Elasticsearch service, for development
145
193
  * purposes.
@@ -188,16 +236,82 @@
188
236
  'nuclio-tutorial-normal-user-model-monitoring-controller-6c4gfcv'
189
237
  ];
190
238
 
191
- logs.total_pages = 30000 / perPage;
192
- logs.total_logs_count = 30000;
239
+ logs.total_pages = 10000 / perPage;
240
+ logs.total_logs_count = 10000;
193
241
 
194
242
  if (withReplicas) {
195
243
  logs.replicas = replicas;
196
244
  }
197
245
 
198
- console.info(queryParams);
246
+ // console.info(queryParams);
199
247
 
200
248
  return $q.when(logs);
201
249
  }
250
+
251
+ /**
252
+ * Gets next part of the logs using Pit Id and search after parameters
253
+ * @param {number} size - size of the logs to be requested
254
+ * @param {Object} queryParams - additional parameters
255
+ * @param {string} queryParams.query - search query text
256
+ * @param {string} queryParams.timeFrame - selected time period to show results for
257
+ * @param {string} [queryParams.lastEntryTimestamp] - time stamp of the last item in a list, used with auto
258
+ * @param {boolean} keepAlive - determines how long the PIT ID should be alive
259
+ * @param {string} pitId - PIT ID that is needed to get next chunk of logs
260
+ * @param {Array} searchAfter - An array of identifiers that points to the last provided log
261
+ * @returns {Promise.<Object>} Elasticsearch logs data.
262
+ */
263
+ function getNextPitLogs(size, queryParams, keepAlive, pitId, searchAfter) {
264
+ var searchFrom = '';
265
+ var searchTo = 'now';
266
+
267
+ if (queryParams.timeFrame) {
268
+ searchFrom = 'now-' + queryParams.timeFrame;
269
+ } else {
270
+ searchFrom = lodash.get(queryParams, 'customTimeFrame.from');
271
+ searchTo = lodash.get(queryParams, 'customTimeFrame.to', 'now');
272
+ }
273
+
274
+ var config = {
275
+ size: size,
276
+ body: {
277
+ pit: {
278
+ id: pitId,
279
+ keep_alive: keepAlive
280
+ },
281
+ query: {
282
+ bool: {
283
+ must: [
284
+ {
285
+ range: {
286
+ '@timestamp': {
287
+ gte: searchFrom,
288
+ lte: searchTo
289
+ }
290
+ }
291
+ },
292
+ {
293
+ query_string: {
294
+ query: queryParams.query,
295
+ analyze_wildcard: true,
296
+ default_field: '*'
297
+ }
298
+ }
299
+ ]
300
+ }
301
+ },
302
+ sort: [
303
+ {
304
+ '@timestamp': 'desc'
305
+ }
306
+ ]
307
+ }
308
+ };
309
+
310
+ if (searchAfter) {
311
+ config.body.search_after = searchAfter;
312
+ }
313
+
314
+ return ElasticsearchService.search(config);
315
+ }
202
316
  }
203
317
  }());
@@ -28,11 +28,11 @@ such restriction.
28
28
  controller: NclVersionExecutionLogController
29
29
  });
30
30
 
31
- function NclVersionExecutionLogController(lodash, $interval, i18next, $i18next, $rootScope, moment, ConfigService,
32
- ControlPanelLogsDataService, ExportService, LoginService,PaginationService) {
31
+ function NclVersionExecutionLogController(lodash, $interval, i18next, $i18next, $rootScope, moment, ControlPanelLogsDataService,
32
+ ConfigService, ExportService, LoginService, PaginationService) {
33
33
  var ctrl = this;
34
-
35
34
  var lng = i18next.language;
35
+
36
36
  var refreshInterval = null;
37
37
  var initialTimeRange = {
38
38
  from: null,
@@ -51,6 +51,7 @@ such restriction.
51
51
  }
52
52
  };
53
53
 
54
+ ctrl.downloadButtonIsDisabled = false;
54
55
  ctrl.isSplashShowed = {
55
56
  value: false
56
57
  };
@@ -67,6 +68,7 @@ such restriction.
67
68
  }
68
69
  };
69
70
  ctrl.datePreset = initialDatePreset;
71
+ ctrl.logsAreDownloading = false;
70
72
  ctrl.timeRange = initialTimeRange;
71
73
  ctrl.searchStates = {};
72
74
  ctrl.selectedReplicas = [];
@@ -164,7 +166,7 @@ such restriction.
164
166
  ctrl.$onDestroy = onDestroy;
165
167
 
166
168
  ctrl.applyFilters = applyFilters;
167
- // ctrl.downloadLogFiles = downloadLogFiles;
169
+ ctrl.downloadLogFiles = downloadLogFiles;
168
170
  ctrl.onCheckboxChange = onCheckboxChange;
169
171
  ctrl.onRefreshRateChange = onRefreshRateChange;
170
172
  ctrl.onTimeRangeChange = onTimeRangeChange;
@@ -213,18 +215,22 @@ such restriction.
213
215
  searchWithParams(0, ctrl.page.size);
214
216
  }
215
217
 
216
- // /**
217
- // * Downloads log to the file
218
- // */
219
- // function downloadLogFiles() {
220
- // ExportService.exportLogs(prepareLogs(), ctrl.version.metadata.name);
221
- //
222
- // function prepareLogs() {
223
- // return ctrl.logs.map(function (log) {
224
- // return log['@timestamp'] + ' ' + log.name + ' (' + log.level + ') ' + log.message + ' ' + log.more;
225
- // });
226
- // }
227
- // }
218
+ /**
219
+ * Downloads log to the file
220
+ */
221
+ function downloadLogFiles() {
222
+ stopAutoUpdate();
223
+
224
+ ctrl.downloadButtonIsDisabled = true;
225
+ return ControlPanelLogsDataService.collectLogs(queryParams())
226
+ .then(function (response) {
227
+ ExportService.exportLogs(response, ctrl.version.metadata.name);
228
+ }).finally(function () {
229
+ startAutoUpdate();
230
+
231
+ ctrl.downloadButtonIsDisabled = false;
232
+ });
233
+ }
228
234
 
229
235
  /**
230
236
  * Triggered when search text was changed
@@ -277,7 +283,7 @@ such restriction.
277
283
  function refreshLogs() {
278
284
  startAutoUpdate();
279
285
 
280
- ControlPanelLogsDataService.logsPaginated(ctrl.page.number, ctrl.page.size, queryParams(), true)
286
+ ControlPanelLogsDataService.logsPaginated(ctrl.page.number, ctrl.page.size, queryParams())
281
287
  .then(function (logs) {
282
288
  if (logs.length > 0) {
283
289
  ctrl.logs = lodash.cloneDeep(logs);
@@ -330,13 +336,12 @@ such restriction.
330
336
  return;
331
337
  }
332
338
 
333
- ControlPanelLogsDataService.logsPaginated(ctrl.page.number, ctrl.page.size, queryParamsAutoUpdate(), true)
339
+ ControlPanelLogsDataService.logsPaginated(ctrl.page.number, ctrl.page.size, queryParamsAutoUpdate())
334
340
  .then(function (logs) {
335
341
  if (logs.length > 0) {
336
342
  ctrl.logs = lodash.cloneDeep(logs);
337
343
  ctrl.page.total = logs['total_pages'];
338
344
 
339
- // set lastItemTimeStamp and start autoupdate
340
345
  onChangePageCallback();
341
346
  }
342
347
  });
@@ -1,7 +1,7 @@
1
1
  .ncl-version-execution-log {
2
2
  .control-panel-log-color-set();
3
3
 
4
- min-width: 1200px;
4
+ min-width: 1250px;
5
5
  padding: 24px 25px 22px 41px;
6
6
 
7
7
  .ncl-version-execution-log-wrapper {
@@ -34,6 +34,10 @@
34
34
  transition: @igz-basic-transition;
35
35
  height: 100%;
36
36
 
37
+ .limitation-message {
38
+ line-height: 20px;
39
+ }
40
+
37
41
  .logs-container {
38
42
  padding-bottom: 50px;
39
43
  }
@@ -110,6 +110,9 @@
110
110
  <igz-info-page-actions-bar>
111
111
  <div class="igz-action-panel">
112
112
  <div class="actions-list">
113
+ <div class="actions-bar-left">
114
+ <span class="limitation-message" data-ng-i18next="[html]functions:LOGS_LINES_LIMITATION"></span>
115
+ </div>
113
116
  <div class="actions-bar-right">
114
117
  <div class="actions-bar-left actions-buttons-block actions-dropdown-block">
115
118
  <igz-default-dropdown data-values-array="$ctrl.refreshRate.options"
@@ -126,16 +129,17 @@
126
129
  data-refresh="$ctrl.searchWithParams($ctrl.page.number, $ctrl.page.size)">
127
130
  </igz-action-item-refresh>
128
131
  </div>
129
- <!-- <div class="actions-bar-left">-->
130
- <!-- <div class="igz-action-item"-->
131
- <!-- data-ng-click="$ctrl.downloadLogFiles()"-->
132
- <!-- data-uib-tooltip="{{ 'common:DOWNLOAD' | i18next }}"-->
133
- <!-- data-tooltip-placement="bottom"-->
134
- <!-- data-tooltip-popup-delay="300"-->
135
- <!-- data-tooltip-append-to-body="true">-->
136
- <!-- <div class="action-icon igz-icon-download"></div>-->
137
- <!-- </div>-->
138
- <!-- </div>-->
132
+ <div class="actions-bar-left">
133
+ <div class="igz-action-item"
134
+ data-ng-click="$ctrl.downloadLogFiles()"
135
+ data-ng-class="{'inactive': $ctrl.logsAreDownloading || $ctrl.downloadButtonIsDisabled}"
136
+ data-uib-tooltip="{{ 'common:DOWNLOAD' | i18next }}"
137
+ data-tooltip-placement="bottom"
138
+ data-tooltip-popup-delay="300"
139
+ data-tooltip-append-to-body="true">
140
+ <div class="action-icon igz-icon-download"></div>
141
+ </div>
142
+ </div>
139
143
  <igz-actions-panes data-filters-toggle-method="$ctrl.toggleFilters()"
140
144
  data-show-filter-icon="true"
141
145
  data-filters-counter="$ctrl.activeFilters"