Skip to content

Commit

Permalink
324970: Provide a mechanism to continue manual analysis from MAT's
Browse files Browse the repository at this point in the history
automatic reports

Add more links to queries for Top Components

Improve accessibility of HTML pie charts

Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=324970
  • Loading branch information
ajohnson1 committed Oct 7, 2020
1 parent e2bad31 commit 9f1ff7e
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ private void addBiggestObjects(SectionSpec composite) throws SnapshotException
composite.add(new QuerySpec(Messages.TopConsumers2Query_BiggestObjectsOverview, pie.build()));
QuerySpec spec = new QuerySpec(Messages.TopConsumers2Query_BiggestObjects,
new ObjectListResult.Outbound(snapshot, suspects.toArray()));
addCommand(spec, "list_objects", suspects); //$NON-NLS-1$
addCommand(spec, "show_dominator_tree", suspects); //$NON-NLS-1$
spec.set(Params.Html.COLLAPSED, Boolean.TRUE.toString());
composite.add(spec);
}
Expand Down Expand Up @@ -220,7 +220,7 @@ private void addBiggestObjects(SectionSpec composite) throws SnapshotException
composite.add(new QuerySpec(Messages.TopConsumers2Query_BiggestObjectsOverview, pie.build()));
QuerySpec spec = new QuerySpec(Messages.TopConsumers2Query_BiggestObjects,
new ObjectListResult.Outbound(snapshot, ids));
addCommand(spec, "list_objects", suspects); //$NON-NLS-1$
addCommand(spec, "show_dominator_tree", suspects); //$NON-NLS-1$
spec.set(Params.Html.COLLAPSED, Boolean.TRUE.toString());
composite.add(spec);
}
Expand Down Expand Up @@ -320,7 +320,20 @@ public String getOQL()
{
suspectObjects.addAll(r.getObjectIds());
}
addCommand(spec, "histogram", suspectObjects); //$NON-NLS-1$
addCommand(spec, "show_dominator_tree -groupby BY_CLASS", suspectObjects); //$NON-NLS-1$
if (spec.getCommand() == null && objects == null)
{
StringBuilder sb = new StringBuilder();
for (ClassHistogramRecord r : suspects)
{
if (sb.length() > 0)
sb.append(',');
sb.append(r.getClassId());
}
sb.insert(0, "show_dominator_tree -groupby BY_CLASS SELECT OBJECTS o FROM OBJECTS (dominators(-1)) o where classof(o) in (SELECT * FROM OBJECTS "); //$NON-NLS-1$
sb.append(')');
spec.setCommand(sb.toString());
}
spec.set(Params.Html.COLLAPSED, Boolean.TRUE.toString());
composite.add(spec);
}
Expand Down Expand Up @@ -407,6 +420,28 @@ public String getOQL()
suspectObjects.addAll(r.getObjectIds());
}
addCommand(spec, "show_dominator_tree -groupby BY_CLASSLOADER", suspectObjects); //$NON-NLS-1$
if (spec.getCommand() == null && objects == null)
{
StringBuilder sb = new StringBuilder();
for (ClassLoaderHistogramRecord r : suspects)
{
if (sb.length() > 0)
sb.append(',');
sb.append(r.getClassLoaderId());
}
sb.insert(0, "(SELECT * FROM OBJECTS "); //$NON-NLS-1$
sb.append(')');
String ids = sb.toString();
sb.setLength(0);
sb.append("show_dominator_tree -groupby BY_CLASSLOADER SELECT OBJECTS o FROM OBJECTS (dominators(-1)) o WHERE classof(o).@classLoaderId in "); //$NON-NLS-1$
sb.append(ids);
sb.append(" and o implements org.eclipse.mat.snapshot.model.IClass = false and o implements org.eclipse.mat.snapshot.model.IClassLoader = false"); //$NON-NLS-1$
sb.append(" or o implements org.eclipse.mat.snapshot.model.IClass and $ {snapshot}.getObject(o).@classLoaderId in "); //$NON-NLS-1$
sb.append(ids);
sb.append(" or o implements org.eclipse.mat.snapshot.model.IClassLoader and o in "); //$NON-NLS-1$
sb.append(ids);
spec.setCommand(sb.toString());
}
}
catch (SnapshotException e)
{}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2019 SAP AG and others.
* Copyright (c) 2008, 2020 SAP AG, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -14,8 +14,13 @@
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.birt.chart.computation.LegendItemHints;
import org.eclipse.birt.chart.device.EmptyUpdateNotifier;
Expand All @@ -29,13 +34,15 @@
import org.eclipse.birt.chart.factory.RunTimeContext;
import org.eclipse.birt.chart.model.Chart;
import org.eclipse.birt.chart.model.attribute.ActionType;
import org.eclipse.birt.chart.model.attribute.Anchor;
import org.eclipse.birt.chart.model.attribute.Bounds;
import org.eclipse.birt.chart.model.attribute.Insets;
import org.eclipse.birt.chart.model.attribute.TooltipValue;
import org.eclipse.birt.chart.model.attribute.TriggerCondition;
import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl;
import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
import org.eclipse.birt.chart.model.attribute.impl.TooltipValueImpl;
import org.eclipse.birt.chart.model.attribute.impl.URLValueImpl;
import org.eclipse.birt.chart.model.data.Action;
import org.eclipse.birt.chart.model.data.Trigger;
import org.eclipse.birt.chart.model.data.impl.ActionImpl;
Expand All @@ -44,46 +51,72 @@
import org.eclipse.birt.chart.render.ActionRendererAdapter;
import org.eclipse.birt.chart.script.IScriptClassLoader;
import org.eclipse.birt.chart.util.PluginSettings;
import org.eclipse.mat.SnapshotException;
import org.eclipse.mat.query.IResult;
import org.eclipse.mat.query.IResultPie;
import org.eclipse.mat.query.IResultPie.Slice;
import org.eclipse.mat.query.registry.QueryObjectLink;
import org.eclipse.mat.report.IOutputter;
import org.eclipse.mat.report.Renderer;
import org.eclipse.mat.util.HTMLUtils;
import org.eclipse.mat.util.HTMLUtils;
import org.eclipse.mat.util.MessageUtil;
import org.eclipse.mat.util.Units;

