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/01/05 23:30:23 UTC

[2/2] ambari git commit: AMBARI-22741 Log Search UI: implement graph for access logs. (ababiichuk)

AMBARI-22741 Log Search UI: implement graph for access logs. (ababiichuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/011e448e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/011e448e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/011e448e

Branch: refs/heads/trunk
Commit: 011e448e22acf6b5f677aaab0c41d064e4d66577
Parents: 2b9a34b
Author: ababiichuk <ab...@hortonworks.com>
Authored: Fri Jan 5 21:37:12 2018 +0200
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Fri Jan 5 21:37:12 2018 +0200

----------------------------------------------------------------------
 .../ambari-logsearch-web/src/app/app.module.ts  |   4 +
 .../components/graph/graph.component.less       |   1 +
 .../classes/components/graph/graph.component.ts |  75 ++++--
 .../components/graph/time-graph.component.less  |  48 ++++
 .../components/graph/time-graph.component.ts    | 250 +++++++++++++++++++
 .../src/app/classes/graph.ts                    |  19 ++
 .../src/app/classes/models/store.ts             |   1 +
 .../audit-logs-graph-query-params.spec.ts       | 203 +++++++++++++++
 .../queries/audit-logs-graph-query-params.ts    |  69 +++++
 .../service-logs-histogram-query-params.spec.ts | 203 ---------------
 .../service-logs-histogram-query-params.ts      |  50 +---
 .../audit-logs-entries.component.html           |  10 +-
 .../audit-logs-entries.component.spec.ts        |   3 +
 .../audit-logs-table.component.spec.ts          |   7 +-
 .../collapsible-panel.component.html            |   6 +-
 .../collapsible-panel.component.spec.ts         |   4 +-
 .../collapsible-panel.component.ts              |   4 +-
 .../dropdown-button.component.spec.ts           |   7 +-
 .../dropdown-list.component.spec.ts             |   7 +-
 .../filter-button.component.spec.ts             |   7 +-
 .../filter-dropdown.component.spec.ts           |   3 +
 .../filters-panel.component.spec.ts             |   7 +-
 .../horizontal-histogram.component.ts           |   8 +-
 .../log-context/log-context.component.spec.ts   |   7 +-
 .../logs-container.component.html               |  28 ++-
 .../logs-container.component.spec.ts            |   7 +-
 .../logs-container/logs-container.component.ts  |  30 ++-
 .../menu-button/menu-button.component.spec.ts   |   7 +-
 .../service-logs-table.component.spec.ts        |   7 +-
 .../time-histogram.component.html               |   2 +-
 .../time-histogram.component.less               |  36 ---
 .../time-histogram.component.spec.ts            |   1 -
 .../time-histogram/time-histogram.component.ts  | 247 +-----------------
 .../time-line-graph.component.html              |  27 ++
 .../time-line-graph.component.less              |  42 ++++
 .../time-line-graph.component.spec.ts           |  69 +++++
 .../time-line-graph.component.ts                | 111 ++++++++
 .../time-range-picker.component.spec.ts         |   7 +-
 .../timezone-picker.component.spec.ts           |   7 +-
 .../top-menu/top-menu.component.spec.ts         |   3 +
 .../ambari-logsearch-web/src/app/mock-data.ts   |  36 ++-
 .../services/component-actions.service.spec.ts  |   7 +-
 .../component-generator.service.spec.ts         |   7 +-
 .../src/app/services/http-client.service.ts     |   5 +
 .../app/services/logs-container.service.spec.ts |   3 +
 .../src/app/services/logs-container.service.ts  |  61 ++---
 .../storage/audit-logs-graph-data.service.ts    |  32 +++
 .../app/services/storage/reducers.service.ts    |   2 +
 .../src/assets/i18n/en.json                     |   1 +
 49 files changed, 1164 insertions(+), 624 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
index da78a71..6258c73 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
@@ -42,6 +42,7 @@ import {ComponentGeneratorService} from '@app/services/component-generator.servi
 import {AppSettingsService} from '@app/services/storage/app-settings.service';
 import {AppStateService} from '@app/services/storage/app-state.service';
 import {AuditLogsService} from '@app/services/storage/audit-logs.service';
+import {AuditLogsGraphDataService} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService} from '@app/services/storage/service-logs.service';
 import {ServiceLogsHistogramDataService} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService} from '@app/services/storage/service-logs-truncated.service';
@@ -92,6 +93,7 @@ import {GraphLegendComponent} from '@app/components/graph-legend/graph-legend.co
 import {HorizontalHistogramComponent} from '@app/components/horizontal-histogram/horizontal-histogram.component';
 import {GraphTooltipComponent} from '@app/components/graph-tooltip/graph-tooltip.component';
 import {GraphLegendItemComponent} from '@app/components/graph-legend-item/graph-legend-item.component';
+import {TimeLineGraphComponent} from '@app/components/time-line-graph/time-line-graph.component';
 
 import {TimeZoneAbbrPipe} from '@app/pipes/timezone-abbr.pipe';
 import {TimerSecondsPipe} from '@app/pipes/timer-seconds.pipe';
@@ -153,6 +155,7 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
     HorizontalHistogramComponent,
     GraphTooltipComponent,
     GraphLegendItemComponent,
+    TimeLineGraphComponent,
     TimeZoneAbbrPipe,
     TimerSecondsPipe
   ],
@@ -182,6 +185,7 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
     AppSettingsService,
     AppStateService,
     AuditLogsService,
+    AuditLogsGraphDataService,
     ServiceLogsService,
     ServiceLogsHistogramDataService,
     ServiceLogsTruncatedService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.less
