Skip to content
This repository was archived by the owner on Jan 8, 2019. It is now read-only.

Commit f746079

Browse files
committed
Merge branch 'master' of github.com:Graylog2/graylog2-web-interface
2 parents 0471ca7 + 2c94bbd commit f746079

File tree

15 files changed

+170
-45
lines changed

15 files changed

+170
-45
lines changed

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,36 @@
11
[![Build Status](https://travis-ci.org/Graylog2/graylog2-web-interface.png)](https://travis-ci.org/Graylog2/graylog2-web-interface)
2+
3+
## Development Setup
4+
5+
* Make sure Java 7 and Maven is installed
6+
* Install Play version 2.2.2 and ensure the `play` binary is in `PATH`
7+
* Clone the git repository and initialize the submodules
8+
9+
```
10+
$ git submodule init
11+
Submodule 'modules/graylog2-rest-client' (git://github.com/Graylog2/graylog2-rest-client.git) registered for path 'modules/graylog2-rest-client'
12+
13+
$ git submodule update
14+
Cloning into 'modules/graylog2-rest-client'...
15+
remote: Counting objects: 1227, done.
16+
remote: Compressing objects: 100% (16/16), done.
17+
remote: Total 1227 (delta 3), reused 0 (delta 0)
18+
Receiving objects: 100% (1227/1227), 234.23 KiB | 303.00 KiB/s, done.
19+
Resolving deltas: 100% (671/671), done.
20+
Checking connectivity... done.
21+
Submodule path 'modules/graylog2-rest-client': checked out 'dbd45912656eaf0b8794d7fd6133eeede37f8408'
22+
```
23+
24+
* Run the server
25+
26+
```
27+
$ play run
28+
...
29+
30+
--- (Running the application from SBT, auto-reloading is enabled) ---
31+
32+
[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
33+
34+
(Server started, use Ctrl+D to stop and go back to the console...)
35+
36+
```

app/assets/javascripts/analyzers/analyzers/fieldcharts.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,11 @@ $(document).ready(function() {
147147
width: $("#main-content").width()-12,
148148
height: 175,
149149
interpolation: opts.interpolation,
150-
renderer: opts.renderer,
151-
150+
renderer: rickshawHelper.getRenderer(opts.renderer),
151+
resolution: data.interval,
152152
series: [ {
153153
name: "value",
154-
data: data.values,
154+
data: rickshawHelper.correctDataBoundaries(data.values, data.from, data.to, data.interval),
155155
color: '#26ADE4',
156156
gl2_query: opts.query,
157157
valuetype: opts.valuetype,
@@ -174,7 +174,8 @@ $(document).ready(function() {
174174
new Rickshaw.Graph.HoverDetail({
175175
graph: graph,
176176
formatter: function(series, x, y) {
177-
var date = '<span class="date">' + new Date(x * 1000).toString() + '</span>';
177+
var dateMoment = moment(new Date(x * 1000 )).zone(gl2UserTimeZoneOffset);
178+
var date = '<span class="date">' + dateMoment.format('ddd MMM DD YYYY HH:mm:ss ZZ') + '</span>';
178179
var swatch = '<span class="detail_swatch" style="background-color: ' + series.color + '"></span>';
179180
var content = swatch + '[' + series.valuetype + '] ' + series.field + ': ' + numeral(y).format('0.[000]') + '<br>' + date;
180181
return content;

app/assets/javascripts/dashboards/widgets/field_chart.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,16 @@ function updateWidget_field_chart(widget, data) {
5555
}
5656

5757
if(series.length == 0) {
58+
graphElem.html("<div class=\"not-available\">N/A</div>");
5859
return;
5960
}
6061

62+
var resolution = graphElem.data("config-interval");
63+
64+
if (data.time_range != null) {
65+
rickshawHelper.correctDataBoundaries(series, data.time_range.from, data.time_range.to, resolution);
66+
}
67+
6168
// we need to replace the entire element that rickshaw touches, otherwise
6269
// it will leak event listeners and tons of DOM elements
6370
graphElem.html('<div class="graph_chart">');
@@ -69,7 +76,8 @@ function updateWidget_field_chart(widget, data) {
6976
width: 800,
7077
height: 70,
7178
interpolation: graphElem.attr("data-config-interpolation"),
72-
renderer: renderer,
79+
renderer: rickshawHelper.getRenderer(renderer),
80+
resolution: resolution,
7381
series: [ {
7482
name: "value",
7583
data: series,
@@ -93,7 +101,8 @@ function updateWidget_field_chart(widget, data) {
93101
graph: graph,
94102
formatter: function(series, x, y) {
95103
field = graphElem.attr("data-config-field");
96-
var date = '<span class="date">' + new Date(x * 1000).toString() + '</span>';
104+
var dateMoment = moment(new Date(x * 1000 )).zone(gl2UserTimeZoneOffset);
105+
var date = '<span class="date">' + dateMoment.format('ddd MMM DD YYYY HH:mm:ss ZZ') + '</span>';
97106
var swatch = '<span class="detail_swatch"></span>';
98107
var content = '[' + graphElem.attr("data-config-valuetype") + '] ' + field + ': ' + numeral(y).format('0.[000]') + '<br>' + date;
99108
return content;

app/assets/javascripts/moment-helper.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,12 @@ momentHelper = {
6767
userDate.millisecond(parsedDate.millisecond());
6868

6969
return userDate;
70+
},
71+
72+
getFormattedResolution: function(resolution) {
73+
if (resolution == "week") {
74+
return "isoWeek"; // Weeks should start on Monday :)
75+
}
76+
return resolution;
7077
}
7178
};

app/assets/javascripts/result-histogram.js

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,11 @@
1-
// We need to override Rickshaw _frequentInterval detection for bar charts due to this issue:
2-
// https://github.com/shutterstock/rickshaw/issues/461
3-
var ResultHistogramRenderer = Rickshaw.Class.create(Rickshaw.Graph.Renderer.Bar, {
4-
_frequentInterval: function(data) {
5-
var selectedResolution = $(".date-histogram-res-selector.selected-resolution").data("resolution");
6-
var resolutionDuration = moment.duration(1, selectedResolution);
7-
return { count: 1, magnitude: resolutionDuration.asSeconds() };
8-
}
9-
});
10-
111
resultHistogram = {
122
_histogram: [],
133

14-
// Show the whole search time range, even if no data is available
154
_correctDataBoundaries: function(data) {
165
var resultGraphElement = $("#result-graph");
17-
var fromMoment = moment.utc(resultGraphElement.data("from"));
18-
var toMoment = moment.utc(resultGraphElement.data("to"));
19-
206
var selectedResolution = $(".date-histogram-res-selector.selected-resolution").data("resolution");
21-
if (selectedResolution == "week") {
22-
selectedResolution = "isoWeek"; // Weeks should start on Monday :)
23-
}
24-
var fromFormatted = fromMoment.startOf(selectedResolution).unix();
25-
var toFormatted = toMoment.startOf(selectedResolution).unix();
267

27-
if (fromFormatted != data[0].x) {
28-
data.unshift({"x": fromFormatted, "y": 0});
29-
}
30-
if ((toFormatted != data[data.length-1].x) && (toFormatted != fromFormatted)) {
31-
data.push({"x": toFormatted, "y": 0});
32-
}
33-
34-
return data;
8+
return rickshawHelper.correctDataBoundaries(data, resultGraphElement.data("from"), resultGraphElement.data("to"), selectedResolution);
359
},
3610

3711
setData: function(data) {
@@ -48,12 +22,14 @@ resultHistogram = {
4822
$("#result-graph-timeline" ).html("");
4923

5024
var graphWidth = resultGraphElement.width();
25+
var selectedResolution = $(".date-histogram-res-selector.selected-resolution").data("resolution");
5126

5227
var resultGraph = new Rickshaw.Graph( {
5328
element: resultGraphElement.get(0),
5429
width: graphWidth,
5530
height: 175,
56-
renderer: ResultHistogramRenderer,
31+
renderer: rickshawHelper.getRenderer("bar"),
32+
resolution: selectedResolution,
5733
series: [ {
5834
name: "Messages",
5935
data: this._histogram,
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// We need to override Rickshaw _frequentInterval detection for bar charts due to this issue:
2+
// https://github.com/shutterstock/rickshaw/issues/461
3+
SmartResolutionBarRenderer = Rickshaw.Class.create(Rickshaw.Graph.Renderer.Bar, {
4+
defaults: function($super) {
5+
6+
var defaults = Rickshaw.extend( $super(), {
7+
gapSize: 0.05,
8+
unstack: false,
9+
resolution: 'minute'
10+
} );
11+
12+
delete defaults.tension;
13+
return defaults;
14+
},
15+
16+
initialize: function($super, args) {
17+
args = args || {};
18+
this.resolution = args.resolution || this.resolution;
19+
$super(args);
20+
},
21+
22+
_frequentInterval: function(data) {
23+
var resolutionDuration = moment.duration(1, this.resolution);
24+
return { count: 100, magnitude: resolutionDuration.asSeconds() };
25+
}
26+
});
27+
28+
rickshawHelper = {
29+
getRenderer: function (renderer) {
30+
if (renderer == "bar") {
31+
return SmartResolutionBarRenderer;
32+
}
33+
return renderer;
34+
},
35+
36+
// Add two points before the actual data if needed to ensure charts look
37+
// good while we show the whole time range.
38+
_correctDataLeftBoundary: function (data, boundary, resolution) {
39+
var firstDataPoint = data[0];
40+
if (boundary < firstDataPoint.x) {
41+
var previousPointInTime = moment.unix(firstDataPoint.x).subtract(1, resolution).unix();
42+
if (previousPointInTime > boundary) {
43+
data.unshift({"x": previousPointInTime, "y": 0});
44+
}
45+
46+
data.unshift({"x": boundary, "y": 0});
47+
}
48+
},
49+
50+
// Add two points after the actual data if needed to ensure charts look
51+
// good while we show the whole time range.
52+
_correctDataRightBoundary: function (data, boundary, resolution) {
53+
var lastDataPoint = data[data.length-1];
54+
if (boundary > lastDataPoint.x) {
55+
var nextPointInTime = moment.unix(lastDataPoint.x).add(1, resolution).unix();
56+
if (nextPointInTime < boundary) {
57+
data.push({"x": nextPointInTime, "y": 0});
58+
}
59+
data.push({"x": boundary, "y": 0});
60+
}
61+
},
62+
63+
// Show the whole search time range on charts, even if no data is available.
64+
correctDataBoundaries: function (data, from, to, resolution) {
65+
var fromMoment = moment.utc(from);
66+
var toMoment = moment.utc(to);
67+
68+
var formattedResolution = momentHelper.getFormattedResolution(resolution);
69+
var fromFormatted = fromMoment.startOf(formattedResolution).unix();
70+
var toFormatted = toMoment.startOf(formattedResolution).unix();
71+
72+
// Correct left boundary
73+
this._correctDataLeftBoundary(data, fromFormatted, resolution);
74+
75+
if (toFormatted != fromFormatted) {
76+
this._correctDataRightBoundary(data, toFormatted, resolution);
77+
}
78+
79+
return data;
80+
}
81+
};

app/assets/stylesheets/main.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1977,7 +1977,7 @@ hr.search-result-head-separator {
19771977
color: #ebebeb;
19781978
}
19791979

1980-
.dashboard .widget .search_result_chart .not-available {
1980+
.dashboard .widget .not-available {
19811981
line-height: 70px !important;
19821982
text-align: center;
19831983
font-size: 70px;

app/controllers/api/DashboardsApiController.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.graylog2.restclient.lib.timeranges.TimeRange;
3434
import org.graylog2.restclient.models.User;
3535
import org.graylog2.restclient.models.api.requests.dashboards.UserSetWidgetPositionsRequest;
36+
import org.graylog2.restclient.models.api.responses.dashboards.DashboardWidgetValueResponse;
3637
import org.graylog2.restclient.models.dashboards.Dashboard;
3738
import org.graylog2.restclient.models.dashboards.DashboardService;
3839
import org.graylog2.restclient.models.NodeService;
@@ -135,11 +136,13 @@ public Result widgetValue(String dashboardId, String widgetId) {
135136
try {
136137
Dashboard dashboard = dashboardService.get(dashboardId);
137138
DashboardWidget widget = dashboard.getWidget(widgetId);
139+
DashboardWidgetValueResponse widgetValue = widget.getValue(api());
138140

139141
Map<String, Object> result = Maps.newHashMap();
140-
result.put("result", widget.getValue(api()).result);
141-
result.put("took_ms", widget.getValue(api()).tookMs);
142-
result.put("calculated_at", widget.getValue(api()).calculatedAt);
142+
result.put("result", widgetValue.result);
143+
result.put("took_ms", widgetValue.tookMs);
144+
result.put("calculated_at", widgetValue.calculatedAt);
145+
result.put("time_range", widgetValue.computationTimeRange);
143146

144147
return ok(new Gson().toJson(result)).as("application/json");
145148
} catch (APIException e) {

app/controllers/api/SearchApiController.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,12 @@ public Result fieldHistogram(String q, String field, String rangeType, int relat
165165
FieldHistogramResponse histo = search.fieldHistogram(field, interval);
166166

167167
Map<String, Object> result = Maps.newHashMap();
168+
AbsoluteRange boundaries = histo.getHistogramBoundaries();
168169
result.put("time", histo.time);
169170
result.put("interval", histo.interval);
170171
result.put("values", histo.getFormattedResults(valueType));
172+
result.put("from", boundaries.getFrom());
173+
result.put("to", boundaries.getTo());
171174

172175
return ok(new Gson().toJson(result)).as("application/json");
173176
} catch (IOException e) {

app/views/dashboards/widgets/field_chart.scala.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
data-config-interpolation="@widget.getConfig.get("interpolation")"
88
data-config-renderer="@widget.getConfig.get("renderer")"
99
data-config-valuetype="@widget.getConfig.get("valuetype")"
10+
data-config-interval="@widget.getConfig.get("interval")"
1011
>
1112
<div class="reloading">
1213
<i class="icon icon-refresh"></i>

0 commit comments

Comments
 (0)