@Renderer(target = "html", result = IResultPie.class)
public class HtmlPieChartRenderer implements IOutputter
{

public void embedd(Context context, IResult result, Writer writer) throws IOException
public void embedd(final Context context, IResult result, Writer writer) throws IOException
{
try
{
IResultPie pie = (IResultPie) result;
final IResultPie pie = (IResultPie) result;

String imageFile = "chart" + context.getId() + ".png"; //$NON-NLS-1$ //$NON-NLS-2$

Chart chart = ChartBuilder.create(pie, false, ColorDefinitionImpl.WHITE(), ColorDefinitionImpl.BLACK());

Trigger trigger = TriggerImpl.create(TriggerCondition.ONMOUSEOVER_LITERAL,
ActionImpl.create(ActionType.SHOW_TOOLTIP_LITERAL,
TooltipValueImpl.create(200, "tooltip"))); //$NON-NLS-1$
chart.getLegend().getTriggers().add(trigger);


// For hover text with title=
Trigger trigger = TriggerImpl.create(TriggerCondition.ONMOUSEOVER_LITERAL, ActionImpl
.create(ActionType.SHOW_TOOLTIP_LITERAL, TooltipValueImpl.create(200, "tooltip"))); //$NON-NLS-1$
chart.getLegend().getTriggers().add(trigger);
// For open mat:// URL
Trigger trigger2 = TriggerImpl.create(TriggerCondition.ONCLICK_LITERAL, ActionImpl.create(
ActionType.URL_REDIRECT_LITERAL, URLValueImpl.create(null, null, null, null, null)));
chart.getLegend().getTriggers().add(trigger2);
// For open mat:// URL
Trigger trigger3 = TriggerImpl.create(TriggerCondition.ONKEYPRESS_LITERAL, ActionImpl.create(
ActionType.URL_REDIRECT_LITERAL, URLValueImpl.create(null, null, null, null, null)));
chart.getLegend().getTriggers().add(trigger3);

PluginSettings ps = PluginSettings.instance();
IDeviceRenderer render = ps.getDevice("dv.PNG"); //$NON-NLS-1$
render.setProperty(IDeviceRenderer.FILE_IDENTIFIER, new File(context.getOutputDirectory(), imageFile));

// Set size for chart
int width = 850, height = 350;
final int slices = pie.getSlices().size();
// Make room for more columns of labels
if (slices > 13)
width += 350 * (slices / 13);
Bounds bo = BoundsImpl.create(0, 0, width, height);
/**
* Windows on high res display.
* 100% = 96 15", 22" display, 1920 x 1080
* 125% = 120
* 150% = 144
* 175% = 168
*/
int resolution = render.getDisplayServer().getDpiResolution();
bo.scale(72d / resolution);

// Make a bit more room for long class names in the legend
Legend lg = chart.getLegend();
Insets is = lg.getInsets();
is.setLeft(is.getLeft() - 10);
lg.setMaxPercent(0.40);
// Normally 40%
lg.setMaxPercent((width - 510.0) / width);
lg.setAnchor(Anchor.EAST_LITERAL);

RunTimeContext rtc = new RunTimeContext();
rtc.setScriptClassLoader(new IScriptClassLoader()
Expand All @@ -107,8 +140,44 @@ public void processAction(Action action, StructureSource source)
if (StructureType.LEGEND_ENTRY.equals(source.getType()))
{
LegendItemHints item = (LegendItemHints) source.getSource();
tooltip.setText(item.getItemText());
Slice slice = pie.getSlices().get(item.getIndex());
String v = Units.Storage.of((long)slice.getValue()).format((long)slice.getValue());
if (v != null)
{
// Add some information
tooltip.setText(MessageUtil.format(Messages.HtmlPieChartRenderer_LabelTooltipWithStorage, item.getItemText(), v));
}
else
{
tooltip.setText(item.getItemText());
}
}
}
else if (ActionType.URL_REDIRECT_LITERAL.equals(action.getType()))
{
URLValueImpl cb = (URLValueImpl) action.getValue();
if (StructureType.LEGEND_ENTRY.equals(source.getType()))
{
LegendItemHints item = (LegendItemHints) source.getSource();
Slice slice = pie.getSlices().get(item.getIndex());
if (slice.getContext() != null)
{
try
{
int id = slice.getContext().getObjectId();
if (id != -1)
{
String externalIdentifier = context.getQueryContext().mapToExternalIdentifier(id);
cb.setBaseUrl(QueryObjectLink.forObject(externalIdentifier));
}
}
catch (SnapshotException e)
{
return;
}
}
}

}
}
/*
Expand All @@ -123,10 +192,11 @@ public void processAction(Action action, StructureSource source, RunTimeContext
gr.render(render, state);
String imageMap = ((IImageMapEmitter) render).getImageMap();
// fix up HTML errors
imageMap = imageMap.replaceAll("/><area","><area").replaceFirst("/>$", ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
imageMap = fixupMapAreas(imageMap, resolution);
String mapName = "chart" + context.getId() + "map"; //$NON-NLS-1$ //$NON-NLS-2$
writer.append("<map name='").append(mapName).append("'>").append(imageMap).append("</map>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
writer.append("<img src=\"").append(imageFile).append("\" width=\"" + width + "\" height=\"" + height + "\" usemap='#").append(mapName).append("' alt=\"\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
String altText = MessageUtil.format(Messages.HtmlPieChartRenderer_PieChartSlices, slices);
writer.append("<img src=\"").append(imageFile).append("\" width=\"" + width + "\" height=\"" + height + "\" usemap='#").append(mapName).append("' alt=\"").append(altText).append("\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
}
catch (LinkageError e)
{
Expand All @@ -138,6 +208,67 @@ public void processAction(Action action, StructureSource source, RunTimeContext
}
}

/**
* BIRT has some problems with map area
* @param imageMap a fragment of HTML; a list of &lt;area&gt;
* @param resolution in DPI - normal is 96
* @return a fixed-up fragment of HTML
*/
private String fixupMapAreas(String imageMap, int resolution)
{
// Fix up for HTML4
imageMap = imageMap.replaceAll("/><area","><area").replaceFirst("/>$", ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
// Fix up alternate text
String altReplace = MessageFormat.format(Matcher.quoteReplacement(Messages.HtmlPieChartRenderer_AreaAltReplace), "$2"); //$NON-NLS-1$
imageMap = imageMap.replaceAll("alt=\"\"([^>]*)title=\"([^\"]*)\"", "alt=\"" + altReplace + "\"$1title=\"$2\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// Fix up no destination
imageMap = imageMap.replace("href=\"\"", ""); //$NON-NLS-1$ //$NON-NLS-2$
// Fix up order of areas - BIRT generates in reverse order
String areas[] = imageMap.split("<area "); //$NON-NLS-1$
Arrays.sort(areas, new Comparator<String>() {
public int compare(String o1, String o2)
{
int i1 = o1.indexOf("title"); //$NON-NLS-1$
int i2 = o2.indexOf("title"); //$NON-NLS-1$
return o1.substring(i1 + 1).compareTo(o2.substring(i2 + 1));
}
});
/*
* Fix up scaling of area coordinates - they seem too small in BIRT 4.7
*
* Set up scaling as things go wrong on Windows
* with high DPI scaling of 125%, 150% etc.
* Expect first coordinate to be about 850*0.6=510
* Round to nearest 25%.
*/
double scaling = resolution / 96.0;
for (int i = 0; i < areas.length; ++i)
{
String m = "coords=\""; //$NON-NLS-1$
int i1 = areas[i].indexOf(m);
if (i1 >= 0)
{
i1 += m.length();
int i2 = areas[i].indexOf("\"", i1); //$NON-NLS-1$
if (i2 > 0) {
StringBuilder sb = new StringBuilder(areas[i].substring(0, i1));
String coords[] = areas[i].substring(i1, i2).split(","); //$NON-NLS-1$
for (int j = 0; j < coords.length; ++j)
{
if (j > 0)
sb.append(',');
int v = Integer.parseInt(coords[j]);
sb.append((int)(v * scaling));
}
sb.append(areas[i].substring(i2));
areas[i] = sb.toString();
}
}
}
imageMap = String.join("<area ", areas); //$NON-NLS-1$
return imageMap;
}

private void handleError(Throwable e, Writer writer) throws IOException
{
StringBuilder message = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2010 SAP AG and others.
* Copyright (c) 2010,2020 SAP AG, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
* Andrew Johnson (IBM Corporation) - more links
*******************************************************************************/
package org.eclipse.mat.impl.chart;

Expand All @@ -16,7 +17,10 @@ public class Messages extends NLS
{
private static final String BUNDLE_NAME = "org.eclipse.mat.impl.chart.messages"; //$NON-NLS-1$
public static String ChartBuilder_Total;
public static String HtmlPieChartRenderer_AreaAltReplace;
public static String HtmlPieChartRenderer_ErrorRenderingChart;
public static String HtmlPieChartRenderer_LabelTooltipWithStorage;
public static String HtmlPieChartRenderer_PieChartSlices;
public static String HtmlPieChartRenderer_SeeLogForDetails;
static
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
###############################################################################
# Copyright (c) 2010 SAP AG and others.
# Copyright (c) 2010,2020 SAP AG, IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# SAP AG - initial API and implementation
# Andrew Johnson (IBM Corporation) - more links
###############################################################################
ChartBuilder_Total=Total: {0}
HtmlPieChartRenderer_AreaAltReplace=Slice {0}
HtmlPieChartRenderer_ErrorRenderingChart=Error rendering chart:
HtmlPieChartRenderer_LabelTooltipWithStorage={0}: {1}
HtmlPieChartRenderer_PieChartSlices=Pie chart with {0} slices
HtmlPieChartRenderer_SeeLogForDetails=\ (See Log for Details)
2 changes: 1 addition & 1 deletion plugins/org.eclipse.mat.report/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Export-Package: org.eclipse.mat,
org.eclipse.mat.query.annotations.descriptors,
org.eclipse.mat.query.quantize,
org.eclipse.mat.query.refined,
org.eclipse.mat.query.registry;x-friends:="org.eclipse.mat.ui,org.eclipse.mat.api,org.eclipse.mat.chart.ui",
org.eclipse.mat.query.registry;x-friends:="org.eclipse.mat.ui,org.eclipse.mat.api,org.eclipse.mat.chart,org.eclipse.mat.chart.ui",
org.eclipse.mat.query.results,
org.eclipse.mat.report,
org.eclipse.mat.util
Expand Down
4 changes: 4 additions & 0 deletions plugins/org.eclipse.mat.report/META-INF/html/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ function hide(obj, a)
{
div.display = "block";
obj.firstChild.src = imageBase.value + 'opened.gif'
if (obj.getAttribute("data-hide") != null)
obj.title=obj.getAttribute("data-hide")
}
else
{
div.display = "none";
obj.firstChild.src = imageBase.value + 'closed.gif'
if (obj.getAttribute("data-unhide") != null)
obj.title=obj.getAttribute("data-unhide")
}
}

Expand Down
Loading

0 comments on commit 9f1ff7e

Please sign in to comment.