index 0830193..3a57838 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.less
@@ -25,6 +25,7 @@
       stroke: @base-font-color;
     }
     .tick {
+      cursor: default;
       line {
         display: none;
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.ts
index 1bb7f92..167f478 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/graph.component.ts
@@ -19,7 +19,9 @@
 import {AfterViewInit, OnChanges, SimpleChanges, ViewChild, ElementRef, Input} from '@angular/core';
 import * as d3 from 'd3';
 import * as d3sc from 'd3-scale-chromatic';
-import {GraphPositionOptions, GraphMarginOptions, GraphTooltipInfo, LegendItem} from '@app/classes/graph';
+import {
+  GraphPositionOptions, GraphMarginOptions, GraphTooltipInfo, LegendItem, GraphEventData
+} from '@app/classes/graph';
 import {HomogeneousObject} from '@app/classes/object';
 import {ServiceInjector} from '@app/classes/service-injector';
 import {UtilsService} from '@app/services/utils.service';
@@ -96,6 +98,27 @@ export class GraphComponent implements AfterViewInit, OnChanges {
   @Input()
   reverseYRange: boolean = false;
 
+  /**
+   * Indicates whether X axis ticks with fractional values should be displayed on chart (if any)
+   * @type {boolean}
+   */
+  @Input()
+  allowFractionalXTicks: boolean = true;
+
+  /**
+   * Indicates whether Y axis ticks with fractional values should be displayed on chart (if any)
+   * @type {boolean}
+   */
+  @Input()
+  allowFractionalYTicks: boolean = true;
+
+  /**
+   * Indicated whether Y values equal to 0 should be skipped in tooltip
+   * @type {boolean}
+   */
+  @Input()
+  skipZeroValuesInTooltip: boolean = true;
+
   @ViewChild('graphContainer')
   graphContainerRef: ElementRef;
 
@@ -134,8 +157,8 @@ export class GraphComponent implements AfterViewInit, OnChanges {
   protected tooltipInfo: GraphTooltipInfo | {} = {};
 
   /**
-   * This is the computed position of the tooltip relative to the @graphContainer which is the container of the histogram.
-   * It is set when the mousemoving over the bars in the @handleRectMouseMove method.
+   * This is the computed position of the tooltip relative to the @graphContainer which is the container of the graph.
+   * It is set when the mousemoving over the figures in the @handleRectMouseMove method.
    */
   private tooltipPosition: GraphPositionOptions;
 
@@ -230,8 +253,16 @@ export class GraphComponent implements AfterViewInit, OnChanges {
 
   protected populate(): void {}
 
+  /**
+   * Set the domain values for the x scale regarding the given data.
+   * @param formattedData
+   */
   protected setXScaleDomain(formattedData?: any): void {}
 
+  /**
+   * Set the domain for the y scale regarding the given data.
+   * @param formattedData
+   */
   protected setYScaleDomain(formattedData?: any): void {}
 
   /**
@@ -271,7 +302,11 @@ export class GraphComponent implements AfterViewInit, OnChanges {
    * @returns {string|undefined}
    */
   protected xAxisTickFormatter = (tick: any, index: number): string | undefined => {
-    return tick.toString();
+    if (this.allowFractionalXTicks) {
+      return tick.toString();
+    } else {
+      return Number.isInteger(tick) ? tick.toFixed(0) : undefined;
+    }
   };
 
   /**
@@ -283,45 +318,53 @@ export class GraphComponent implements AfterViewInit, OnChanges {
    * @returns {string|undefined}
    */
   protected yAxisTickFormatter = (tick: any, index: number): string | undefined => {
-    return tick.toString();
+    if (this.allowFractionalYTicks) {
+      return tick.toString();
+    } else {
+      return Number.isInteger(tick) ? tick.toFixed(0) : undefined;
+    }
   };
 
   /**
-   * The goal is to handle the mouse over event on the rect svg elements so that we can populate the tooltip info object
+   * The goal is to handle the mouse over event on the svg elements so that we can populate the tooltip info object
    * and set the initial position of the tooltip. So we call the corresponding methods.
-   * @param d The data for the currently "selected" bar
+   * @param {GraphEventData} d The data for the currently "selected" figure
    * @param {number} index The index of the current element in the selection
    * @param elements The selection of the elements
    */
-  protected handleRectMouseOver = (d: {data: any, [key: string]: any}, index: number, elements: any): void => {
+  protected handleMouseOver = (d: GraphEventData, index: number, elements: HTMLElement[]): void => {
     this.setTooltipDataFromChartData(d);
     this.setTooltipPosition();
   };
 
   /**
-   * The goal is to handle the movement of the mouse over the rect svg elements, so that we can set the position of
+   * The goal is to handle the movement of the mouse over the svg elements, so that we can set the position of
    * the tooltip by calling the @setTooltipPosition method.
    */
-  protected handleRectMouseMove = (): void => {
+  protected handleMouseMove = (): void => {
     this.setTooltipPosition();
   };
 
   /**
    * The goal is to reset the tooltipInfo object so that the tooltip will be hidden.
    */
-  protected handleRectMouseOut = (): void => {
+  protected handleMouseOut = (): void => {
     this.tooltipInfo = {};
   };
 
   /**
    * The goal is set the tooltip
-   * @param d
+   * @param {GraphEventData} d
    */
-  protected setTooltipDataFromChartData(d: {data: any, [key: string]: any}): void {
-    let {tick, ...data} = d.data;
-    let levelColors = this.colors;
+  protected setTooltipDataFromChartData(d: GraphEventData): void {
+    const {tick, ...data} = d.data,
+      levelColors = this.colors;
+    let tooltipKeys = Object.keys(levelColors);
+    if (this.skipZeroValuesInTooltip) {
+      tooltipKeys = tooltipKeys.filter((key: string): boolean => data[key] > 0)
+    }
     this.tooltipInfo = {
-      data: Object.keys(levelColors).filter((key: string): boolean => data[key] > 0).map((key: string): object => Object.assign({}, {
+      data: tooltipKeys.map((key: string): object => Object.assign({}, {
         color: this.colors[key],
         label: this.labels[key],
         value: data[key]

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.less
new file mode 100644
index 0000000..d616b58
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.less
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import '../../../components/mixins';
+
+:host {
+  background: #ECECEC; // TODO add style according to actual design
+
+  /deep/ svg {
+    cursor: crosshair;
+  }
+
+  .time-gap {
+    color: @base-font-color;
+    font-size: 1.2rem;
+    text-align: center;
+  }
+
+  footer {
+    .default-flex;
+    font-size: 1.2rem;
+    color: @base-font-color;
+    padding: 0 1em .5em;
+  }
+
+  /deep/ rect.drag-area {
+    fill: #fff;
+  }
+
+  /deep/ rect.unselected-drag-area {
+    fill: darken(@main-background-color, 10%);
+    opacity: .6;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.ts
new file mode 100644
index 0000000..4e0aa10
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/graph/time-graph.component.ts
@@ -0,0 +1,250 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {OnInit, Input, Output, EventEmitter} from '@angular/core';
+import * as d3 from 'd3';
+import * as moment from 'moment-timezone';
+import {AppSettingsService} from '@app/services/storage/app-settings.service';
+import {ChartTimeGap, GraphScaleItem} from '@app/classes/graph';
+import {ServiceInjector} from '@app/classes/service-injector';
+import {GraphComponent} from '@app/classes/components/graph/graph.component';
+
+export class TimeGraphComponent extends GraphComponent implements OnInit {
+
+  constructor() {
+    super();
+    this.appSettings = ServiceInjector.injector.get(AppSettingsService);
+  }
+
+  ngOnInit() {
+    this.appSettings.getParameter('timeZone').subscribe((value: string): void => {
+      this.timeZone = value;
+      this.createGraph();
+    });
+  }
+
+  @Input()
+  tickTimeFormat: string = 'MM/DD HH:mm';
+
+  @Input()
+  historyStartEndTimeFormat: string = 'dddd, MMMM DD, YYYY';
+
+  @Output()
+  selectArea: EventEmitter<number[]> = new EventEmitter();
+
+  readonly isTimeGraph: boolean = true;
+
+  readonly allowFractionalXTicks: boolean = false;
+
+  protected appSettings: AppSettingsService;
+
+  protected dragArea: d3.Selection<SVGGraphicsElement, undefined, SVGGraphicsElement, undefined>;
+
+  protected dragStartX: number;
+
+  protected minDragX: number;
+
+  protected maxDragX: number;
+
+  protected timeZone: string;
+
+  /**
+   * This property holds the data structure describing the gaps between the xAxis ticks.
+   * The unit property can be: second, minute, hour, day
+   * The value is the number of the given unit.
+   */
+  protected chartTimeGap: ChartTimeGap | null;
+  /**
+   * This is the rectangle element to represent the unselected time range on the left side of the selected time range
+   */
+  protected leftDragArea: d3.Selection<SVGGraphicsElement, undefined, SVGGraphicsElement, undefined>;
+  /**
+   * This is the rectangle element to represent the unselected time range on the right side of the selected time range
+   */
+  protected rightDragArea: d3.Selection<SVGGraphicsElement, undefined, SVGGraphicsElement, undefined>;
+
+  /**
+   * This is a Date object holding the value of the first tick of the xAxis. It is a helper getter for the template.
+   */
+  protected get firstDateTick(): Date | undefined {
+    const ticks = this.xScale && this.xScale.ticks();
+    return (ticks && ticks.length && ticks[0]) || undefined;
+  }
+
+  /**
+   * This is a Date object holding the value of the last tick of the xAxis. It is a helper getter for the template.
+   */
+  protected get lastDateTick(): Date | undefined {
+    const ticks = this.xScale && this.xScale.ticks();
+    return (ticks && ticks.length && ticks[ticks.length - 1]) || undefined;
+  }
+
+  protected xAxisTickFormatter = (tick: Date): string => {
+    return moment(tick).tz(this.timeZone).format(this.tickTimeFormat);
+  };
+
+  protected setXScaleDomain(data: GraphScaleItem[]): void {
+    this.xScale.domain(d3.extent(data, item => item.tick)).nice();
+  }
+
+  /**
+   * The goal is to calculate the time gap between the given dates. It will return an object representing the unit and
+   * the value in the given unit. Eg.: {unit: 'minute', value: 5}
+   * @param {Date} startDate
+   * @param {Date} endDate
+   * @returns {ChartTimeGap}
+   */
+  protected getTimeGap(startDate: Date, endDate: Date): ChartTimeGap {
+    const startDateMoment = moment(startDate);
+    const endDateMoment = moment(endDate);
+    const diffInWeek: number = endDateMoment.diff(startDateMoment, 'weeks');
+    const diffInDay: number = endDateMoment.diff(startDateMoment, 'days');
+    const diffInHour: number = endDateMoment.diff(startDateMoment, 'hours');
+    const diffInMin: number = endDateMoment.diff(startDateMoment, 'minutes');
+    const diffInSec: number = endDateMoment.diff(startDateMoment, 'seconds');
+    const value = diffInWeek >= 1 ? diffInWeek : (
+      diffInDay >= 1 ? diffInDay : (
+        diffInHour >= 1 ? diffInHour : (diffInMin >= 1 ? diffInMin : diffInSec)
+      )
+    );
+    const unit: string = diffInWeek >= 1 ? 'week' : (
+      diffInDay >= 1 ? `day` : (
+        diffInHour >= 1 ? `hour` : (diffInMin >= 1 ? `minute` : `second`)
+      )
+    );
+    const label = `histogram.gap.${unit}${value > 1 ? 's' : ''}`;
+    return {
+      value,
+      unit,
+      label
+    };
+  }
+
+  /**
+   * The goal is to have a simple function to set the time gap corresponding to the xScale ticks.
+   * It will reset the time gap if the xScale is not set or there are no ticks.
+   */
+  protected setChartTimeGapByXScale(): void {
+    let ticks = this.xScale && this.xScale.ticks();
+    if (ticks && ticks.length) {
+      this.setChartTimeGap(ticks[0], ticks[1] || ticks[0]);
+    } else {
+      this.resetChartTimeGap();
+    }
+  }
+
+  /**
+   * Simply reset the time gap property to null.
+   */
+  protected resetChartTimeGap(): void {
+    this.chartTimeGap = null;
+  }
+
+  /**
+   * The goal is to have a single point where we set the chartTimeGap property corresponding the given timerange.
+   * @param {Date} startDate
+   * @param {Date} endDate
+   */
+  protected setChartTimeGap(startDate: Date, endDate: Date): void {
+    this.chartTimeGap = this.getTimeGap(startDate, endDate);
+  }
+
+  protected getTimeRangeByXRanges(startX: number, endX: number): [number, number] {
+    const xScaleInterval = this.xScale.domain().map((point: Date): number => point.valueOf());
+    const xScaleLength = xScaleInterval[1] - xScaleInterval[0];
+    const ratio = xScaleLength / this.width;
+    return [Math.round(xScaleInterval[0] + ratio * startX), Math.round(xScaleInterval[0] + ratio * endX)];
+  }
+
+  /**
+   * The goal is to create the two shadow rectangle beside the selected area. Actually we blurout the not selected
+   * timeranges
+   * @param {number} startX This is the starting position of the drag event withing the container
+   * @param {number} currentX This is the ending point of the drag within the container
+   */
+  protected createInvertDragArea(startX: number, currentX: number): void {
+    const height: number = this.height + this.margin.top + this.margin.bottom;
+    this.leftDragArea = this.svg.insert('rect').attr('height', height).attr('class', 'unselected-drag-area');
+    this.rightDragArea = this.svg.insert('rect').attr('height', height).attr('class', 'unselected-drag-area');
+    this.setInvertDragArea(startX, currentX);
+  }
+
+  /**
+   * Set the position and the width of the blur/shadow rectangles of the unselected area(s).
+   * @param {number} startX The start point of the selected area.
+   * @param {number} currentX The end point of the selected area.
+   */
+  protected setInvertDragArea(startX: number, currentX: number): void {
+    const left: number = Math.min(startX, currentX);
+    const right: number = Math.max(startX, currentX);
+    const rightAreaWidth: number = Math.max(0, this.width - right);
+    const leftAreaWidth: number = Math.max(0, left);
+    this.leftDragArea.attr('x', 0).attr('width', leftAreaWidth);
+    this.rightDragArea.attr('x', right).attr('width', rightAreaWidth);
+  }
+
+  /**
+   * The goal is to have a single point where we remove the rectangles of the blur/shadow, unselected time range(s)
+   */
+  protected clearInvertDragArea(): void {
+    this.leftDragArea.remove();
+    this.rightDragArea.remove();
+  }
+
+  protected setDragBehavior(): void {
+    this.minDragX = this.margin.left;
+    this.maxDragX = this.graphContainer.clientWidth;
+    d3.selectAll(`svg#${this.svgId}`).call(d3.drag()
+      .on('start', (datum: undefined, index: number, containers: d3.ContainerElement[]): void => {
+        if (this.dragArea) {
+          this.dragArea.remove();
+        }
+        this.dragStartX = Math.max(0, this.getDragX(containers[0]) - this.margin.left);
+        this.dragArea = this.svg.insert('rect', ':first-child').attr('x', this.dragStartX).attr('y', 0).attr('width', 0)
+          .attr('height', this.height).attr('class', 'drag-area');
+      })
+      .on('drag', (datum: undefined, index: number, containers: d3.ContainerElement[]): void => {
+        const mousePos = this.getDragX(containers[0]);
+        const currentX = Math.max(mousePos, this.minDragX) - this.margin.left;
+        const startX = Math.min(currentX, this.dragStartX);
+        const currentWidth = Math.abs(currentX - this.dragStartX);
+        this.dragArea.attr('x', startX).attr('width', currentWidth);
+        let timeRange = this.getTimeRangeByXRanges(startX, startX + currentWidth);
+        this.setChartTimeGap(new Date(timeRange[0]), new Date(timeRange[1]));
+      })
+      .on('end', (): void => {
+        const dragAreaDetails = this.dragArea.node().getBBox();
+        const startX = Math.max(0, dragAreaDetails.x);
+        const endX = Math.min(this.width, dragAreaDetails.x + dragAreaDetails.width);
+        const dateRange: [number, number] = this.getTimeRangeByXRanges(startX, endX);
+        this.selectArea.emit(dateRange);
+        this.dragArea.remove();
+        this.setChartTimeGap(new Date(dateRange[0]), new Date(dateRange[1]));
+      })
+    );
+    d3.selectAll(`svg#${this.svgId} .value, svg#${this.svgId} .axis`).call(d3.drag().on('start', (): void => {
+      d3.event.sourceEvent.stopPropagation();
+    }));
+  }
+
+  protected getDragX(element: d3.ContainerElement): number {
+    return d3.mouse(element)[0];
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/graph.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/graph.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/graph.ts
index 3992828..cc07ec8 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/graph.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/graph.ts
@@ -40,3 +40,22 @@ export interface GraphScaleItem {
   tick: number;
   [key: string]: number;
 }
+
+export interface ChartTimeGap {
+  value: number;
+  unit: string;
+  label: string;
+}
+
+export interface GraphEventData extends Array<number> {
+  data: GraphScaleItem;
+}
+
+export type GraphLinePoint = GraphScaleItem & {
+  color: string;
+}
+
+export interface GraphLineData {
+  points: GraphScaleItem[];
+  key: string;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/store.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/store.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/store.ts
index f996d92..f2d0696 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/store.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/store.ts
@@ -46,6 +46,7 @@ export interface AppStore {
   appSettings: AppSettings;
   appState: AppState;
   auditLogs: AuditLog[];
+  auditLogsGraphData: BarGraph[];
   serviceLogs: ServiceLog[];
   serviceLogsHistogramData: BarGraph[];
   serviceLogsTruncated: ServiceLog[];

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.spec.ts
new file mode 100644
index 0000000..8951dff
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.spec.ts
@@ -0,0 +1,203 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {AuditLogsGraphQueryParams} from './audit-logs-graph-query-params';
+
+describe('AuditLogsGraphQueryParams', () => {
+
+  describe('constructor', () => {
+    const cases = [
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:00:00.100Z'
+        },
+        unit: '+100MILLISECOND',
+        title: 'less than 1s'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:00:01Z'
+        },
+        unit: '+100MILLISECOND',
+        title: '1s'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:00:20Z'
+        },
+        unit: '+500MILLISECOND',
+        title: 'between 1s and 30s'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:00:20Z'
+        },
+        unit: '+500MILLISECOND',
+        title: '30s'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:00:40Z'
+        },
+        unit: '+2SECOND',
+        title: 'between 30s and 1m'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:01:00Z'
+        },
+        unit: '+2SECOND',
+        title: '1m'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:20:00Z'
+        },
+        unit: '+1MINUTE',
+        title: 'between 1m and 30m'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T00:30:00Z'
+        },
+        unit: '+2MINUTE',
+        title: '30m'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T01:00:00Z'
+        },
+        unit: '+2MINUTE',
+        title: 'between 30m and 2h'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T02:00:00Z'
+        },
+        unit: '+5MINUTE',
+        title: '2h'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T04:00:00Z'
+        },
+        unit: '+5MINUTE',
+        title: 'between 2h and 6h'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T06:00:00Z'
+        },
+        unit: '+10MINUTE',
+        title: '6h'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T08:00:00Z'
+        },
+        unit: '+10MINUTE',
+        title: 'between 6h and 10h'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T10:00:00Z'
+        },
+        unit: '+10MINUTE',
+        title: '10h'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-01T22:00:00Z'
+        },
+        unit: '+1HOUR',
+        title: 'between 10h and 1d'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-02T00:00:00Z'
+        },
+        unit: '+1HOUR',
+        title: '1d'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-10T00:00:00Z'
+        },
+        unit: '+8HOUR',
+        title: 'between 1d and 15d'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-01-16T00:00:00Z'
+        },
+        unit: '+1DAY',
+        title: '15d'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-03-31T00:00:00Z'
+        },
+        unit: '+1DAY',
+        title: 'between 15d and 3M'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-04-01T00:00:00Z'
+        },
+        unit: '+1DAY',
+        title: '3M'
+      },
+      {
+        options: {
+          from: '2017-01-01T00:00:00Z',
+          to: '2017-05-01T00:00:00Z'
+        },
+        unit: '+1MONTH',
+        title: 'over 3M'
+      }
+    ];
+
+    cases.forEach(test => {
+      it(test.title, () => {
+        const paramsObject = new AuditLogsGraphQueryParams(test.options);
+        expect(paramsObject.unit).toEqual(test.unit);
+      });
+    });
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.ts
new file mode 100644
index 0000000..7e63acf
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-graph-query-params.ts
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {QueryParams} from '@app/classes/queries/query-params';
+
+export class AuditLogsGraphQueryParams extends QueryParams {
+  constructor(options: AuditLogsGraphQueryParams) {
+    let unit;
+    const diffTimeStamp = new Date(options.to).valueOf() - new Date(options.from).valueOf();
+    switch (true) {
+      case diffTimeStamp <= 1000:
+        unit = '+100MILLISECOND';
+        break;
+      case diffTimeStamp <= 30000:
+        unit = '+500MILLISECOND';
+        break;
+      case diffTimeStamp <= 60000:
+        unit = '+2SECOND';
+        break;
+      case diffTimeStamp < 1800000:
+        unit = '+1MINUTE';
+        break;
+      case diffTimeStamp < 7200000:
+        unit = '+2MINUTE';
+        break;
+      case diffTimeStamp < 21600000:
+        unit = '+5MINUTE';
+        break;
+      case diffTimeStamp <= 36000000:
+        unit = '+10MINUTE';
+        break;
+      case diffTimeStamp <= 86400000:
+        unit = '+1HOUR';
+        break;
+      case diffTimeStamp < 1296000000:
+        unit = '+8HOUR';
+        break;
+      case diffTimeStamp <= 7776000000:
+        unit = '+1DAY';
+        break;
+      default:
+        unit = '+1MONTH';
+        break;
+    }
+    options.unit = unit;
+    super(options);
+  }
+
+  from: string;
+  to: string;
+  unit?: string;
+  includeQuery?: string;
+  excludeQuery?: string;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.spec.ts
deleted file mode 100644
index eb891ed..0000000
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.spec.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import {ServiceLogsHistogramQueryParams} from './service-logs-histogram-query-params';
-
-describe('ServiceLogsHistogramQueryParams', () => {
-
-  describe('constructor', () => {
-    const cases = [
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:00:00.100Z'
-        },
-        unit: '+100MILLISECOND',
-        title: 'less than 1s'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:00:01Z'
-        },
-        unit: '+100MILLISECOND',
-        title: '1s'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:00:20Z'
-        },
-        unit: '+500MILLISECOND',
-        title: 'between 1s and 30s'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:00:20Z'
-        },
-        unit: '+500MILLISECOND',
-        title: '30s'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:00:40Z'
-        },
-        unit: '+2SECOND',
-        title: 'between 30s and 1m'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:01:00Z'
-        },
-        unit: '+2SECOND',
-        title: '1m'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:20:00Z'
-        },
-        unit: '+1MINUTE',
-        title: 'between 1m and 30m'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T00:30:00Z'
-        },
-        unit: '+2MINUTE',
-        title: '30m'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T01:00:00Z'
-        },
-        unit: '+2MINUTE',
-        title: 'between 30m and 2h'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T02:00:00Z'
-        },
-        unit: '+5MINUTE',
-        title: '2h'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T04:00:00Z'
-        },
-        unit: '+5MINUTE',
-        title: 'between 2h and 6h'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T06:00:00Z'
-        },
-        unit: '+10MINUTE',
-        title: '6h'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T08:00:00Z'
-        },
-        unit: '+10MINUTE',
-        title: 'between 6h and 10h'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T10:00:00Z'
-        },
-        unit: '+10MINUTE',
-        title: '10h'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-01T22:00:00Z'
-        },
-        unit: '+1HOUR',
-        title: 'between 10h and 1d'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-02T00:00:00Z'
-        },
-        unit: '+1HOUR',
-        title: '1d'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-10T00:00:00Z'
-        },
-        unit: '+8HOUR',
-        title: 'between 1d and 15d'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-01-16T00:00:00Z'
-        },
-        unit: '+1DAY',
-        title: '15d'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-03-31T00:00:00Z'
-        },
-        unit: '+1DAY',
-        title: 'between 15d and 3M'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-04-01T00:00:00Z'
-        },
-        unit: '+1DAY',
-        title: '3M'
-      },
-      {
-        options: {
-          from: '2017-01-01T00:00:00Z',
-          to: '2017-05-01T00:00:00Z'
-        },
-        unit: '+1MONTH',
-        title: 'over 3M'
-      }
-    ];
-
-    cases.forEach(test => {
-      it(test.title, () => {
-        const paramsObject = new ServiceLogsHistogramQueryParams(test.options);
-        expect(paramsObject.unit).toEqual(test.unit);
-      });
-    });
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.ts
index 148aa62..ff83a8b 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-histogram-query-params.ts
@@ -16,55 +16,9 @@
  * limitations under the License.
  */
 
