make the drop down for "combine with" dynamic
This commit is contained in:
@@ -2,6 +2,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NgModule, enableProdMode } from '@angular/core';
|
import { NgModule, enableProdMode } from '@angular/core';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
@@ -26,6 +27,7 @@ import { YAxisRangeComponent } from './y-axis-range/y-axis-range.component';
|
|||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
MatSelectModule,MatFormFieldModule, MatInputModule,
|
MatSelectModule,MatFormFieldModule, MatInputModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
HttpClientModule
|
HttpClientModule
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ This page describes how to use this tool.
|
|||||||
|
|
||||||
<h2>Why not use one of the existing monitoring tools?</h2>
|
<h2>Why not use one of the existing monitoring tools?</h2>
|
||||||
<p>
|
<p>
|
||||||
There are many monitoring tools out there.
|
There are many tools out there that do monitoring in one way or the other. Here are a few:
|
||||||
<a href="https://newrelic.com" target="_blank" rel="nofollow" class="external-link">New Relic</a>,
|
<a href="https://newrelic.com" target="_blank" rel="nofollow" class="external-link">New Relic</a>,
|
||||||
<a href="https://www.splunk.com" target="_blank" rel="nofollow" class="external-link">Splunk</a>,
|
<a href="https://www.splunk.com" target="_blank" rel="nofollow" class="external-link">Splunk</a>,
|
||||||
<a href="https://www.elastic.co/products/kibana" target="_blank" rel="nofollow" class="external-link">Kibana</a> (<a href="https://www.elastic.co/products/elastic-stack" target="_blank" rel="nofollow" class="external-link">ELK</a>),
|
<a href="https://www.elastic.co/products/kibana" target="_blank" rel="nofollow" class="external-link">Kibana</a> (<a href="https://www.elastic.co/products/elastic-stack" target="_blank" rel="nofollow" class="external-link">ELK</a>),
|
||||||
@@ -28,14 +28,16 @@ There are many monitoring tools out there.
|
|||||||
+ <a href="https://www.influxdata.com/time-series-platform/chronograf/" target="_blank" rel="nofollow" class="external-link">Chronograf</a>,
|
+ <a href="https://www.influxdata.com/time-series-platform/chronograf/" target="_blank" rel="nofollow" class="external-link">Chronograf</a>,
|
||||||
<a href="http://opentsdb.net/" target="_blank" rel="nofollow" class="external-link">OpenTSDB</a>,
|
<a href="http://opentsdb.net/" target="_blank" rel="nofollow" class="external-link">OpenTSDB</a>,
|
||||||
<a href="https://www.nagios.org/" target="_blank" rel="nofollow" class="external-link">Nagios</a>/<a href="https://icinga.com/" target="_blank" rel="nofollow" class="external-link">Icinga</a>,
|
<a href="https://www.nagios.org/" target="_blank" rel="nofollow" class="external-link">Nagios</a>/<a href="https://icinga.com/" target="_blank" rel="nofollow" class="external-link">Icinga</a>,
|
||||||
Heka,
|
<a href="https://sentry.io/" target="_blank" rel="nofollow" class="external-link">Sentry</a>,
|
||||||
Bosun,
|
<a href="https://github.com/mozilla-services/heka" target="_blank" rel="nofollow" class="external-link">Heka</a>,
|
||||||
Wavefront,
|
<a href="https://bosun.org/" target="_blank" rel="nofollow" class="external-link">Bosun</a>,
|
||||||
Dropwizard,
|
<a href="https://www.wavefront.com/" target="_blank" rel="nofollow" class="external-link">Wavefront</a>,
|
||||||
Druid.io,
|
<a href="https://www.instana.com/supported-technologies/dropwizard/" target="_blank" rel="nofollow" class="external-link">Dropwizard</a>,
|
||||||
Bleemo,
|
<a href="https://druid.apache.org/" target="_blank" rel="nofollow" class="external-link">Druid.io</a>,
|
||||||
Site24x7,
|
<a href="https://bleemeo.com/" target="_blank" rel="nofollow" class="external-link">Bleemo</a>,
|
||||||
Sitescope,
|
<a href="https://www.site24x7.com/" target="_blank" rel="nofollow" class="external-link">Site24x7</a>,
|
||||||
|
<a href="https://www.datadoghq.com/" target="_blank" rel="nofollow" class="external-link">Datadog</a>,
|
||||||
|
<a href="https://www.microfocus.com/en-us/products/sitescope-application-monitoring/overview" target="_blank" rel="nofollow" class="external-link">Sitescope</a>,
|
||||||
and many more. None of them provides the visualizations we had in mind. We wanted to plot each value of the time series data individually, so that we can identify the
|
and many more. None of them provides the visualizations we had in mind. We wanted to plot each value of the time series data individually, so that we can identify the
|
||||||
response times of a single request. But tools like Splunk, Kibana, Chronograf or Grafana only plot aggregated data (average, min/max, percentiles).
|
response times of a single request. But tools like Splunk, Kibana, Chronograf or Grafana only plot aggregated data (average, min/max, percentiles).
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -14,18 +14,23 @@ export class PlotService {
|
|||||||
|
|
||||||
constructor(private http: HttpClient) {
|
constructor(private http: HttpClient) {
|
||||||
this.plotTypes = new Array<PlotType>();
|
this.plotTypes = new Array<PlotType>();
|
||||||
this.plotTypes.push(new PlotType("Scatter", "scatter-chart2", true));
|
this.plotTypes.push(new PlotType(
|
||||||
this.plotTypes.push(new PlotType("Heatmap", "heatmap", false));
|
"Scatter",
|
||||||
this.plotTypes.push(new PlotType("Contour", "contour-chart", false));
|
"scatter-chart2",
|
||||||
this.plotTypes.push(new PlotType("Cumulative Distribution", "cumulative-distribution-chart", true));
|
true,
|
||||||
this.plotTypes.push(new PlotType("Histogram", "histogram", false));
|
DataType.Time,
|
||||||
this.plotTypes.push(new PlotType("Ridgelines", "ridgelines", false));
|
DataType.Duration));
|
||||||
this.plotTypes.push(new PlotType("Quantile-Quantile", "quantile-quantile", false));
|
this.plotTypes.push(new PlotType("Heatmap", "heatmap", false, DataType.Other, DataType.Other));
|
||||||
this.plotTypes.push(new PlotType("Parallel Requests", "parallel-requests-chart", true));
|
this.plotTypes.push(new PlotType("Contour", "contour-chart", false, DataType.Time, DataType.Duration));
|
||||||
this.plotTypes.push(new PlotType("Violin", "violin-chart", false));
|
this.plotTypes.push(new PlotType("Cumulative Distribution", "cumulative-distribution-chart", true, DataType.Percent, DataType.Duration));
|
||||||
this.plotTypes.push(new PlotType("Strip", "strip-chart", false));
|
this.plotTypes.push(new PlotType("Histogram", "histogram", false, DataType.Group, DataType.Duration));
|
||||||
this.plotTypes.push(new PlotType("Pie", "pie-chart", false));
|
this.plotTypes.push(new PlotType("Ridgelines", "ridgelines", false, DataType.Other, DataType.Other));
|
||||||
this.plotTypes.push(new PlotType("Bar", "bar-chart", false));
|
this.plotTypes.push(new PlotType("Quantile-Quantile", "quantile-quantile", false, DataType.Other, DataType.Other));
|
||||||
|
this.plotTypes.push(new PlotType("Parallel Requests", "parallel-requests-chart", true, DataType.Time, DataType.Count));
|
||||||
|
this.plotTypes.push(new PlotType("Violin", "violin-chart", false, DataType.Group, DataType.Duration));
|
||||||
|
this.plotTypes.push(new PlotType("Strip", "strip-chart", false, DataType.Group, DataType.Duration));
|
||||||
|
this.plotTypes.push(new PlotType("Pie", "pie-chart", false, DataType.Other, DataType.Other));
|
||||||
|
this.plotTypes.push(new PlotType("Bar", "bar-chart", false, DataType.Other, DataType.Other));
|
||||||
|
|
||||||
this.tagFields = new Array<TagField>();
|
this.tagFields = new Array<TagField>();
|
||||||
|
|
||||||
@@ -57,11 +62,34 @@ export class PlotType {
|
|||||||
name: string;
|
name: string;
|
||||||
icon: string
|
icon: string
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
xAxis: DataType;
|
||||||
|
yAxis: DataType;
|
||||||
|
|
||||||
constructor(name: string, icon: string, active: boolean) {
|
constructor(name: string, icon: string, active: boolean, xAxis: DataType, yAxis: DataType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.active = active;
|
this.active = active;
|
||||||
|
this.xAxis = xAxis;
|
||||||
|
this.yAxis = yAxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
compatible(other: PlotType) : boolean {
|
||||||
|
|
||||||
|
const xEqual = this.xAxis === other.xAxis;
|
||||||
|
const yEqual = this.yAxis === other.yAxis;
|
||||||
|
const anyIsOther = this.xAxis === DataType.Other
|
||||||
|
|| this.yAxis === DataType.Other
|
||||||
|
|| other.xAxis === DataType.Other
|
||||||
|
|| other.yAxis === DataType.Other;
|
||||||
|
|
||||||
|
var result = xEqual || yEqual;
|
||||||
|
|
||||||
|
// if either dimension is Other, then this plot is not compatible with any other plot
|
||||||
|
result = result && !anyIsOther;
|
||||||
|
|
||||||
|
// is not the same
|
||||||
|
result = result && this.name != other.name;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,4 +101,13 @@ export class TagField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DataType {
|
||||||
|
Time,
|
||||||
|
Duration,
|
||||||
|
Percent,
|
||||||
|
Count,
|
||||||
|
Group,
|
||||||
|
Metric,
|
||||||
|
Other
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,19 +7,21 @@
|
|||||||
<input matInput placeholder="Query" value="{{query}}" />
|
<input matInput placeholder="Query" value="{{query}}" />
|
||||||
</div>
|
</div>
|
||||||
<div id="filters">
|
<div id="filters">
|
||||||
<button mat-button>
|
<button mat-button (click)="plot()">
|
||||||
<img src="assets/img/scatter-chart2.svg" class="icon-inline" aria-hidden="true" title="create plot" />
|
<img src="assets/img/scatter-chart2.svg" class="icon-inline" aria-hidden="true" title="create plot" />
|
||||||
Plot
|
Plot
|
||||||
</button>
|
</button>
|
||||||
<button mat-button>
|
<!--
|
||||||
|
<button mat-button (click)="gallery()">
|
||||||
<img src="assets/img/four-squares-line.svg" class="icon-inline" aria-hidden="true" title="Create Gallery (only active if 'Split' is set)" />
|
<img src="assets/img/four-squares-line.svg" class="icon-inline" aria-hidden="true" title="Create Gallery (only active if 'Split' is set)" />
|
||||||
Gallery
|
Gallery
|
||||||
</button>
|
</button>
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Type:</mat-label>
|
<mat-label>Type:</mat-label>
|
||||||
<mat-select [(value)]="selectedPlotType">
|
<mat-select [formControl]="selectedPlotType">
|
||||||
<mat-option *ngFor="let plotType of plotTypes" [value]="plotType.name">
|
<mat-option *ngFor="let plotType of plotTypes" [value]="plotType.name">
|
||||||
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
|
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { PlotService, PlotType } from '../plot.service';
|
import { PlotService, PlotType } from '../plot.service';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pdb-visualization-page',
|
selector: 'pdb-visualization-page',
|
||||||
@@ -8,10 +11,12 @@ import { PlotService, PlotType } from '../plot.service';
|
|||||||
})
|
})
|
||||||
export class VisualizationPageComponent implements OnInit {
|
export class VisualizationPageComponent implements OnInit {
|
||||||
|
|
||||||
selectedPlotType: string;
|
availablePlotTypes = {};
|
||||||
|
|
||||||
|
selectedPlotType = new FormControl('');
|
||||||
plotTypes: Array<any>;
|
plotTypes: Array<any>;
|
||||||
|
|
||||||
selectedCombinePlotType: string;
|
selectedCombinePlotType = new FormControl('');
|
||||||
combinePlotTypes: Array<any>;
|
combinePlotTypes: Array<any>;
|
||||||
|
|
||||||
tagFields: Array<any>;
|
tagFields: Array<any>;
|
||||||
@@ -23,21 +28,42 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
|
|
||||||
query: string;
|
query: string;
|
||||||
|
|
||||||
constructor(private plotService: PlotService) {
|
constructor(private plotService: PlotService, private http: HttpClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
const that = this;
|
||||||
this.query = "pod=*";
|
this.query = "pod=*";
|
||||||
this.plotTypes = this.plotService.getPlotTypes();
|
this.plotTypes = this.plotService.getPlotTypes();
|
||||||
this.selectedPlotType = this.plotTypes[0].name;
|
this.selectedPlotType.setValue(this.plotTypes[0].name);
|
||||||
|
|
||||||
this.combinePlotTypes = this.plotTypes;
|
this.plotTypes.forEach(pt => this.availablePlotTypes[pt.name] = pt);
|
||||||
|
|
||||||
|
this.combinePlotTypes = this.getCombinablePlotTypes(this.selectedPlotType.value);
|
||||||
|
|
||||||
this.tagFields = this.plotService.getTagFields();
|
this.tagFields = this.plotService.getTagFields();
|
||||||
this.yAxis = "log";
|
this.yAxis = "log";
|
||||||
this.yAxisUnit = "MINUTES";
|
this.yAxisUnit = "MINUTES";
|
||||||
this.minYValue = 0;
|
this.minYValue = 0;
|
||||||
this.maxYValue = 120;
|
this.maxYValue = 120;
|
||||||
|
|
||||||
|
|
||||||
|
this.selectedPlotType.valueChanges.subscribe(function(selectedMainPlotType){
|
||||||
|
that.combinePlotTypes = that.getCombinablePlotTypes(selectedMainPlotType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getCombinablePlotTypes(selectedMainPlotType) : Array<any>{
|
||||||
|
// get compatible plot types
|
||||||
|
const mainPlotType = this.availablePlotTypes[selectedMainPlotType];
|
||||||
|
|
||||||
|
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType));
|
||||||
|
console.log(compatiblePlotTypes);
|
||||||
|
return compatiblePlotTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
plot(){
|
||||||
|
console.log("plot clicked");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-small {
|
.icon-small {
|
||||||
max-width: 1.5em;
|
width: 1.5em;
|
||||||
max-height: 1.5em;
|
height: 1.5em;
|
||||||
margin: 0.2em;
|
margin: 0.2em;
|
||||||
}
|
}
|
||||||
.icon-small:hover {
|
.icon-small:hover {
|
||||||
|
|||||||
Reference in New Issue
Block a user