Permalink
Browse files

Merge branch 'develop' into graphiteReportNotInMutex

  • Loading branch information...
sburnicki committed Dec 3, 2018
2 parents e980dd2 + 6f0e862 commit 159e9bdcd1cef492335e06830646bb67cc068569
@@ -33,7 +33,6 @@ environments:
username: '{{ default .Env.MYSQL_USER "osm" }}'
password: '{{ default .Env.MYSQL_PASSWORD "osm123" }}'
dbCreate: "managed by liquibase"
driverClassName: "com.mysql.jdbc.Driver"
pooled: true
properties:
minEvictableIdleTimeMillis: 60000
@@ -38,8 +38,8 @@ <h2>{{ 'frontend.de.iteratec.osm.landing.healthIssues' | translate }}</h2>
<p class="applicationName">{{ application }} </p>
<ul class="clickable-list">
<li *ngFor="let failingJob of failingJobs[application]"
[class.error]="failingJob.percentageFailLast5 >= 20"
[class.warning]="failingJob.percentageFailLast5 < 20">
[class.error]="failingJob.percentageFailLast5 > 20"
[class.warning]="failingJob.percentageFailLast5 <= 20">
<a href="/jobResult/listFailed?jobId={{failingJob.job_id}}">
<aside class="percentage-aside">
<p class="percentage percentage-big">{{ failingJob.percentageFailLast5 }}%</p>
@@ -95,6 +95,6 @@
}
li.warning:hover {
background: darken($color-error-light, 5);
background: darken($color-warning-light, 5);
}
}
@@ -18,13 +18,15 @@
package de.iteratec.osm.result
import de.iteratec.osm.ConfigService
import de.iteratec.osm.measurement.schedule.JobGroup
import de.iteratec.osm.measurement.schedule.JobGroupService
import de.iteratec.osm.p13n.CustomDashboardService
import de.iteratec.osm.report.UserspecificDashboardBase
import de.iteratec.osm.report.UserspecificDashboardService
import de.iteratec.osm.report.UserspecificEventResultDashboard
import de.iteratec.osm.report.chart.*
import de.iteratec.osm.report.chart.CsiAggregationInterval
import de.iteratec.osm.report.chart.EventService
import de.iteratec.osm.report.chart.OsmChartAxis
import de.iteratec.osm.report.chart.OsmRickshawChart
import de.iteratec.osm.util.AnnotationUtil
import de.iteratec.osm.util.ControllerUtils
import de.iteratec.osm.util.I18nService
@@ -34,13 +36,7 @@ import grails.web.mapping.LinkGenerator
import org.grails.web.json.JSONObject
import org.joda.time.DateTime
import org.joda.time.Interval
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter
import org.joda.time.format.ISODateTimeFormat
import org.springframework.dao.DataIntegrityViolationException
import org.supercsv.encoder.DefaultCsvEncoder
import org.supercsv.io.CsvListWriter
import org.supercsv.prefs.CsvPreference
class EventResultDashboardController {
@@ -358,183 +354,6 @@ class EventResultDashboardController {
modelToRender.put('i18n', i18n as JSON)
}
/**
* <p>
* WARNING: This method is a duplicate of CsiDashboardController's
* version.
* </p>
*
* <p>
* Performs a redirect with HTTP status code 303 (see other).
* </p>
*
* <p>
* Using this redirect enforces the client to perform the next request
* with the HTTP method GET.
* This method SHOULD be used in a redirect-after-post situation.
* </p>
*
* <p>
* After using this method, the response should be considered to be
* committed and should not be written to.
* </p>
*
* @param actionNameToRedirectTo
* The Name of the action to redirect to;
* not <code>null</code>.
* @param urlParams
* The parameters to add as query string;
* not <code>null</code>.
*
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.3.4"
* >http://tools.ietf.org/html/rfc2616#section-10.3.4</a>
*
* @since copy since: IT-188
*/
private void redirectWith303(String actionNameToRedirectTo, Map urlParams) {
// There is a missing feature to do this:
// http://jira.grails.org/browse/GRAILS-8829
// Workaround based on:
// http://fillinginthegaps.wordpress.com/2008/12/26/grails-301-moved-permanently-redirect/
Map paramsWithoutGrailsActionNameOfOldAction = urlParams.findAll({ Map.Entry m -> !m.getKey().toString().startsWith('_action') });
String uri = grailsLinkGenerator.link(action: actionNameToRedirectTo, params: paramsWithoutGrailsActionNameOfOldAction)
response.setStatus(303)
response.setHeader("Location", uri)
render(status: 303)
}
/**
* <p>
* WARNING: This constant is a duplicate of CsiDashboardController's
* version.
* </p>
*
* The {@link DateTimeFormat} used for CSV export and table view.
* @since copy since: IT-188
*/
private static
final DateTimeFormatter CSV_TABLE_DATE_TIME_FORMAT = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm:ss");
/**
* <p>
* WARNING: This method is a duplicate of CsiDashboardController's
* version.
* </p>
*
* <p>
* Converts the specified result values in the source map to a CSV
* corresponding to RFC 4180 written to specified {@link Writer}.
* </p>
*
* @param source
* The result values a List of OsmChartGraph,
* not <code>null</code>.
* @param target
* The {@link Writer} to write CSV to,
* not <code>null</code>.
* @param localeForNumberFormat
* The locale used to format the numeric values,
* not <code>null</code>.
*
* @throws IOException if write on {@code target} failed.
* @since copy since: IT-188
*/
private
static void writeCSV(List<OsmChartGraph> source, Writer target) throws IOException {
// Sort graph points by time
Map pointsByGraphByTime = [:].withDefault { [:] }
for (OsmChartGraph eachCSIValueEntry : source) {
for (OsmChartPoint eachPoint : eachCSIValueEntry.getPoints()) {
pointsByGraphByTime[eachPoint.time][eachCSIValueEntry.getLabel()] = eachPoint
}
}
CsvListWriter csvWriter = new CsvListWriter(
target,
new CsvPreference.Builder(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE).useEncoder(new DefaultCsvEncoder()).build()
)
// Create CSV header:
List<String> csvHeader = new LinkedList<String>();
csvHeader.add('Zeitpunkt'); // TODO i18n?
List<String> graphLabelsInOrderOfHeader = new LinkedList<String>();
for (OsmChartGraph eachGraph : source) {
csvHeader.add(eachGraph.getLabel());
graphLabelsInOrderOfHeader.add(eachGraph.getLabel());
}
csvWriter.writeHeader(csvHeader.toArray(new String[csvHeader.size()]));
for (Map.Entry<Long, TreeMap<String, OsmChartPoint>> eachPointByGraphOfTime : pointsByGraphByTime) {
List<String> row = new LinkedList<String>();
DateTime time = new DateTime(eachPointByGraphOfTime.getKey());
row.add(CSV_TABLE_DATE_TIME_FORMAT.print(time));
for (String eachGraphLabel : graphLabelsInOrderOfHeader) {
OsmChartPoint point = eachPointByGraphOfTime.getValue().get(eachGraphLabel);
if (point != null) {
row.add(point.csiAggregation?.round(2));
} else {
row.add("");
}
}
csvWriter.writeRow(row);
}
csvWriter.flush();
}
/**
* <p>
* Creates a CSV based on the selection passed as {@link EventResultDashboardShowAllCommand}.
* </p>
*
* @param cmd
* The command with the users selections;
* not <code>null</code>.
* @return nothing , immediately renders a CSV to response' output stream.
* @see <a href="http://tools.ietf.org/html/rfc4180">http://tools.ietf.org/html/rfc4180</a>
*/
public Map<String, Object> downloadCsv(EventResultDashboardShowAllCommand cmd) {
Map<String, Object> modelToRender = new HashMap<String, Object>();
if (request.queryString && cmd.validate()) {
cmd.copyRequestDataToViewModelMap(modelToRender)
fillWithEventResultData(modelToRender, cmd)
} else {
redirectWith303('showAll', params)
return
}
String filename = ""
List<JobGroup> selectedJobGroups = JobGroup.findAllByIdInList(cmd.selectedFolder)
selectedJobGroups.each { jobGroup ->
filename += jobGroup.name + '_'
}
if (modelToRender['selectedInterval'] != -1) {
filename += modelToRender['selectedInterval'] + 'm_'
}
DateTimeFormatter dateFormatter = ISODateTimeFormat.date()
filename += dateFormatter.print(cmd.from) + '_to_' + dateFormatter.print(cmd.to) + '.csv'
response.setHeader('Content-disposition', 'attachment; filename=' + filename);
response.setContentType("text/csv;header=present;charset=UTF-8");
Writer responseWriter = new OutputStreamWriter(response.getOutputStream());
List<OsmChartGraph> csiValues = modelToRender['eventResultValues'];
writeCSV(csiValues, responseWriter);
response.getOutputStream().flush()
return null;
}
/**
* <p>
* Constructs the static view data of the {@link #showAll(EventResultDashboardShowAllCommand)}
@@ -377,7 +377,6 @@ class TabularResultPresentationController {
property('connectivityProfile.bandwidthUp')
property('connectivityProfile.latency')
property('connectivityProfile.packetLoss')
property('testDetailsWaterfallURL')
}
}
@@ -53,7 +53,6 @@ class EventResult implements CsiValue, RepresentableWptResult {
Long id
Date dateCreated
Date lastUpdated
URL testDetailsWaterfallURL
MeasuredEvent measuredEvent
JobGroup jobGroup
Page page
@@ -147,7 +146,6 @@ class EventResult implements CsiValue, RepresentableWptResult {
medianValue(nullable: false)
numberOfWptRun(nullable: false)
cachedView(nullable: false)
testDetailsWaterfallURL(nullable: true)
docCompleteIncomingBytes(nullable: true)
docCompleteRequests(nullable: true)
@@ -0,0 +1,5 @@
databaseChangeLog = {
changeSet(author: "fho", id: "20181130-1") {
dropColumn(columnName: "test_details_waterfallurl", tableName: "event_result")
}
}
@@ -71,4 +71,5 @@ databaseChangeLog = {
include file: '2018-11-15-v500-hero-element-times.groovy'
include file: '2018-11-16-v500-add-new-measurands.groovy'
include file: '2018-11-19-v500-add-missing-job-result-check.groovy'
include file: '2018-11-30-v500-remove-waterfall-url.groovy'
}
@@ -202,16 +202,14 @@ class EventResultPersisterService implements iResultListener {
if (!resultXml.isValidTestStep(viewResultsNodeOfThisRun)) {
return false
}
GString waterfallAnchor = getWaterfallAnchor(resultXml, event.name, testStepZeroBasedIndex + 1)
persistResult(
jobRun,
event,
cachedView,
runZeroBasedIndex + 1,
resultXml.isMedian(runZeroBasedIndex, cachedView, testStepZeroBasedIndex),
viewResultsNodeOfThisRun,
testStepZeroBasedIndex + 1,
waterfallAnchor
testStepZeroBasedIndex + 1
)
return true
}
@@ -227,10 +225,10 @@ class EventResultPersisterService implements iResultListener {
* @return
*/
protected EventResult persistResult(
JobResult jobRun, MeasuredEvent event, CachedView view, Integer run, Boolean median, GPathResult viewTag, testStepOneBasedIndex, GString waterfallAnchor) {
JobResult jobRun, MeasuredEvent event, CachedView view, Integer run, Boolean median, GPathResult viewTag, testStepOneBasedIndex) {
EventResult result = jobRun.findEventResult(event, view, run) ?: new EventResult()
return saveResult(result, jobRun, event, view, run, median, viewTag, testStepOneBasedIndex, waterfallAnchor)
return saveResult(result, jobRun, event, view, run, median, viewTag, testStepOneBasedIndex)
}
@@ -260,7 +258,7 @@ class EventResultPersisterService implements iResultListener {
* @return Saved {@link EventResult}.
*/
protected EventResult saveResult(EventResult result, JobResult jobRun, MeasuredEvent step, CachedView view, Integer run, Boolean median,
GPathResult viewTag, Integer testStepOneBasedIndex, GString waterfallAnchor) {
GPathResult viewTag, Integer testStepOneBasedIndex) {
log.debug("persisting result: jobRun=${jobRun.testId}, run=${run}, cachedView=${view}, medianValue=${median}")
@@ -280,7 +278,6 @@ class EventResultPersisterService implements iResultListener {
result.browser = jobRun.job.location.browser
result.location = jobRun.job.location
setAllMeasurands(viewTag, result)
setWaterfallUrl(result, jobRun, waterfallAnchor)
result.testAgent = jobRun.testAgent
setConnectivity(result, jobRun)
result.oneBasedStepIndexInJourney = testStepOneBasedIndex
@@ -310,29 +307,6 @@ class EventResultPersisterService implements iResultListener {
}
}
private void setWaterfallUrl(EventResult result, JobResult jobRun, GString waterfallAnchor) {
try {
result.testDetailsWaterfallURL = result.buildTestDetailsURL(jobRun, waterfallAnchor);
} catch (MalformedURLException mue) {
log.error("Failed to build test's detail url for result: ${result} and jobResult: ${jobRun}!", mue)
} catch (Exception e) {
log.error("An unexpected error occurred while trying to build test's detail url (result=${result})!", e)
}
}
private GString getWaterfallAnchor(WptResultXml xmlResult, String eventName, Integer testStepOneBasedIndex) {
switch (xmlResult.version) {
case WptXmlResultVersion.BEFORE_MULTISTEP:
return "${STATIC_PART_WATERFALL_ANCHOR}${eventName.replace(PageService.STEPNAME_DELIMITTER, '').replace('.', '')}"
case WptXmlResultVersion.MULTISTEP_FORK_ITERATEC:
return "${STATIC_PART_WATERFALL_ANCHOR}${eventName.replace(PageService.STEPNAME_DELIMITTER, '').replace('.', '')}"
case WptXmlResultVersion.MULTISTEP:
return "${STATIC_PART_WATERFALL_ANCHOR}_step${testStepOneBasedIndex}"
default:
throw new IllegalStateException("Version of result xml isn't specified!")
}
}
private void setAllMeasurands(GPathResult inputValues, EventResult result) {
Measurand.values().each {
if (it.getTagInResultXml()) {
@@ -164,6 +164,7 @@ class JobRunService {
}
}
log.debug("Cleanup done.")
return jobResultsToDelete.size()
}
private int rescheduleJobRunsYoungerThan(Date date) {
@@ -279,7 +279,7 @@ public class EventResultDashboardService {
}
URL testsDetailsURL
performanceLoggingService.logExecutionTimeSilently(LogLevel.DEBUG, 'getting result-map RAW - building detail urls', 2){
testsDetailsURL = eventResult.testDetailsWaterfallURL ?: this.buildTestsDetailsURL(eventResult)
testsDetailsURL = this.buildTestsDetailsURL(eventResult)
}
WptEventResultInfo chartPointWptInfo
performanceLoggingService.logExecutionTimeSilently(LogLevel.DEBUG, 'getting result-map RAW - get points wpt infos', 2){
@@ -148,9 +148,6 @@
</g:else>
</ul>
</div>
<g:actionSubmit value="${message(code: 'de.iteratec.ism.ui.labels.download.csv', 'default': 'Export as CSV')}"
action="downloadCsv" class="btn btn-primary pull-right space-right show-button"/>
<g:render template="/_resultSelection/hiddenWarnings"/>
<!-- Actual tabs -->
Oops, something went wrong.

0 comments on commit 159e9bd

Please sign in to comment.