FUS: add action to test whitelist

This commit is contained in:
Svetlana.Zemlyanskaya
2019-02-04 16:36:05 +01:00
parent 1aa55e2390
commit c96e2cc6ef
5 changed files with 530 additions and 0 deletions
@@ -0,0 +1,34 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TestParseEventLogWhitelistAction extends DumbAwareAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final Project project = e.getProject();
if (project != null) {
new TestParseEventLogWhitelistDialog(project, e.getData(CommonDataKeys.EDITOR)).show();
}
}
@Override
public void update(@NotNull AnActionEvent e) {
boolean enabled = isEnabled(e.getProject());
e.getPresentation().setEnabledAndVisible(enabled);
if (enabled && e.getData(CommonDataKeys.EDITOR) == null) {
e.getPresentation().setEnabled(false);
}
}
private static boolean isEnabled(@Nullable Project project) {
return project != null && ApplicationManagerEx.getApplicationEx().isInternal();
}
}
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.internal.statistic.actions.TestParseEventLogWhitelistDialog">
<grid id="27dc6" binding="myMainPanel" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<splitpane id="e8a18" binding="myInputOutputSplitPane">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="200" height="200"/>
</grid>
</constraints>
<properties>
<orientation value="0"/>
</properties>
<border type="none"/>
<children>
<scrollpane id="609ba" class="com.intellij.ui.components.JBScrollPane">
<constraints>
<splitpane position="right"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="4a4ba" class="javax.swing.JEditorPane" binding="myResultPane">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
<splitpane id="b867e" binding="myInputDataSplitPane">
<constraints>
<splitpane position="left"/>
</constraints>
<properties>
<continuousLayout value="true"/>
<dividerLocation value="200"/>
<dividerSize value="2"/>
</properties>
<border type="empty"/>
<children>
<scrollpane id="c30e5" class="com.intellij.ui.components.JBScrollPane">
<constraints>
<splitpane position="left"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="ecf31" binding="myWhitelistPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints/>
<properties/>
<border type="none"/>
<children/>
</grid>
</children>
</scrollpane>
<scrollpane id="59306" class="com.intellij.ui.components.JBScrollPane">
<constraints>
<splitpane position="right"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="29cce" class="javax.swing.JEditorPane" binding="myEventLogPanel">
<constraints/>
<properties>
<text value="Add event log to filter here"/>
</properties>
</component>
</children>
</scrollpane>
</children>
</splitpane>
</children>
</splitpane>
</children>
</grid>
</form>
@@ -0,0 +1,184 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.actions;
import com.intellij.internal.statistic.eventLog.*;
import com.intellij.internal.statistic.service.fus.FUStatisticsWhiteListGroupsService;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.testFramework.LightVirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.Set;
public class TestParseEventLogWhitelistDialog extends DialogWrapper {
private static final Logger LOG = Logger.getInstance(TestParseEventLogWhitelistDialog.class);
private static final int IN_DIVIDER_LOCATION = 650;
private static final int IN_OUT_DIVIDER_LOCATION = 500;
private JPanel myMainPanel;
private JPanel myWhitelistPanel;
private JEditorPane myEventLogPanel;
private JSplitPane myInputDataSplitPane;
private JSplitPane myInputOutputSplitPane;
private JEditorPane myResultPane;
private final Project myProject;
private final EditorEx myEditor;
protected TestParseEventLogWhitelistDialog(@NotNull Project project, @Nullable Editor selectedEditor) {
super(project);
myProject = project;
setOKButtonText("&Filter Event Log");
setCancelButtonText("&Close");
Disposer.register(myProject, getDisposable());
VirtualFile selectedFile = selectedEditor == null ? null : FileDocumentManager.getInstance().getFile(selectedEditor.getDocument());
setTitle(selectedFile == null ? "Event Log Filter" : "Event Log Filter by: " + selectedFile.getName());
myEditor = initEditor(selectedEditor);
myEditor.getSettings().setLineMarkerAreaShown(false);
init();
if (selectedEditor != null) {
doOKAction();
ApplicationManager.getApplication().invokeLater(() -> {
IdeFocusManager.getGlobalInstance()
.doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(myEditor.getContentComponent(), true));
myEditor.getCaretModel().moveToOffset(selectedEditor.getCaretModel().getOffset());
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
}, ModalityState.stateForComponent(myMainPanel));
}
}
@NotNull
private EditorEx initEditor(@Nullable Editor selectedEditor) {
if (selectedEditor != null) {
return (EditorEx)EditorFactory.getInstance().createEditor(selectedEditor.getDocument(), myProject);
}
else {
Document document = EditorFactory.getInstance().createDocument(StringUtil.notNullize("{}"));
EditorEx editor = (EditorEx)EditorFactory.getInstance().createEditor(document, myProject);
editor.getSelectionModel().setSelection(0, document.getTextLength());
return editor;
}
}
@Override
protected void init() {
configEditorPanel(myProject, myWhitelistPanel, myEditor);
myInputDataSplitPane.setDividerLocation(IN_DIVIDER_LOCATION);
myInputOutputSplitPane.setDividerLocation(IN_OUT_DIVIDER_LOCATION);
super.init();
}
private static void configEditorPanel(@NotNull Project project, @NotNull JPanel panel, @NotNull EditorEx editor) {
panel.setLayout(new BorderLayout());
panel.add(editor.getComponent(), BorderLayout.CENTER);
editor.getSettings().setFoldingOutlineShown(false);
final FileType fileType = FileTypeManager.getInstance().findFileTypeByName("JSON");
final LightVirtualFile lightFile = new LightVirtualFile("Dummy.json", fileType, "");
EditorHighlighter highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, lightFile);
try {
editor.setHighlighter(highlighter);
}
catch (Throwable e) {
LOG.warn(e);
}
}
@Override
@NotNull
protected String getDimensionServiceKey() {
return TestParseEventLogWhitelistDialog.class.getCanonicalName();
}
@SuppressWarnings("TestOnlyProblems")
@Override
protected void doOKAction() {
myEditor.getSelectionModel().removeSelection();
updateOutputText("");
final BuildNumber build = BuildNumber.fromString(EventLogConfiguration.INSTANCE.getBuild());
final Set<String> groups = FUStatisticsWhiteListGroupsService.parseApprovedGroups(myEditor.getDocument().getText(), build);
try {
final String parsed = parseLogAndFilter(new LogEventWhitelistFilter(groups), myEventLogPanel.getText());
updateOutputText(parsed.trim());
}
catch (IOException | ParseEventLogWhitelistException e) {
Messages.showErrorDialog(myProject, e.getMessage(), "Failed Applying Whitelist to Event Log");
}
}
private void updateOutputText(@NotNull String text) {
myResultPane.setText(text);
}
@NotNull
private static String parseLogAndFilter(@NotNull LogEventFilter filter, @NotNull String text)
throws IOException, ParseEventLogWhitelistException {
final File log = FileUtil.createTempFile("feature-event-log", ".log");
try {
FileUtil.writeToFile(log, text);
final LogEventRecordRequest request = LogEventRecordRequest.Companion.create(log, filter, true);
if (request == null) {
throw new ParseEventLogWhitelistException("Failed parsing event log");
}
return LogEventSerializer.INSTANCE.toString(request);
}
finally {
FileUtil.delete(log);
}
}
@Nullable
@Override
protected JComponent createCenterPanel() {
return myMainPanel;
}
@Override
public JComponent getPreferredFocusedComponent() {
return myEventLogPanel;
}
@Override
public void dispose() {
if (!myEditor.isDisposed()) {
EditorFactory.getInstance().releaseEditor(myEditor);
}
super.dispose();
}
public static class ParseEventLogWhitelistException extends Exception {
public ParseEventLogWhitelistException(String s) {
super(s);
}
}
}
@@ -672,6 +672,230 @@ class FeatureStatisticsWhitelistTest {
doTest(content, "183.2495", "test.group.id")
}
@Test
fun `with from snapshot and build later is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.0"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495", "test.group.id")
}
@Test
fun `with from snapshot and build later with bugfix update is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.0"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495.245", "test.group.id")
}
@Test
fun `with from snapshot and build earlier is not accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "191.0"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495")
}
@Test
fun `with from equals to build is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495", "test.group.id")
}
@Test
fun `with from middle number equals to build is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495.0", "test.group.id")
}
@Test
fun `with from middle number equals to build and last is bigger is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495.12", "test.group.id")
}
@Test
fun `with build middle number equals to from and last is bigger is not accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495.12"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.1495")
}
@Test
fun `with build middle number equals to to is not accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495.12",
"to": "183.4885"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.4885")
}
@Test
fun `with build middle number equals to to and last is bigger is not accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495.12",
"to": "183.4885"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.4885.35")
}
@Test
fun `with build middle number smaller then to is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495.12",
"to": "183.4885"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.4884.35", "test.group.id")
}
@Test
fun `with build middle number smaller then to and have two numbers is accepted`() {
val content = """
{
"groups" : [{
"id" : "test.group.id",
"title" : "Test Group",
"description" : "Test group description",
"type" : "counter",
"builds" : [ {
"from" : "183.1495.12",
"to": "183.4885"
}],
"context" : {
}
}]
}
"""
doTest(content, "183.4884", "test.group.id")
}
@Test
fun `snapshot builds major greater than from is accepted`() {
val content = """
@@ -172,6 +172,11 @@
<add-to-group group-id="Internal" anchor="last"/>
</group>
<action internal="true" id="TestParseEventLogWhitelistAction" class="com.intellij.internal.statistic.actions.TestParseEventLogWhitelistAction"
text="Test Parsing Event Log Whitelist...">
<add-to-group group-id="FeatureUsage.Internal" anchor="last"/>
</action>
<!-- Help -->
<action id="WhatsNewAction" class="com.intellij.ide.actions.WhatsNewAction">
<add-to-group group-id="HelpMenu" anchor="after" relative-to-action="ShowTips"/>