-import {QueryParams} from '@app/classes/queries/query-params';
+import {AuditLogsGraphQueryParams} from '@app/classes/queries/audit-logs-graph-query-params';
 
-export class ServiceLogsHistogramQueryParams extends QueryParams {
-  constructor(options: ServiceLogsHistogramQueryParams) {
-    let unit;
-    const diffTimeStamp = new Date(options.to).valueOf() - new Date(options.from).valueOf();
-    switch (true) {
-      case diffTimeStamp <= 1000:
-        unit = '+100MILLISECOND';
-        break;
-      case diffTimeStamp <= 30000:
-        unit = '+500MILLISECOND';
-        break;
-      case diffTimeStamp <= 60000:
-        unit = '+2SECOND';
-        break;
-      case diffTimeStamp < 1800000:
-        unit = '+1MINUTE';
-        break;
-      case diffTimeStamp < 7200000:
-        unit = '+2MINUTE';
-        break;
-      case diffTimeStamp < 21600000:
-        unit = '+5MINUTE';
-        break;
-      case diffTimeStamp <= 36000000:
-        unit = '+10MINUTE';
-        break;
-      case diffTimeStamp <= 86400000:
-        unit = '+1HOUR';
-        break;
-      case diffTimeStamp < 1296000000:
-        unit = '+8HOUR';
-        break;
-      case diffTimeStamp <= 7776000000:
-        unit = '+1DAY';
-        break;
-      default:
-        unit = '+1MONTH';
-        break;
-    }
-    options.unit = unit;
-    super(options);
-  }
-  from: string;
-  to: string;
-  unit?: string;
+export class ServiceLogsHistogramQueryParams extends AuditLogsGraphQueryParams {
   clusters?: string;
   level?: string;
-  includeQuery?: string;
-  excludeQuery?: string;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.html
index 3c5852a..fe9f697 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.html
@@ -20,11 +20,13 @@
   <audit-logs-table *ngSwitchCase="'logs'" [totalCount]="totalCount" [logs]="logs" [columns]="columns"
                     [filtersForm]="filtersForm"></audit-logs-table>
   <div *ngSwitchCase="'summary'" class="row">
-    <collapsible-panel title="{{'logs.topUsers' | translate: usersGraphTitleParams}}" class="col-md-6">
-      <horizontal-histogram [data]="topUsersGraphData"></horizontal-histogram>
+    <collapsible-panel commonTitle="{{'logs.topUsers' | translate: usersGraphTitleParams}}" class="col-md-6">
+      <horizontal-histogram [data]="topUsersGraphData" [allowFractionalXTicks]="false"
+                            svgId="top-users-graph"></horizontal-histogram>
     </collapsible-panel>
-    <collapsible-panel title="{{'logs.topResources' | translate: resourcesGraphTitleParams}}" class="col-md-6">
-      <horizontal-histogram [data]="topResourcesGraphData"></horizontal-histogram>
+    <collapsible-panel commonTitle="{{'logs.topResources' | translate: resourcesGraphTitleParams}}" class="col-md-6">
+      <horizontal-histogram [data]="topResourcesGraphData" [allowFractionalXTicks]="false"
+                            svgId="top-resources-graph"></horizontal-histogram>
     </collapsible-panel>
   </div>
 </ng-container>

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.spec.ts
index 260b383..f7d0cdc 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-entries/audit-logs-entries.component.spec.ts
@@ -22,6 +22,7 @@ import {StoreModule} from '@ngrx/store';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
 import {
   ServiceLogsHistogramDataService, serviceLogsHistogramData
@@ -63,6 +64,7 @@ describe('AuditLogsEntriesComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           appSettings,
@@ -85,6 +87,7 @@ describe('AuditLogsEntriesComponent', () => {
         AuditLogsFieldsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
+        AuditLogsGraphDataService,
         AppSettingsService,
         AppStateService,
         ClustersService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
index b6206db..1a2f4de 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
@@ -26,8 +26,11 @@ import {TranslationModules} from '@app/test-config.spec';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
 import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
@@ -72,6 +75,7 @@ describe('AuditLogsTableComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           serviceLogsTruncated,
@@ -93,6 +97,7 @@ describe('AuditLogsTableComponent', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         ServiceLogsTruncatedService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html
index 4d0bd39..a671946 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html
@@ -15,13 +15,13 @@
   limitations under the License.
 -->
 <div [ngClass]="{'panel': true, 'panel-default': true, 'panel-collapsible': true, 'panel-collapsed': isCollapsed}">
-    <div [ngClass]="{'panel-heading': true}" (click)="handleCollapseBtnClick($event)">
+    <div class="panel-heading" (click)="handleCollapseBtnClick($event)">
       <a [attr.aria-collapsed]="isCollapsed">
         <i [ngClass]="{'fa': true, 'fa-caret-down': !isCollapsed, 'fa-caret-right': isCollapsed}"></i>
-        {{((isCollapsed ? collapsedTitle : openTitle) || title) | translate}}
+        {{((isCollapsed ? collapsedTitle : openTitle) || commonTitle) | translate}}
       </a>
     </div>
-    <div [ngClass]="{'panel-body': true}" [attr.aria-collapsed]="isCollapsed">
+    <div class="panel-body" [attr.aria-collapsed]="isCollapsed">
       <ng-content></ng-content>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts
index 5f5f1b0..f92f30a 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts
@@ -120,7 +120,7 @@ describe('CollapsiblePanelComponent', () => {
     let title = 'Title';
     let headingEl = el.querySelector('.panel-heading');
     component.openTitle = '';
-    component.title = title;
+    component.commonTitle = title;
     component.isCollapsed = false;
     fixture.detectChanges();
     expect(headingEl.textContent).toContain(title);
@@ -130,7 +130,7 @@ describe('CollapsiblePanelComponent', () => {
     let title = 'Title';
     let headingEl = el.querySelector('.panel-heading');
     component.collapsedTitle = '';
-    component.title = title;
+    component.commonTitle = title;
     component.isCollapsed = true;
     fixture.detectChanges();
     expect(headingEl.textContent).toContain(title);

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts
index f82823a..5e86bfa 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts
@@ -39,7 +39,7 @@ export class CollapsiblePanelComponent {
    * @type {string}
    */
   @Input()
-  title: string = '';
+  commonTitle: string = '';
 
   /**
    * The panel's title for the opened state
@@ -82,7 +82,7 @@ export class CollapsiblePanelComponent {
   /**
    * The goal is to simply negate the current collapse state.
    */
-  toggleCollapsed():void {
+  toggleCollapsed(): void {
     this.isCollapsed = !this.isCollapsed;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.spec.ts
index 9f2bb16..b9f9540 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.spec.ts
@@ -28,9 +28,12 @@ import {AppStateService, appState} from '@app/services/storage/app-state.service
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
 import {UtilsService} from '@app/services/utils.service';
@@ -65,6 +68,7 @@ describe('DropdownButtonComponent', () => {
           hosts,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -81,6 +85,7 @@ describe('DropdownButtonComponent', () => {
         HostsService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.spec.ts
index 63824cb..dd602d7 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.spec.ts
@@ -24,8 +24,11 @@ import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
 import {ClustersService, clusters} from '@app/services/storage/clusters.service';
@@ -62,6 +65,7 @@ describe('DropdownListComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           appSettings,
@@ -85,6 +89,7 @@ describe('DropdownListComponent', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         AppSettingsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-button/filter-button.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-button/filter-button.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-button/filter-button.component.spec.ts
index 082082c..4c93cbe 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-button/filter-button.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-button/filter-button.component.spec.ts
@@ -28,9 +28,12 @@ import {AppStateService, appState} from '@app/services/storage/app-state.service
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
 import {ComponentActionsService} from '@app/services/component-actions.service';
@@ -65,6 +68,7 @@ describe('FilterButtonComponent', () => {
           hosts,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -81,6 +85,7 @@ describe('FilterButtonComponent', () => {
         HostsService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
index d085f3e..61d30d1 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
@@ -24,6 +24,7 @@ import {AppSettingsService, appSettings} from '@app/services/storage/app-setting
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
 import {
@@ -79,6 +80,7 @@ describe('FilterDropdownComponent', () => {
           appState,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -95,6 +97,7 @@ describe('FilterDropdownComponent', () => {
         AppStateService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
index c9f9b52..8df1d54 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
@@ -28,8 +28,11 @@ import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
@@ -67,6 +70,7 @@ describe('FiltersPanelComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           appState,
@@ -83,6 +87,7 @@ describe('FiltersPanelComponent', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         AppStateService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/horizontal-histogram/horizontal-histogram.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/horizontal-histogram/horizontal-histogram.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/horizontal-histogram/horizontal-histogram.component.ts
index 9553e2e..8cc3149 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/horizontal-histogram/horizontal-histogram.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/horizontal-histogram/horizontal-histogram.component.ts
@@ -28,7 +28,7 @@ import {HomogeneousObject} from '@app/classes/object';
 export class HorizontalHistogramComponent extends GraphComponent {
 
   /**
-   * Thickness of horizontal bar o the graph
+   * Thickness of horizontal bar of the graph
    * @type {number}
    */
   @Input()
@@ -81,9 +81,9 @@ export class HorizontalHistogramComponent extends GraphComponent {
       }).attr('height', item => item[0] === item[1] ? '0' : barSize.toString())
       .attr('width', item => this.xScale(item[1]) - this.xScale(item[0]))
       .style('fill', (item, index) => this.orderedColors[index])
-      .on('mouseover', this.handleRectMouseOver)
-      .on('mousemove', this.handleRectMouseMove)
-      .on('mouseout', this.handleRectMouseOut);
+      .on('mouseover', this.handleMouseOver)
+      .on('mousemove', this.handleMouseMove)
+      .on('mouseout', this.handleMouseOut);
   }
 
   protected setXScaleDomain(): void {

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/log-context/log-context.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/log-context/log-context.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/log-context/log-context.component.spec.ts
index 7bd87ad..c346c9a 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/log-context/log-context.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/log-context/log-context.component.spec.ts
@@ -21,8 +21,11 @@ import {StoreModule} from '@ngrx/store';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
 import {ClustersService, clusters} from '@app/services/storage/clusters.service';
@@ -60,6 +63,7 @@ describe('LogContextComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           appSettings,
@@ -76,6 +80,7 @@ describe('LogContextComponent', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         AppSettingsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
index 8e507ae..412fd2c 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
@@ -34,21 +34,31 @@
     </div>
 
     <!-- TODO use plugin for singular/plural -->
-    <div class="logs-header col-md-12">{{
+    <div *ngIf="logsType === 'serviceLogs'" class="logs-header col-md-12">{{
       (!totalEventsFoundMessageParams.totalCount ? 'logs.noEventFound' :
         (totalEventsFoundMessageParams.totalCount === 1 ? 'logs.oneEventFound' : 'logs.totalEventFound'))
             | translate: totalEventsFoundMessageParams
     }}</div>
   </div>
-  <collapsible-panel openTitle="logs.hideGraph" collapsedTitle="logs.showGraph">
-    <time-histogram [data]="histogramData" [colors]="serviceLogsHistogramColors" svgId="service-logs-histogram"
-                    (selectArea)="setCustomTimeRange($event[0], $event[1])"></time-histogram>
-  </collapsible-panel>
   <ng-container [ngSwitch]="logsType">
-    <service-logs-table *ngSwitchCase="'serviceLogs'" [totalCount]="totalCount" [logs]="serviceLogs | async"
-                        [columns]="serviceLogsColumns | async" [filtersForm]="filtersForm"></service-logs-table>
-    <audit-logs-entries *ngSwitchCase="'auditLogs'" [totalCount]="totalCount" [logs]="auditLogs | async"
-                        [columns]="auditLogsColumns | async" [filtersForm]="filtersForm"></audit-logs-entries>
+    <ng-container *ngSwitchCase="'serviceLogs'">
+      <collapsible-panel openTitle="logs.hideGraph" collapsedTitle="logs.showGraph">
+        <time-histogram (selectArea)="setCustomTimeRange($event[0], $event[1])" [data]="serviceLogsHistogramData"
+                        [colors]="serviceLogsHistogramColors" [allowFractionalYTicks]="false"
+                        svgId="service-logs-histogram"></time-histogram>
+      </collapsible-panel>
+      <service-logs-table [totalCount]="totalCount" [logs]="serviceLogs | async" [columns]="serviceLogsColumns | async"
+                          [filtersForm]="filtersForm"></service-logs-table>
+    </ng-container>
+    <ng-container *ngSwitchCase="'auditLogs'">
+      <collapsible-panel commonTitle="logs.duration">
+        <time-line-graph (selectArea)="setCustomTimeRange($event[0], $event[1])" [data]="auditLogsGraphData"
+                         [allowFractionalYTicks]="false" [skipZeroValuesInTooltip]="false"
+                         svgId="audit-logs-graph"></time-line-graph>
+      </collapsible-panel>
+      <audit-logs-entries [totalCount]="totalCount" [logs]="auditLogs | async" [columns]="auditLogsColumns | async"
+                          [filtersForm]="filtersForm"></audit-logs-entries>
+    </ng-container>
   </ng-container>
   <log-context *ngIf="isServiceLogContextView" [id]="activeLog.id" [hostName]="activeLog.host_name"
                [componentName]="activeLog.component_name"></log-context>

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts
index 2bb8731..8a3d985 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts
@@ -26,9 +26,12 @@ import {ClustersService, clusters} from '@app/services/storage/clusters.service'
 import {ComponentsService, components} from '@app/services/storage/components.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
@@ -65,6 +68,7 @@ describe('LogsContainerComponent', () => {
           components,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -85,6 +89,7 @@ describe('LogsContainerComponent', () => {
         ComponentsService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
index 6d50a17..d853bb5 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
@@ -16,11 +16,12 @@
  * limitations under the License.
  */
 
-import {Component, ElementRef, ViewChild, HostListener} from '@angular/core';
+import {Component, OnInit, ElementRef, ViewChild, HostListener} from '@angular/core';
 import {FormGroup} from '@angular/forms';
 import {Observable} from 'rxjs/Observable';
 import {LogsContainerService} from '@app/services/logs-container.service';
 import {ServiceLogsHistogramDataService} from '@app/services/storage/service-logs-histogram-data.service';
+import {AuditLogsGraphDataService} from '@app/services/storage/audit-logs-graph-data.service';
 import {AppStateService} from '@app/services/storage/app-state.service';
 import {TabsService} from '@app/services/storage/tabs.service';
 import {AuditLog} from '@app/classes/models/audit-log';
@@ -38,18 +39,27 @@ import {FiltersPanelComponent} from "@app/components/filters-panel/filters-panel
   templateUrl: './logs-container.component.html',
   styleUrls: ['./logs-container.component.less']
 })
-export class LogsContainerComponent {
+export class LogsContainerComponent implements OnInit {
 
   constructor(
-    private serviceLogsHistogramStorage: ServiceLogsHistogramDataService, private appState: AppStateService,
-    private tabsStorage: TabsService, private logsContainer: LogsContainerService
+    private appState: AppStateService, private tabsStorage: TabsService, private logsContainer: LogsContainerService,
+    private serviceLogsHistogramStorage: ServiceLogsHistogramDataService,
+    private auditLogsGraphStorage: AuditLogsGraphDataService
   ) {
+  }
+
+  ngOnInit() {
     this.logsContainer.loadColumnsNames();
-    appState.getParameter('activeLogsType').subscribe((value: LogsType) => this.logsType = value);
-    serviceLogsHistogramStorage.getAll().subscribe((data: BarGraph[]): void => {
-      this.histogramData = this.logsContainer.getHistogramData(data);
+    this.appState.getParameter('activeLogsType').subscribe((value: LogsType) => this.logsType = value);
+    this.serviceLogsHistogramStorage.getAll().subscribe((data: BarGraph[]): void => {
+      this.serviceLogsHistogramData = this.logsContainer.getGraphData(data, Object.keys(this.logsContainer.colors));
+    });
+    this.auditLogsGraphStorage.getAll().subscribe((data: BarGraph[]): void => {
+      this.auditLogsGraphData = this.logsContainer.getGraphData(data);
+    });
+    this.appState.getParameter('isServiceLogContextView').subscribe((value: boolean): void => {
+      this.isServiceLogContextView = value;
     });
-    appState.getParameter('isServiceLogContextView').subscribe((value: boolean) => this.isServiceLogContextView = value);
   }
 
   @ViewChild('container') containerRef: ElementRef;
@@ -74,7 +84,9 @@ export class LogsContainerComponent {
     return this.logsContainer.totalCount;
   }
 
-  histogramData: HomogeneousObject<HomogeneousObject<number>>;
+  serviceLogsHistogramData: HomogeneousObject<HomogeneousObject<number>>;
+
+  auditLogsGraphData: HomogeneousObject<HomogeneousObject<number>>;
 
   get serviceLogsHistogramColors(): HomogeneousObject<string> {
     return this.logsContainer.colors;

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.spec.ts
index 67d9423..3b210a3 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.spec.ts
@@ -28,9 +28,12 @@ import {ComponentsService, components} from '@app/services/storage/components.se
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
 import {ComponentActionsService} from '@app/services/component-actions.service';
@@ -64,6 +67,7 @@ describe('MenuButtonComponent', () => {
           hosts,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -80,6 +84,7 @@ describe('MenuButtonComponent', () => {
         HostsService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
index 0c323f7..05420ff 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
@@ -26,8 +26,11 @@ import {TranslationModules} from '@app/test-config.spec';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
 import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
@@ -75,6 +78,7 @@ describe('ServiceLogsTableComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           serviceLogsTruncated,
@@ -96,6 +100,7 @@ describe('ServiceLogsTableComponent', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         ServiceLogsTruncatedService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.html
index 720f55e..be68d08 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.html
@@ -27,7 +27,7 @@
   </div>
 </header>
 <div #graphContainer></div>
-<footer *ngIf="isTimeGraph && (firstDateTick || lastDateTick)">
+<footer *ngIf="firstDateTick || lastDateTick">
   <div *ngIf="firstDateTick">{{firstDateTick | amTz: timeZone | amDateFormat: historyStartEndTimeFormat}}</div>
   <div *ngIf="lastDateTick">{{lastDateTick | amTz: timeZone | amDateFormat: historyStartEndTimeFormat}}</div>
 </footer>

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less
index 364517c..e085d90 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less
@@ -19,43 +19,7 @@
 @import '../mixins';
 
 :host {
-  position: relative;
-  background: #ECECEC; // TODO add style according to actual design
-
-  /deep/ .axis {
-    .tick {
-      cursor: default;
-    }
-  }
-
-  /deep/ svg {
-    cursor: crosshair;
-  }
-
   header {
     padding: @graph-padding;
   }
-
-  .time-gap {
-    color: @base-font-color;
-    font-size: 1.2rem;
-    text-align: center;
-  }
-
-  footer {
-    .default-flex;
-    font-size: 1.2rem;
-    color: @base-font-color;
-    padding: 0 1em .5em;
-  }
-
-  /deep/ rect.drag-area {
-    fill: #fff;
-  }
-
-  /deep/ rect.unselected-drag-area {
-    fill: darken(@main-background-color, 10%);
-    opacity: .6;
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.spec.ts
index 09cd5d8..b429cdc 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.spec.ts
@@ -107,7 +107,6 @@ describe('TimeHistogramComponent', () => {
       ],
       providers: [
         AppSettingsService,
-        ServiceLogsHistogramDataService,
         LogsContainerService,
         {
           provide: HttpClientService,