You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2018/05/10 10:06:18 UTC

[ambari] branch trunk updated: [AMBARI-23779] - [Log Search UI] limitation for number of URL paramater value length

This is an automated email from the ASF dual-hosted git repository.

ababiichuk pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 1b6a473  [AMBARI-23779] - [Log Search UI] limitation for number of URL paramater value length
1b6a473 is described below

commit 1b6a473241a9648664f550233b3c3e2d43d0a300
Author: Istvan Tobias <to...@gmail.com>
AuthorDate: Wed May 9 11:56:21 2018 +0200

    [AMBARI-23779] - [Log Search UI] limitation for number of URL paramater value length
---
 .../src/app/services/http-client.service.ts        |   46 +-
 .../src/app/services/mock-api-data.service.ts      |   34 +-
 .../src/mockdata/mock-data-common.ts               |  118 +-
 .../src/mockdata/mock-data-get.ts                  |   68 +-
 .../src/mockdata/mock-data-post.ts                 | 1649 +++++++++++++++++++-
 5 files changed, 1806 insertions(+), 109 deletions(-)

diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
index 8c222e0..19a12ab 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
@@ -104,6 +104,17 @@ export class HttpClientService extends Http {
     super(backend, defaultOptions);
   }
 
+  /**
+   * The goal here is to check if the given real api url should be always POST or not.\
+   * See https://issues.apache.org/jira/browse/AMBARI-23779
+   * @param {string} url The full url for the api end point.
+   * @returns {boolean}
+   */
+  private shouldTurnGetToPost(url: string): boolean {
+    const subUrl = url.replace(this.apiPrefix, '');
+    return /^(audit|service)/.test(subUrl);
+  }
+
   private generateUrlString(url: string, urlVariables?: HomogeneousObject<string>): string {
     const preset = this.endPoints[url];
     let generatedUrl: string;
@@ -153,23 +164,50 @@ export class HttpClientService extends Http {
 
   request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
     const handleResponseError = (error) => {
-      let handled: boolean = false;
+      let handled = false;
       if (this.unauthorizedStatuses.indexOf(error.status) > -1) {
         this.appState.setParameter('isAuthorized', false);
         handled = true;
       }
       return handled;
     };
-    const req: Observable<Response> = super.request(this.generateUrl(url), options).first()
+    return super.request(this.generateUrl(url), options).first()
       .map(response => response)
       .catch((error: any) => {
         return handleResponseError(error) ? Observable.of(error) : Observable.throw(error);
       });
-    return req;
   }
 
   get(url: string, params?: HomogeneousObject<string>, urlVariables?: HomogeneousObject<string>): Observable<Response> {
-    return super.get(this.generateUrlString(url, urlVariables), this.generateOptions(url, params));
+    const generatedUrl: string = this.generateUrlString(url, urlVariables);
+    let response$: Observable<Response>;
+    const options = this.generateOptions(url, params);
+    if (this.shouldTurnGetToPost(generatedUrl)) {
+      let body = (options && options.params) || params || {};
+      if (body instanceof URLSearchParams) {
+        const paramsMap = Array.from(body.paramsMap);
+        body = paramsMap.reduce((current, param) => {
+          const [key, value] = param;
+          return {
+            ...current,
+            [key]: Array.isArray(value) && value.length === 1 ? value[0] : value
+          };
+        }, {});
+      } else if (typeof body === 'string') {
+        body = body.split('&').reduce((current, param): {[key: string]: any} => {
+          const pair = param.split('=');
+          return {
+            ...current,
+            [pair[0]]: decodeURIComponent(pair[1])
+          };
+        }, {});
+      }
+      options.params = {};
+      response$ = super.post(generatedUrl, body, options);
+    } else {
+      response$ = super.get(this.generateUrlString(url, urlVariables), this.generateOptions(url, params));
+    }
+    return response$;
   }
 
   put(url: string, body: any, params?: HomogeneousObject<string>, urlVariables?: HomogeneousObject<string>): Observable<Response> {
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
index b1dc6cf..92707d0 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
@@ -22,8 +22,8 @@ import {Observable} from 'rxjs/Observable';
 import {Subscriber} from 'rxjs/Subscriber';
 import 'rxjs/add/operator/delay';
 import * as moment from 'moment';
-import {mockDataGet} from "@mockdata/mock-data-get";
-import {mockDataPost} from "@mockdata/mock-data-post";
+import {mockDataGet} from '@mockdata/mock-data-get';
+import {mockDataPost} from '@mockdata/mock-data-post';
 
 export class MockBackendService extends InMemoryBackendService {
   getLocation(url: string): any {
@@ -134,6 +134,16 @@ export class MockApiDataService implements InMemoryDbService {
     return mockDataObj[matchedPath];
   }
 
+  /**
+   * The goal here is to check if the given real api url should be always POST or not.\
+   * See https://issues.apache.org/jira/browse/AMBARI-23779
+   * @param {string} url The full url for the api end point.
+   * @returns {boolean}
+   */
+  private shouldTurnGetToPost(url: string): boolean {
+    return /(audit|service)/.test(url);
+  }
+
   get(interceptorArgs: any): Observable<Response> {
     const query = interceptorArgs.requestInfo.query;
     const path = interceptorArgs.requestInfo.base + interceptorArgs.requestInfo.collectionName;
@@ -145,7 +155,15 @@ export class MockApiDataService implements InMemoryDbService {
         allData = this.findDataByUrlPatter(path, mockDataGet);
       }
       if (typeof allData === 'function') {
-        allData = allData(query, interceptorArgs.requestInfo.req);
+        try {
+          allData = allData(query, interceptorArgs.requestInfo.req);
+        } catch (error) {
+          return new Observable<Response>((subscriber: Subscriber<Response>) => subscriber.error(
+            new Response(createErrorResponse(
+              interceptorArgs.requestInfo.req, 500, error
+            )))
+          );
+        }
       }
       const is404 = !allData;
 
@@ -229,7 +247,15 @@ export class MockApiDataService implements InMemoryDbService {
       responseBody = this.findDataByUrlPatter(path, mockDataPost);
     }
     if (typeof responseBody === 'function') {
-      responseBody = responseBody(query, interceptorArgs.requestInfo.req);
+      try {
+        responseBody = responseBody(query, interceptorArgs.requestInfo.req);
+      } catch (error) {
+        return new Observable<Response>((subscriber: Subscriber<Response>) => subscriber.error(
+          new Response(createErrorResponse(
+            interceptorArgs.requestInfo.req, 500, error
+          )))
+        );
+      }
     }
     const is404 = !responseBody;
 
diff --git a/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-common.ts b/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-common.ts
index 3c909b6..d830139 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-common.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-common.ts
@@ -21,26 +21,26 @@ import * as randomize from 'randomatic';
 
 export const clusters: string[] = ['cl0', 'cl1', 'cl2'];
 
-export const hosts: string[] = ["c64001", "c64002", "c64003"];
+export const hosts: string[] = ['c64001', 'c64002', 'c64003'];
 
 export const services: string[] = ['hdfs', 'ambari'];
 
 export const users: string[] = ['hdfs', 'admin', 'user'];
 
 export const components = [
-  "ambari_agent",
-  "hdfs_secondarynamenode",
-  "infra_solr",
-  "logsearch_app",
-  "logsearch_feeder"
+  'ambari_agent',
+  'hdfs_secondarynamenode',
+  'infra_solr',
+  'logsearch_app',
+  'logsearch_feeder'
 ];
 
 export const levels = [
-  "INFO",
-  "WARN",
-  "ERROR",
-  "FATAL",
-  "DEBUG"
+  'INFO',
+  'WARN',
+  'ERROR',
+  'FATAL',
+  'DEBUG'
 ];
 
 export function ucFirst(str) {
@@ -55,18 +55,23 @@ export function getRandomElement(list: Array<any>) {
   return list[getRandomInt(list.length)];
 }
 
-export function generatePath(c: number = 3, addComponent: boolean | string = true, addService: boolean | string = false, folderNameMaxLength: number = 12): string {
-  let path = "/var/log";
+export function generatePath(
+  c: number = 3,
+  addComponent: boolean | string = true,
+  addService: boolean | string = false,
+  folderNameMaxLength: number = 12
+): string {
+  let path = '/var/log';
   if (addService) {
-    path += ("/" + (addService === true ? getRandomElement(services) : addService));
+    path += ('/' + (addService === true ? getRandomElement(services) : addService));
     c -= 1;
   }
   if (addComponent) {
-    path += ("/" + (addComponent === true ? getRandomElement(components) : addComponent));
+    path += ('/' + (addComponent === true ? getRandomElement(components) : addComponent));
     c -= 1;
   }
-  for (let i=0; i<c; i+=1) {
-    path += ("/" + randomize('Aa0?', getRandomInt(folderNameMaxLength), {chars: '-_'}));
+  for (let i = 0; i < c; i += 1) {
+    path += ('/' + randomize('Aa0?', getRandomInt(folderNameMaxLength), {chars: '-_'}));
   }
   return path;
 }
@@ -75,36 +80,36 @@ export function generateServiceLog(defaults?: {[key:string]: any}) {
   const component = (defaults && defaults.type) || getRandomElement(components);
   const host = (defaults && defaults.host) || getRandomElement(hosts);
   return Object.assign({
-    "id": randomize('a0', 32, {chars: '-'}),
-    "bundle_id": null,
-    "case_id": null,
-    "cluster": getRandomElement(clusters),
-    "seq_num": randomize('0', 5),
-    "log_message": randomize('a0?a0', getRandomInt(1000), {chars: " \n"}),
-    "logfile_line_number": randomize('0', 4),
-    "event_dur_ms": null,
-    "file": randomize('a0?a0', 16, {chars: '-_'}) + ".java",
-    "type": component,
-    "event_count": getRandomInt(1000),
-    "event_md5": randomize('a0', 32),
-    "message_md5": randomize('a0', 32),
-    "_ttl_": `-${getRandomInt(30)}DAYS`,
-    "_expire_at_": 1518188622956,
-    "_version_": randomize('0', 20),
-    "_router_field_": null,
-    "level": getRandomElement(levels),
-    "line_number": getRandomInt(999),
-    "logtime": moment().subtract(getRandomInt(14), 'days').valueOf(),
-    "ip": `${getRandomInt(255)}.${getRandomInt(255)}.${getRandomInt(255)}.${getRandomInt(255)}`,
-    "path": generatePath(3, component) + ".json",
-    "host": host + ".ambari.apache.org",
-    "group": host + ".ambari.apache.org"
+    'id': randomize('a0', 32, {chars: '-'}),
+    'bundle_id': null,
+    'case_id': null,
+    'cluster': getRandomElement(clusters),
+    'seq_num': randomize('0', 5),
+    'log_message': randomize('a0?a0', getRandomInt(1000), {chars: ' \n'}),
+    'logfile_line_number': randomize('0', 4),
+    'event_dur_ms': null,
+    'file': randomize('a0?a0', 16, {chars: '-_'}) + '.java',
+    'type': component,
+    'event_count': getRandomInt(1000),
+    'event_md5': randomize('a0', 32),
+    'message_md5': randomize('a0', 32),
+    '_ttl_': `-${getRandomInt(30)}DAYS`,
+    '_expire_at_': 1518188622956,
+    '_version_': randomize('0', 20),
+    '_router_field_': null,
+    'level': getRandomElement(levels),
+    'line_number': getRandomInt(999),
+    'logtime': moment().subtract(getRandomInt(14), 'days').valueOf(),
+    'ip': `${getRandomInt(255)}.${getRandomInt(255)}.${getRandomInt(255)}.${getRandomInt(255)}`,
+    'path': generatePath(3, component) + '.json',
+    'host': host + '.ambari.apache.org',
+    'group': host + '.ambari.apache.org'
   }, defaults || {});
 }
 
 export function generateAuditLog(defaults?: {[key: string]: any}) {
-  const component:string = (defaults && defaults.component)  || getRandomElement(components); // meta default
-  const service:string = (defaults && defaults.repo)  || getRandomElement(services);
+  const component: string = (defaults && defaults.component)  || getRandomElement(components); // meta default
+  const service: string = (defaults && defaults.repo)  || getRandomElement(services);
   const time = moment().subtract(getRandomInt(14), 'days');
   return Object.assign({
     policy: 'policy',
@@ -146,13 +151,36 @@ export function generateAuditLog(defaults?: {[key: string]: any}) {
     case_id: 'c0',
     log_message: `User(${getRandomElement(users)}), Operation(SERVICE_CHECK)`,
     logfile_line_number: 4,
-    message_md5: randomize('a0',20),
+    message_md5: randomize('a0', 20),
     cluster: getRandomElement(clusters),
     event_count: getRandomInt(100),
-    event_md5: randomize('0',20),
+    event_md5: randomize('0', 20),
     event_dur_ms: getRandomInt(900),
     _ttl_: '+7DAYS',
     _expire_at_: time.format(),
     _router_field_: getRandomInt(20)
   }, defaults || {});
 }
+
+export function generateDataCount(from, to, unit, gap) {
+  let current = moment(from);
+  const end = moment(to);
+  const data = [];
+  while (current.isBefore(end)) {
+    data.push({
+      name: current.toISOString(),
+      value: getRandomInt(9000)
+    });
+    current = current.add(gap, unit);
+  }
+  return data;
+}
+
+export function generateGraphData(from, to, unit, gap) {
+  return levels.map((level) => {
+    return {
+      dataCount: generateDataCount(from, to, unit, gap),
+      name: level
+    };
+  });
+}
diff --git a/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-get.ts b/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-get.ts
index ab5b235..1c2b76c 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-get.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-get.ts
@@ -17,7 +17,7 @@
  */
 
 import * as moment from 'moment';
-import {Moment} from "moment";
+import {Moment} from 'moment';
 
 import {
   clusters,
@@ -25,54 +25,30 @@ import {
   services,
   users,
   components,
-  levels,
   ucFirst,
   getRandomInt,
   getRandomElement,
-  generatePath,
   generateServiceLog,
-  generateAuditLog
+  generateAuditLog,
+  generateGraphData
 } from './mock-data-common';
 import Base = moment.unitOfTime.Base;
 
 const currentTime: Moment = moment();
 
-function generateDataCount(from, to, unit, gap) {
-  let current = moment(from);
-  const end = moment(to);
-  const data = [];
-  while (current.isBefore(end)) {
-    data.push({
-      name: current.toISOString(),
-      value: getRandomInt(9000)
-    });
-    current = current.add(gap, unit);
-  }
-  return data;
-}
-
-function generateGraphData(from, to, unit, gap) {
-  return levels.map((level) => {
-    return {
-      dataCount: generateDataCount(from, to, unit, gap),
-      name: level
-    };
-  });
-}
-
 export const mockDataGet = {
   'login': {},
   'logout': {},
 
   'api/v1/audit/logs': function (query) {
-    let list = [];
-    let params = query.rawParams.split('&').reduce((currentObj, param) => {
+    const list = [];
+    const params = query.rawParams.split('&').reduce((currentObj, param) => {
       let [key, value] = param.split('=');
       switch (key) {
         case 'page':
         case 'pageSize':
         case 'startIndex':
-          value = parseInt(value);
+          value = parseInt(value, 0);
           break;
         case 'from':
         case 'to':
@@ -90,7 +66,7 @@ export const mockDataGet = {
     const intervalSteps = params.to.diff(params.from) / pageSize;
     const startTime = params.from.valueOf();
     for (let i = 0; i < pageSize; i += 1) {
-      let defaults: {[key:string]: any} = {logtime: startTime + (i * intervalSteps)};
+      const defaults: {[key: string]: any} = {logtime: startTime + (i * intervalSteps)};
       list.push(generateAuditLog(defaults));
     }
     return {
@@ -154,24 +130,24 @@ export const mockDataGet = {
         name: comp,
         label: comp.split('_').map(ucFirst).join(' '),
         group: null
-      }
+      };
     })
   },
   'api/v1/audit/logs/resources/\\d': function (query) {
-    let graphData = users.map((user:string) => {
+    const graphData = users.map((user: string) => {
       return {
         name: user,
-        dataCount: services.map((service:string) => {
+        dataCount: services.map((service: string) => {
           return {
             name: service,
             value: getRandomInt(1000)
-          }
+          };
         })
       };
     });
     return {
       graphData: graphData
-    }
+    };
   },
   'api/v1/audit/logs/schema/fields': {
     'defaults': [
@@ -1251,14 +1227,14 @@ export const mockDataGet = {
   'api/v1/public/config': {},
 
   'api/v1/service/logs': function (query) {
-    let list = [];
-    let params = query.rawParams.split('&').reduce((currentObj, param) => {
+    const list = [];
+    const params = query.rawParams.split('&').reduce((currentObj, param) => {
       let [key, value] = param.split('=');
       switch (key) {
         case 'page':
         case 'pageSize':
         case 'startIndex':
-          value = parseInt(value);
+          value = parseInt(value, 0);
           break;
         case 'from':
         case 'to':
@@ -1279,7 +1255,7 @@ export const mockDataGet = {
     const startTime = params.from.valueOf();
 
     for (let i = 0; i < pageSize; i += 1) {
-      let defaults: {[key:string]: any} = {logtime: startTime + (i * intervalSteps)};
+      const defaults: {[key: string]: any} = {logtime: startTime + (i * intervalSteps)};
       if (params.mustBe) {
         defaults.type = getRandomElement(params.mustBe);
       }
@@ -1303,14 +1279,14 @@ export const mockDataGet = {
     };
   },
   'api/v1/service/logs/logList': (query) => {
-    let list = [];
-    let params = query.rawParams.split('&').reduce((currentObj, param) => {
+    const list = [];
+    const params = query.rawParams.split('&').reduce((currentObj, param) => {
       let [key, value] = param.split('=');
       switch (key) {
         case 'page':
         case 'pageSize':
         case 'startIndex':
-          value = parseInt(value);
+          value = parseInt(value, 0);
           break;
         case 'from':
         case 'to':
@@ -1331,7 +1307,7 @@ export const mockDataGet = {
     const startTime = params.from.valueOf();
 
     for (let i = 0; i < pageSize; i += 1) {
-      let defaults: {[key:string]: any} = {
+      const defaults: {[key: string]: any} = {
         logtime: startTime + (i * intervalSteps),
         event_dur_ms: getRandomInt(1000)
       };
@@ -1391,7 +1367,7 @@ export const mockDataGet = {
         name: comp,
         label: comp.split('_').map(ucFirst).join(' '),
         group: null
-      }
+      };
     })
   },
   'api/v1/service/logs/components/levels/counts': {
@@ -1456,7 +1432,7 @@ export const mockDataGet = {
           },
           {
             name: 'WARN',
-            value: '500'
+              value: '500'
           }
         ],
         isParent: false,
diff --git a/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-post.ts b/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-post.ts
index 63caf4b..0bb4208 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-post.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/mockdata/mock-data-post.ts
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import {Request} from "@angular/http";
+import {Request} from '@angular/http';
 
 import * as moment from 'moment';
-import {Moment} from "moment";
+import {Moment} from 'moment';
 
 import {
   clusters,
@@ -27,22 +27,1651 @@ import {
   services,
   users,
   components,
-  levels,
   ucFirst,
   getRandomInt,
   getRandomElement,
-  generatePath,
   generateServiceLog,
-  generateAuditLog
+  generateAuditLog,
+  generateGraphData
 } from './mock-data-common';
+import Base = moment.unitOfTime.Base;
 
+const currentTime: Moment = moment();
 export const mockDataPost = {
-  "login": {},
-  "logout": {},
+  'login': {},
+  'logout': {},
 
-  "api/v1/shipper/[a-zA-Z0-9\\-]{1,}/services/[a-zA-Z0-9\\-]{1,}$": (query: any, request: Request) => {
-    const body = request.getBody();
+  'api/v1/shipper/[a-zA-Z0-9\\-]{1,}/services/[a-zA-Z0-9\\-]{1,}$': (query: any, request: Request) => {
     return {};
   },
-  ".*": {}
+  'api/v1/audit/logs': function (query, request: Request) {
+    const list = [];
+    const params = request.json();
+    params.to = moment(params.to);
+    params.from = moment(params.from);
+    const pageSize = params.pageSize || 50;
+    const intervalSteps = params.to.diff(params.from) / pageSize;
+    const startTime = params.from.valueOf();
+    for (let i = 0; i < pageSize; i += 1) {
+      const defaults: {[key: string]: any} = {logtime: startTime + (i * intervalSteps)};
+      list.push(generateAuditLog(defaults));
+    }
+    return {
+      'startIndex': params.startIndex,
+      'pageSize': pageSize,
+      'totalCount': 10 * pageSize,
+      'resultSize': 10 * pageSize,
+      'sortType': params.sortType,
+      'sortBy': params.sortBy,
+      'queryTimeMS': 1518013198573,
+      'logList': list
+    };
+  },
+  'api/v1/audit/logs/bargraph': {
+    graphData: [{
+      dataCount: [
+        {
+          name: currentTime.toISOString(),
+          value: '75'
+        },
+        {
+          name: currentTime.clone().subtract(20, 'm').toISOString(),
+          value: '100'
+        },
+        {
+          name: currentTime.clone().subtract(40, 'm').toISOString(),
+          value: '75'
+        },
+        {
+          name: currentTime.clone().subtract(1, 'h').toISOString(),
+          value: '50'
+        }
+      ],
+      name: 'AMBARI'
+    }, {
+      dataCount: [
+        {
+          name: currentTime.toISOString(),
+          value: '150'
+        },
+        {
+          name: currentTime.clone().subtract(20, 'm').toISOString(),
+          value: '50'
+        },
+        {
+          name: currentTime.clone().subtract(40, 'm').toISOString(),
+          value: '75'
+        },
+        {
+          name: currentTime.clone().subtract(1, 'h').toISOString(),
+          value: '100'
+        }
+      ],
+      name: 'HDFS'
+    }
+    ]},
+  'api/v1/audit/logs/components': {
+    'groups': {},
+    'metadata': components.map(comp => {
+      return {
+        name: comp,
+        label: comp.split('_').map(ucFirst).join(' '),
+        group: null
+      };
+    })
+  },
+  'api/v1/audit/logs/resources/\\d': function (query, request: Request) {
+    const graphData = users.map((user: string) => {
+      return {
+        name: user,
+        dataCount: services.map((service: string) => {
+          return {
+            name: service,
+            value: getRandomInt(1000)
+          };
+        })
+      };
+    });
+    return {
+      graphData: graphData
+    };
+  },
+  'api/v1/audit/logs/schema/fields': {
+    'defaults': [
+      {
+        'name': 'logType',
+        'label': 'Log Type',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'cluster',
+        'label': 'Cluster',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'reason',
+        'label': 'Reason',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'agent',
+        'label': 'Agent',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'access',
+        'label': 'Access Type',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'dst',
+        'label': 'DST',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'perm',
+        'label': 'Perm',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'event_count',
+        'label': 'Event Count',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'repo',
+        'label': 'Repo',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'sess',
+        'label': 'Session',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'reqUser',
+        'label': 'User',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'task_id',
+        'label': 'Task Id',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'type',
+        'label': 'Type',
+        'filterable': true,
+        'visible': true
+      },
+      {
+        'name': 'reqData',
+        'label': 'Req Data',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'result',
+        'label': 'Result',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'path',
+        'label': 'Path',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'file',
+        'label': 'File',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'ugi',
+        'label': 'UGI',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'case_id',
+        'label': 'Case Id',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'host',
+        'label': 'Host',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'action',
+        'label': 'Action',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'log_message',
+        'label': 'Log Message',
+        'filterable': true,
+        'visible': true
+      },
+      {
+        'name': 'agentHost',
+        'label': 'Agent Host',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'id',
+        'label': 'Id',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'logger_name',
+        'label': 'Logger Name',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'text',
+        'label': 'Text',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'authType',
+        'label': 'Auth Type',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'logfile_line_number',
+        'label': 'Logfile Line Number',
+        'filterable': true,
+        'visible': true
+      },
+      {
+        'name': 'policy',
+        'label': 'Policy',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'cliIP',
+        'label': 'Client Ip',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'level',
+        'label': 'Level',
+        'filterable': true,
+        'visible': true
+      },
+      {
+        'name': 'resource',
+        'label': 'Resource',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'resType',
+        'label': 'Res Type',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'ip',
+        'label': 'IP',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'evtTime',
+        'label': 'Event Time',
+        'filterable': true,
+        'visible': true
+      },
+      {
+        'name': 'req_self_id',
+        'label': 'Req Self Id',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'repoType',
+        'label': 'Repo Type',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'req_caller_id',
+        'label': 'Req Caller Id',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'enforcer',
+        'label': 'Access Enforcer',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'bundle_id',
+        'label': 'Bundle Id',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'cliType',
+        'label': 'Client Type',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'reqContext',
+        'label': 'Req Context',
+        'filterable': true,
+        'visible': false
+      },
+      {
+        'name': 'proxyUsers',
+        'label': 'Proxy Users',
+        'filterable': true,
+        'visible': false
+      }
+    ],
+    'overrides': {
+      'ambari': [
+        {
+          'name': 'logType',
+          'label': 'Log Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cluster',
+          'label': 'Cluster',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reason',
+          'label': 'Reason',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'agent',
+          'label': 'Agent',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'access',
+          'label': 'Access',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'dst',
+          'label': 'Dst',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'perm',
+          'label': 'Perm',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'event_count',
+          'label': 'Event Count',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'repo',
+          'label': 'Repo',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'sess',
+          'label': 'Sess',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqUser',
+          'label': 'Req User',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'task_id',
+          'label': 'Task Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'type',
+          'label': 'Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqData',
+          'label': 'Req Data',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'result',
+          'label': 'Result',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'path',
+          'label': 'Path',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'file',
+          'label': 'File',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'ugi',
+          'label': 'Ugi',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'case_id',
+          'label': 'Case Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'host',
+          'label': 'Host',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'action',
+          'label': 'Action',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'log_message',
+          'label': 'Log Message',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'agentHost',
+          'label': 'Agent Host',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'id',
+          'label': 'Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'logger_name',
+          'label': 'Logger Name',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'text',
+          'label': 'Text',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'authType',
+          'label': 'Auth Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'logfile_line_number',
+          'label': 'Logfile Line Number',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'policy',
+          'label': 'Policy',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cliIP',
+          'label': 'Cli I P',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'level',
+          'label': 'Level',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'resource',
+          'label': 'Resource',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'resType',
+          'label': 'Res Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'ip',
+          'label': 'Ip',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'evtTime',
+          'label': 'Evt Time',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'req_self_id',
+          'label': 'Req Self Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'repoType',
+          'label': 'Repo Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'req_caller_id',
+          'label': 'Req Caller Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'enforcer',
+          'label': 'Enforcer',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'bundle_id',
+          'label': 'Bundle Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cliType',
+          'label': 'Cli Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqContext',
+          'label': 'Req Context',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'proxyUsers',
+          'label': 'Proxy Users',
+          'filterable': true,
+          'visible': false
+        }
+      ],
+      'RangerAudit': [
+        {
+          'name': 'logType',
+          'label': 'Log Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cluster',
+          'label': 'Cluster',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reason',
+          'label': 'Reason',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'agent',
+          'label': 'Agent',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'access',
+          'label': 'Access',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'dst',
+          'label': 'Dst',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'perm',
+          'label': 'Perm',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'event_count',
+          'label': 'Event Count',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'repo',
+          'label': 'Repo',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'sess',
+          'label': 'Sess',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqUser',
+          'label': 'Req User',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'task_id',
+          'label': 'Task Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'type',
+          'label': 'Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqData',
+          'label': 'Req Data',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'result',
+          'label': 'Result',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'path',
+          'label': 'Path',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'file',
+          'label': 'File',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'ugi',
+          'label': 'Ugi',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'case_id',
+          'label': 'Case Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'host',
+          'label': 'Host',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'action',
+          'label': 'Action',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'log_message',
+          'label': 'Log Message',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'agentHost',
+          'label': 'Agent Host',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'id',
+          'label': 'Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'logger_name',
+          'label': 'Logger Name',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'text',
+          'label': 'Text',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'authType',
+          'label': 'Auth Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'logfile_line_number',
+          'label': 'Logfile Line Number',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'policy',
+          'label': 'Policy',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cliIP',
+          'label': 'Cli I P',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'level',
+          'label': 'Level',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'resource',
+          'label': 'Resource',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'resType',
+          'label': 'Res Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'ip',
+          'label': 'Ip',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'evtTime',
+          'label': 'Evt Time',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'req_self_id',
+          'label': 'Req Self Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'repoType',
+          'label': 'Repo Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'req_caller_id',
+          'label': 'Req Caller Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'enforcer',
+          'label': 'Enforcer',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'bundle_id',
+          'label': 'Bundle Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cliType',
+          'label': 'Cli Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqContext',
+          'label': 'Req Context',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'proxyUsers',
+          'label': 'Proxy Users',
+          'filterable': true,
+          'visible': false
+        }
+      ],
+      'hdfs': [
+        {
+          'name': 'logType',
+          'label': 'Log Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cluster',
+          'label': 'Cluster',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reason',
+          'label': 'Reason',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'agent',
+          'label': 'Agent',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'access',
+          'label': 'Access',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'dst',
+          'label': 'Dst',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'perm',
+          'label': 'Perm',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'event_count',
+          'label': 'Event Count',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'repo',
+          'label': 'Repo',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'sess',
+          'label': 'Sess',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqUser',
+          'label': 'Req User',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'task_id',
+          'label': 'Task Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'type',
+          'label': 'Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqData',
+          'label': 'Req Data',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'result',
+          'label': 'Result',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'path',
+          'label': 'Path',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'file',
+          'label': 'File',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'ugi',
+          'label': 'Ugi',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'case_id',
+          'label': 'Case Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'host',
+          'label': 'Host',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'action',
+          'label': 'Action',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'log_message',
+          'label': 'Log Message',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'agentHost',
+          'label': 'Agent Host',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'id',
+          'label': 'Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'logger_name',
+          'label': 'Logger Name',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'text',
+          'label': 'Text',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'authType',
+          'label': 'Auth Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'logfile_line_number',
+          'label': 'Logfile Line Number',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'policy',
+          'label': 'Policy',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cliIP',
+          'label': 'Cli I P',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'level',
+          'label': 'Level',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'resource',
+          'label': 'Resource',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'resType',
+          'label': 'Res Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'ip',
+          'label': 'Ip',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'evtTime',
+          'label': 'Evt Time',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'req_self_id',
+          'label': 'Req Self Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'repoType',
+          'label': 'Repo Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'req_caller_id',
+          'label': 'Req Caller Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'enforcer',
+          'label': 'Enforcer',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'bundle_id',
+          'label': 'Bundle Id',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'cliType',
+          'label': 'Cli Type',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'reqContext',
+          'label': 'Req Context',
+          'filterable': true,
+          'visible': false
+        },
+        {
+          'name': 'proxyUsers',
+          'label': 'Proxy Users',
+          'filterable': true,
+          'visible': false
+        }
+      ]
+    }
+  },
+  'api/v1/audit/logs/serviceload': {
+    graphData: [
+      {
+        dataCount: [
+          {
+            name: 'n4',
+            value: 1
+          },
+          {
+            name: 'n5',
+            value: 2
+          }
+        ],
+        name: 'graph2'
+      },
+      {
+        dataCount: [
+          {
+            name: 'n6',
+            value: 10
+          },
+          {
+            name: 'n7',
+            value: 20
+          }
+        ],
+        name: 'graph3'
+      }
+    ]
+  },
+  'api/v1/service/logs': function (query, request: Request) {
+    const list = [];
+    const params = request.json();
+    params.to = moment(params.to);
+    params.from = moment(params.from);
+    const pageSize = params.pageSize || 50;
+    const intervalSteps = params.to.diff(params.from) / pageSize;
+    const startTime = params.from.valueOf();
+
+    for (let i = 0; i < pageSize; i += 1) {
+      const defaults: {[key: string]: any} = {logtime: startTime + (i * intervalSteps)};
+      if (params.mustBe) {
+        defaults.type = getRandomElement(params.mustBe);
+      }
+      if (params.hostList) {
+        defaults.host = getRandomElement(params.hostList);
+      }
+      if (params.level) {
+        defaults.level = getRandomElement(params.level);
+      }
+      list.push(generateServiceLog(defaults));
+    }
+    return {
+      'startIndex': params.startIndex,
+      'pageSize': pageSize,
+      'totalCount': 10 * pageSize,
+      'resultSize': 10 * pageSize,
+      'sortType': params.sortType,
+      'sortBy': params.sortBy,
+      'queryTimeMS': 1518013198573,
+      'logList': list
+    };
+  },
+  'api/v1/service/logs/logList': (query, request: Request) => {
+    const list = [];
+    const params = request.json();
+    params.to = moment(params.to);
+    params.from = moment(params.from);
+    const pageSize = params.pageSize || 50;
+    const intervalSteps = params.to.diff(params.from) / pageSize;
+    const startTime = params.from.valueOf();
+
+    for (let i = 0; i < pageSize; i += 1) {
+      const defaults: {[key: string]: any} = {
+        logtime: startTime + (i * intervalSteps),
+        event_dur_ms: getRandomInt(1000)
+      };
+      if (params.mustBe) {
+        defaults.type = getRandomElement(params.mustBe);
+      }
+      if (params.hostList) {
+        defaults.host = getRandomElement(params.hostList);
+      }
+      if (params.level) {
+        defaults.level = getRandomElement(params.level);
+      }
+      list.push(generateServiceLog(defaults));
+    }
+    return list;
+  },
+  'api/v1/service/logs/aggregated': {
+    graphData: [
+      {
+        name: 'n0',
+        count: 100,
+        dataList: [
+          {
+            name: 'n1',
+            count: 50,
+            dataList: null
+          },
+          {
+            name: 'n2',
+            count: 200,
+            dataList: null
+          }
+        ]
+      },
+      {
+        name: 'n3',
+        count: 10,
+        dataList: [
+          {
+            name: 'n4',
+            count: 5,
+            dataList: null
+          },
+          {
+            name: 'n5',
+            count: 20,
+            dataList: null
+          }
+        ]
+      }
+    ]
+  },
+  'api/v1/service/logs/components': {
+    'groups': {},
+    'metadata': components.map(comp => {
+      return {
+        name: comp,
+        label: comp.split('_').map(ucFirst).join(' '),
+        group: null
+      };
+    })
+  },
+  'api/v1/service/logs/components/levels/counts': {
+    vNodeList: [
+      {
+        name: 'ambari',
+        type: 0,
+        logLevelCount: [
+          {
+            name: 'ERROR',
+            value: '10'
+          },
+          {
+            name: 'WARN',
+            value: '50'
+          }
+        ],
+        childs: [
+          {
+            name: 'hdfs',
+            type: 2,
+            logLevelCount: [
+              {
+                name: 'ERROR',
+                value: '10'
+              },
+              {
+                name: 'WARN',
+                value: '20'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          },
+          {
+            name: 'zookeeper',
+            type: 3,
+            logLevelCount: [
+              {
+                name: 'ERROR',
+                value: '20'
+              },
+              {
+                name: 'WARN',
+                value: '40'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          }
+        ],
+        isParent: true,
+        isRoot: false
+      },
+      {
+        name: 'ambari_agent',
+        type: 1,
+        logLevelCount: [
+          {
+            name: 'ERROR',
+            value: '100'
+          },
+          {
+            name: 'WARN',
+            value: '500'
+          }
+        ],
+        isParent: false,
+        isRoot: false
+      }
+    ]
+  },
+  'api/v1/service/logs/files': {
+    hostLogFiles: {
+      clusters: clusters,
+      services: services
+    }
+  },
+  'api/v1/service/logs/histogram': (query: URLSearchParams, request: Request) => {
+    const body = request.json();
+    const unitParam: string[] = decodeURIComponent(body.unit).match(/(\d{1,})([a-zA-Z]{1,})/);
+    const unit: Base = <Base>unitParam[2];
+    const amount: number = parseInt(unitParam[1], 0);
+    const from = moment(decodeURIComponent(body.from));
+    const to = moment(decodeURIComponent(body.to));
+    return {
+      graphData: generateGraphData(from, to, unit, amount)
+    };
+  },
+  'api/v1/service/logs/hosts': {
+    groupList: hosts.map(host => Object.assign({}, {host}))
+  },
+  'api/v1/service/logs/schema/fields': [{
+    'name': 'cluster',
+    'label': 'Cluster',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'key_log_message',
+    'label': 'Key Log Message',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'type',
+    'label': 'Component',
+    'filterable': true,
+    'visible': true
+  }, {
+    'name': 'path',
+    'label': 'Path',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'logtype',
+    'label': 'Logtype',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'file',
+    'label': 'File',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'line_number',
+    'label': 'Line Number',
+    'filterable': true,
+    'visible': true
+  }, {
+    'name': 'host',
+    'label': 'Host',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'log_message',
+    'label': 'Message',
+    'filterable': true,
+    'visible': true
+  }, {
+    'name': 'logger_name',
+    'label': 'Logger Name',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'logfile_line_number',
+    'label': 'Logfile Line Number',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'group',
+    'label': 'Group',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'method',
+    'label': 'Method',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'level',
+    'label': 'Level',
+    'filterable': true,
+    'visible': true
+  }, {
+    'name': 'ip',
+    'label': 'Ip',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'thread_name',
+    'label': 'Thread',
+    'filterable': true,
+    'visible': false
+  }, {
+    'name': 'logtime',
+    'label': 'Log Time',
+    'filterable': true,
+    'visible': true
+  }],
+  'api/v1/service/logs/serviceconfig': '',
+  'api/v1/service/logs/tree': {
+    vNodeList: [
+      {
+        name: hosts[0],
+        type: 'H',
+        value: '1',
+        childs: [
+          {
+            name: 'ams_collector',
+            type: 'C',
+            value: '1',
+            logLevelCount: [
+              {
+                name: 'WARN',
+                value: '1'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          }
+        ],
+        logLevelCount: [
+          {
+            name: 'WARN',
+            value: '1'
+          }
+        ],
+        isParent: true,
+        isRoot: true
+      },
+      {
+        name: hosts[1],
+        type: 'H',
+        value: '6',
+        childs: [
+          {
+            name: 'ams_collector',
+            type: 'C',
+            value: '1',
+            logLevelCount: [
+              {
+                name: 'ERROR',
+                value: '1'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          },
+          {
+            name: 'ambari_agent',
+            type: 'C',
+            value: '1',
+            logLevelCount: [
+              {
+                name: 'FATAL',
+                value: '1'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          },
+          {
+            name: 'zookeeper_server',
+            type: 'C',
+            value: '2',
+            logLevelCount: [
+              {
+                name: 'INFO',
+                value: '1'
+              },
+              {
+                name: 'DEBUG',
+                value: '1'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          },
+          {
+            name: 'zookeeper_client',
+            type: 'C',
+            value: '2',
+            logLevelCount: [
+              {
+                name: 'TRACE',
+                value: '1'
+              },
+              {
+                name: 'UNKNOWN',
+                value: '1'
+              }
+            ],
+            isParent: false,
+            isRoot: false
+          }
+        ],
+        logLevelCount: [
+          {
+            name: 'ERROR',
+            value: '1'
+          },
+          {
+            name: 'FATAL',
+            value: '1'
+          },
+          {
+            name: 'INFO',
+            value: '1'
+          },
+          {
+            name: 'DEBUG',
+            value: '1'
+          },
+          {
+            name: 'TRACE',
+            value: '1'
+          },
+          {
+            name: 'UNKNOWN',
+            value: '1'
+          }
+        ],
+        isParent: true,
+        isRoot: true
+      }
+    ]
+  },
+  'api/v1/service/logs/truncated': {
+    logList: [
+      {
+        path: '/var/log/ambari-metrics-collector/ambari-metrics-collector.log',
+        host: 'h0',
+        level: 'WARN',
+        logtime: '2017-05-28T11:30:22.531Z',
+        ip: '192.168.0.1',
+        logfile_line_number: 8,
+        type: 'ams_collector',
+        _version_: 9,
+        id: 'id2',
+        file: 'ambari-metrics-collector.log',
+        seq_num: 10,
+        bundle_id: 'b2',
+        case_id: 'c2',
+        log_message: 'Connection refused',
+        message_md5: '1357908642',
+        cluster: 'cl2',
+        event_count: 5,
+        event_md5: '1908755391',
+        event_dur_ms: 200,
+        _ttl_: '+5DAYS',
+        _expire_at_: '2017-05-29T11:30:22.531Z',
+        _router_field_: 20
+      },
+      {
+        path: '/var/log/ambari-metrics-collector/ambari-metrics-collector.log',
+        host: 'h1',
+        level: 'ERROR',
+        logtime: '2017-05-28T10:30:22.531Z',
+        ip: '192.168.0.2',
+        type: 'ams_collector',
+        _version_: 14,
+        id: 'id3',
+        file: 'ambari-metrics-collector.log',
+        seq_num: 15,
+        bundle_id: 'b3',
+        case_id: 'c3',
+        log_message: 'Connection refused',
+        logfile_line_number: 16,
+        message_md5: '1357908642',
+        cluster: 'cl3',
+        event_count: 2,
+        event_md5: '1029384756',
+        event_dur_ms: 700,
+        _ttl_: '+5DAYS',
+        _expire_at_: '2017-05-29T10:30:22.531Z',
+        _router_field_: 5
+      }
+    ]
+  },
+  'api/v1/service/logs/clusters': clusters,
+  '.*': {}
 };

-- 
To stop receiving notification emails like this one, please contact
ababiichuk@apache.org.