From 426c2e4733d1287767356a284486fbdaa0f56f86 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Wed, 19 Jun 2024 10:15:43 -0400 Subject: [PATCH] InAndOut Analysis using ITmfDataProviderConfigurator extension Note: - Used through trace server - Multiple instances allowed - configuration is applied to all traces in experiment - configuration is not applied to experiment - Eclipse is using legacy InAndOut analysis config which allows one configuration per trace only and which integrated in the Eclipse UI [Added] InAndOut Analysis using ITmfDataProviderConfigurator extension Signed-off-by: Bernd Hufmann --- .../build.properties | 3 +- .../plugin.xml | 7 + .../schema/in-and-out-analysis.json | 59 ++++ .../core/analysis/InAndOutAnalysisModule.java | 179 +++++++++++- .../analysis/InAndOutDataProviderFactory.java | 269 ++++++++++++++++++ .../SegmentSpecifierConfiguration.java | 78 +++++ .../core/services/DataProviderService.java | 19 +- .../traceserver.product | 1 + 8 files changed, 604 insertions(+), 11 deletions(-) create mode 100644 analyses/org.eclipse.tracecompass.incubator.inandout.core/schema/in-and-out-analysis.json create mode 100644 analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutDataProviderFactory.java create mode 100644 analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/SegmentSpecifierConfiguration.java diff --git a/analyses/org.eclipse.tracecompass.incubator.inandout.core/build.properties b/analyses/org.eclipse.tracecompass.incubator.inandout.core/build.properties index c2f6da1ba..2eed3aa9d 100644 --- a/analyses/org.eclipse.tracecompass.incubator.inandout.core/build.properties +++ b/analyses/org.eclipse.tracecompass.incubator.inandout.core/build.properties @@ -16,6 +16,7 @@ bin.includes = META-INF/,\ plugin.properties,\ .,\ plugin.xml,\ - icons/ + icons/,\ + schema/ additional.bundles = org.eclipse.jdt.annotation jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/analyses/org.eclipse.tracecompass.incubator.inandout.core/plugin.xml b/analyses/org.eclipse.tracecompass.incubator.inandout.core/plugin.xml index d0eb89bab..d199acab4 100644 --- a/analyses/org.eclipse.tracecompass.incubator.inandout.core/plugin.xml +++ b/analyses/org.eclipse.tracecompass.incubator.inandout.core/plugin.xml @@ -20,4 +20,11 @@ + + + + diff --git a/analyses/org.eclipse.tracecompass.incubator.inandout.core/schema/in-and-out-analysis.json b/analyses/org.eclipse.tracecompass.incubator.inandout.core/schema/in-and-out-analysis.json new file mode 100644 index 000000000..248c1b327 --- /dev/null +++ b/analyses/org.eclipse.tracecompass.incubator.inandout.core/schema/in-and-out-analysis.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://org.eclipse.tracecompass/in-and-out-analysis.json", + "title": "InAndOut Analysis", + "description": "Custom Execution Analysis schema", + "type": "object", + "properties": { + "name" : { + "type": "string", + "description": "The name of this InAndOut configuration" + }, + "description" : { + "type": "string", + "description": "The descrition of this InAndOut configuration" + }, + "specifiers": { + "description": "array specifiers", + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string", + "descritpion": "The label of the identifier" + }, + "inRegex": { + "type": "string", + "descritpion": "The IN regular expression" + }, + "outRegex": { + "type": "string", + "descritpion": "The OUT regular expression" + }, + "contextInRegex": { + "type": "string", + "descritpion": "The context IN regular expression" + }, + "contextOutRegex": { + "type": "string", + "descritpion": "The context OUT regular expression" + }, + "classifier": { + "type": "string", + "descritpion": "The classifier" + }, + "required": [ + "label", + "inRegex", + "outRegex", + "contextInRegex", + "contextOutRegex", + "classifier" + ] + } + } + } + }, + "required": ["name", "specifiers"] +} diff --git a/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutAnalysisModule.java b/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutAnalysisModule.java index 849bede33..399bd5109 100644 --- a/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutAnalysisModule.java +++ b/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutAnalysisModule.java @@ -23,9 +23,18 @@ import java.util.List; import java.util.Objects; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.analysis.profiling.core.instrumented.InstrumentedCallStackAnalysis; import org.eclipse.tracecompass.incubator.internal.inandout.core.Activator; +import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.TmfConfiguration; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException; import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; @@ -50,6 +59,42 @@ public class InAndOutAnalysisModule extends InstrumentedCallStackAnalysis { */ public static final String JSON = ".config.json"; //$NON-NLS-1$ + private @Nullable ITmfConfiguration fConfiguration; + private @Nullable List<@NonNull SegmentSpecifier> fSpecifiers; + + @Override + public @NonNull String getName() { + ITmfConfiguration config = fConfiguration; + if (config != null) { + return config.getName(); + } + return super.getName(); + } + + @Override + public @NonNull String getHelpText() { + ITmfConfiguration config = fConfiguration; + if (config != null) { + return config.getDescription(); + } + return super.getHelpText(); + } + + @Override + public void setConfiguration(ITmfConfiguration configuration) throws TmfConfigurationException { + if (configuration == null) { + throw new TmfConfigurationException("Can't set a null configuration"); //$NON-NLS-1$ + } + SegmentSpecifierConfiguration config = SegmentSpecifierConfiguration.fromJsonMap(configuration.getParameters()); + fConfiguration = configuration; + fSpecifiers = config.getSpecifiers(); + } + + @Override + public @Nullable ITmfConfiguration getConfiguration() { + return fConfiguration; + } + /** * Reference (default) specifier configured. */ @@ -57,16 +102,26 @@ public class InAndOutAnalysisModule extends InstrumentedCallStackAnalysis { @Override public @NonNull String getId() { - return ID; + ITmfConfiguration config = fConfiguration; + if (config == null || fSpecifiers == null) { + return ID; + } + return ID + config.getId(); } @Override public boolean canExecute(@NonNull ITmfTrace trace) { - File config = getConfig(trace); - return config.exists() && super.canExecute(trace); + ITmfConfiguration configuration = fConfiguration; + if (configuration == null) { + // Eclipse Trace Compass + File config = getConfig(trace); + return config.exists() && super.canExecute(trace); + } + return true; } private static File getConfig(@NonNull ITmfTrace trace) { + // Eclipse Trace Compass String folder = TmfTraceManager.getSupplementaryFileDir(trace); File config = new File(folder + File.separator + ID + JSON); if (!config.exists()) { @@ -80,9 +135,13 @@ private static File getConfig(@NonNull ITmfTrace trace) { @Override protected @NonNull ITmfStateProvider createStateProvider() { ITmfTrace trace = Objects.requireNonNull(getTrace(), "Trace should not be null at this point"); //$NON-NLS-1$ - File configFile = getConfig(trace); - List<@NonNull SegmentSpecifier> list = read(configFile); - return new InAndOutAnalysisStateProvider(trace, list); + List<@NonNull SegmentSpecifier> specifiers = fSpecifiers; + if (specifiers == null) { + // Eclipse Trace Compass + File configFile = getConfig(trace); + specifiers = read(configFile); + } + return new InAndOutAnalysisStateProvider(trace, specifiers); } /** @@ -116,10 +175,118 @@ private static File getConfig(@NonNull ITmfTrace trace) { * the specifiers */ public static void write(File file, List<@NonNull SegmentSpecifier> specifiers) { + // Eclipse Trace Compass try (Writer writer = new FileWriter(file)) { writer.append(new Gson().toJson(specifiers)); } catch (IOException e) { Activator.getInstance().logError(e.getMessage(), e); } } + + /** + * Create the InAndOutAnalysisModule for a given configuration and trace + * + * @param config + * the input {@link ITmfConfiguration} + * @param trace + * the trace to apply it to + * @param writeConfig + * write the config (do only once) + * @return InAndOutAnalysisModule + * @throws TmfConfigurationException + * if an error occurs + */ + public static InAndOutAnalysisModule create(@NonNull ITmfConfiguration config, @NonNull ITmfTrace trace, boolean writeConfig) throws TmfConfigurationException { + /* + * Apply configuration to each trace (no need to check trace type here) + */ + InAndOutAnalysisModule module = new InAndOutAnalysisModule(); + module.setConfiguration(config); + if (writeConfig) { + IPath traceConfigPath = getTraceRootFolder(trace, config.getSourceTypeId()); + TmfConfiguration.writeConfiguration(config, traceConfigPath); + } + try { + if (module.setTrace(trace)) { + IAnalysisModule oldModule = trace.addAnalysisModule(module); + if (oldModule != null) { + oldModule.dispose(); + oldModule.clearPersistentData(); + } + } else { + module.dispose(); + throw new TmfConfigurationException("InAndOut analysis module can't be created"); //$NON-NLS-1$ + } + } catch (TmfAnalysisException | TmfTraceException e) { + module.dispose(); + throw new TmfConfigurationException("Exception when setting trace", e); //$NON-NLS-1$ + } + return module; + } + + /** + * Removes configuration from trace: + * - delete configuration file + * - remove analysis module from trace object + * + * @param config + * the configuration to remove + * @param trace + * the + * @throws TmfConfigurationException if an error occurs + */ + public static void remove(ITmfConfiguration config, @NonNull ITmfTrace trace) throws TmfConfigurationException { + IPath traceConfig = getTraceRootFolder(trace, config.getSourceTypeId()); + traceConfig = traceConfig.append(File.separator).append(config.getId()).addFileExtension(TmfConfiguration.JSON_EXTENSION); + File configFile = traceConfig.toFile(); + if ((!configFile.exists()) || !configFile.delete()) { + throw new TmfConfigurationException("InAndOut configuration file can't be deleted from trace: configId=" + config.getId()); //$NON-NLS-1$ + } + + // Remove and clear persistent data + try { + IAnalysisModule module = trace.removeAnalysisModule(ID + config.getId()); + if (module != null) { + module.dispose(); + module.clearPersistentData(); + } + } catch (TmfTraceException e) { + throw new TmfConfigurationException("Error removing analysis module from trace: analysis ID=" + ID + config.getId(), e); //$NON-NLS-1$ + } + } + + @SuppressWarnings("null") + private static @NonNull IPath getTraceRootFolder(@NonNull ITmfTrace trace, String subFolder) { + String supplFolder = TmfTraceManager.getSupplementaryFileDir(trace); + IPath supplPath = new Path(supplFolder); + supplPath = supplPath.addTrailingSeparator().append(subFolder); + return supplPath; + } + + /** + * Reads the configurations for a given trace + * + * @param trace + * the trace to read configurations from + * @return list of configurations if any + * @throws TmfConfigurationException + * if an error occurs + */ + public static @NonNull List readConfigurations(@NonNull ITmfTrace trace) throws TmfConfigurationException { + IPath rootPath = getTraceRootFolder(trace, SegmentSpecifierConfiguration.IN_AND_OUT_CONFIG_SOURCE_TYPE_ID); + File folder = rootPath.toFile(); + List list = new ArrayList<>(); + if (folder.exists()) { + File[] listOfFiles = folder.listFiles(); + for (File file : listOfFiles) { + IPath path = new Path(file.getName()); + if (path.getFileExtension().equals(TmfConfiguration.JSON_EXTENSION)) { + ITmfConfiguration config = TmfConfiguration.fromJsonFile(file); + list.add(config); + } + } + } + return list; + } + } diff --git a/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutDataProviderFactory.java b/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutDataProviderFactory.java new file mode 100644 index 000000000..05a313b01 --- /dev/null +++ b/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/InAndOutDataProviderFactory.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2024 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +package org.eclipse.tracecompass.incubator.internal.inandout.core.analysis; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tracecompass.incubator.internal.inandout.core.Activator; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSourceType; +import org.eclipse.tracecompass.tmf.core.config.ITmfDataProviderConfigurator; +import org.eclipse.tracecompass.tmf.core.config.TmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceType; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; +import org.eclipse.tracecompass.tmf.core.model.DataProviderDescriptor; +import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; +import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; +import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; +import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; +import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; +import org.osgi.framework.Bundle; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + +/** + * Data provider factory for InAndOut analysis. It doesn't have any output but is able + * to create custom InAndOut analyses. + */ +@NonNullByDefault +public class InAndOutDataProviderFactory implements IDataProviderFactory, ITmfDataProviderConfigurator { + + /** Data Provider factory ID */ + public static final String ID = "org.eclipse.tracecompass.incubator.inandout.core.analysis.inAndOutdataProviderFactory"; //$NON-NLS-1$ + + private static final ITmfConfigurationSourceType CONFIG_SOURCE_TYPE; + private static final String NAME = "In And Out Analysis"; //$NON-NLS-1$ + private static final String DESCRIPTION = "Configure In And Out analysis using file description"; //$NON-NLS-1$ + + private static final String CONFIGURATOR_NAME = "InAndOut Configurator"; //$NON-NLS-1$ + private static final String CONFIGURATOR_DESCRIPTION = "Configure custom InAndOut analysis"; //$NON-NLS-1$ + + private static final String CUSTOM_IN_AND_OUT_ANALYSIS_NAME = "InAndOut Analysis ({0})"; //$NON-NLS-1$ + private static final String CUSTOM_IN_AND_OUT_ANALYSIS_DESCRIPTION = "Custom InAndOut analysis configured by \" {0}\""; //$NON-NLS-1$ + + private static final Table fTmfConfigurationTable = HashBasedTable.create(); + + static { + Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID); + IPath defaultPath = new Path(SegmentSpecifierConfiguration.IN_AND_OUT_CONFIG_SOURCE_SCHEMA); + URL url = FileLocator.find(bundle, defaultPath, null); + File schemaFile = null; + try { + schemaFile = new File(FileLocator.toFileURL(url).toURI()); + } catch (URISyntaxException | IOException e) { + Activator.getInstance().logError("Failed to read schema file: " + SegmentSpecifierConfiguration.IN_AND_OUT_CONFIG_SOURCE_SCHEMA, e); //$NON-NLS-1$ + } + CONFIG_SOURCE_TYPE = new TmfConfigurationSourceType.Builder() + .setId(SegmentSpecifierConfiguration.IN_AND_OUT_CONFIG_SOURCE_TYPE_ID) + .setDescription(DESCRIPTION) + .setName(NAME) + .setSchemaFile(schemaFile) + .build(); + } + + // Data provider descriptor meant to be used to create new InAndOut configurations and hence new data providers + private static final IDataProviderDescriptor DESCRIPTOR = new DataProviderDescriptor.Builder() + .setId(ID) + .setName(CONFIGURATOR_NAME) + .setDescription(CONFIGURATOR_DESCRIPTION) + .setProviderType(ProviderType.NONE) + .build(); + + /** + * Default constructor + */ + public InAndOutDataProviderFactory() { + TmfSignalManager.register(this); + } + + @Override + public @Nullable ITmfTreeDataProvider createProvider(ITmfTrace trace) { + return null; + } + + @Override + public Collection getDescriptors(ITmfTrace trace) { + List list = new ArrayList<>(); + list.add(DESCRIPTOR); + for (ITmfConfiguration config : fTmfConfigurationTable.column(trace).values()) { + list.add(getDescriptorFromConfig(config)); + } + return list; + } + + @SuppressWarnings("null") + @Override + public @NonNull List<@NonNull ITmfConfigurationSourceType> getConfigurationSourceTypes() { + return List.of(CONFIG_SOURCE_TYPE); + } + + @Override + public @NonNull IDataProviderDescriptor createDataProviderDescriptors(ITmfTrace trace, ITmfConfiguration configuration) throws TmfConfigurationException { + + if (configuration.getName().equals(TmfConfiguration.UNKNOWN)) { + throw new TmfConfigurationException("Missing configuration name of InAndOut analysis"); //$NON-NLS-1$ + } + + if (configuration.getSourceTypeId().equals(TmfConfiguration.UNKNOWN)) { + throw new TmfConfigurationException("Missing configuration type for InAndOut analysis"); //$NON-NLS-1$ + } + + String description = configuration.getDescription(); + if (configuration.getDescription().equals(TmfConfiguration.UNKNOWN)) { + description = "InAndOut Analysis defined by configuration " + configuration.getName(); //$NON-NLS-1$ + } + + TmfConfiguration.Builder builder = new TmfConfiguration.Builder(); + builder.setId(configuration.getId()) + .setSourceTypeId(configuration.getSourceTypeId()) + .setName(configuration.getName()) + .setDescription(description) + .setParameters(configuration.getParameters()) + .build(); + + ITmfConfiguration config = builder.build(); + + applyConfiguration(trace, config, true); + if (fTmfConfigurationTable.contains(config.getId(), trace)) { + throw new TmfConfigurationException("Configuration already existis with label: " + config.getName()); //$NON-NLS-1$ + } + fTmfConfigurationTable.put(config.getId(), trace, config); + return getDescriptorFromConfig(config); + } + + @Override + public void removeDataProviderDescriptor(ITmfTrace trace, IDataProviderDescriptor descriptor) throws TmfConfigurationException { + + ITmfConfiguration creationConfiguration = descriptor.getConfiguration(); + if (creationConfiguration == null) { + throw new TmfConfigurationException("Data provider was not created by a configuration"); //$NON-NLS-1$ + } + + String configId = creationConfiguration.getId(); + ITmfConfiguration config = fTmfConfigurationTable.get(configId, trace); + if (config == null) { + return; + } + config = fTmfConfigurationTable.remove(configId, trace); + removeConfiguration(trace, config); + } + + /** + * Signal handler for opened trace signal. Will populate trace + * configurations + * + * @param signal + * the signal to handle + */ + @TmfSignalHandler + public void traceOpened(TmfTraceOpenedSignal signal) { + ITmfTrace trace = signal.getTrace(); + if (trace == null) { + return; + } + try { + if (trace instanceof TmfExperiment) { + for (ITmfTrace tr : TmfTraceManager.getTraceSet(trace)) { + @SuppressWarnings("null") + // Read configurations from sub-trace + List configs = InAndOutAnalysisModule.readConfigurations(tr); + readAndApplyConfiguration(trace, configs); + } + } else { + @SuppressWarnings("null") + // Read configurations trace + List configs = InAndOutAnalysisModule.readConfigurations(trace); + readAndApplyConfiguration(trace, configs); + } + } catch (TmfConfigurationException e) { + Activator.getInstance().logError("Error applying configurations for trace " + trace.getName(), e); //$NON-NLS-1$ + } + } + + /** + * Handles trace closed signal + * + * @param signal + * the close signal to handle + */ + @TmfSignalHandler + public void traceClosed(TmfTraceClosedSignal signal) { + ITmfTrace trace = signal.getTrace(); + fTmfConfigurationTable.column(trace).clear(); + } + + private void readAndApplyConfiguration(ITmfTrace trace, List configs) throws TmfConfigurationException { + for (ITmfConfiguration config : configs) { + if (!fTmfConfigurationTable.contains(config.getId(), trace)) { + fTmfConfigurationTable.put(config.getId(), trace, config); + applyConfiguration(trace, config, false); + } + } + } + + private void applyConfiguration(ITmfTrace trace, ITmfConfiguration config, boolean writeConfig) throws TmfConfigurationException { + if (trace instanceof TmfExperiment) { + for (ITmfTrace tr : TmfTraceManager.getTraceSet(trace)) { + applyConfiguration(tr, config, writeConfig); + } + // Only apply for traces in experiment + return; + } + // Apply configuration to any trace (no need to check trace type here) + InAndOutAnalysisModule.create(config, trace, writeConfig); + } + + private void removeConfiguration(ITmfTrace trace, ITmfConfiguration config) throws TmfConfigurationException { + if (trace instanceof TmfExperiment) { + for (ITmfTrace tr : TmfTraceManager.getTraceSet(trace)) { + removeConfiguration(tr, config); + } + // only remove for traces in experiment + return; + } + InAndOutAnalysisModule.remove(config, trace); + } + + @SuppressWarnings("null") + private static IDataProviderDescriptor getDescriptorFromConfig(ITmfConfiguration config) { + return new DataProviderDescriptor.Builder() + .setParentId(ID) + .setId(InAndOutAnalysisModule.ID + config.getId()) + .setName(NLS.bind(CUSTOM_IN_AND_OUT_ANALYSIS_NAME, config.getName())) + .setDescription(NLS.bind(CUSTOM_IN_AND_OUT_ANALYSIS_DESCRIPTION, config.getName())) + .setProviderType(ProviderType.NONE) + .setConfiguration(config) + .build(); + } +} diff --git a/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/SegmentSpecifierConfiguration.java b/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/SegmentSpecifierConfiguration.java new file mode 100644 index 000000000..80271ddbf --- /dev/null +++ b/analyses/org.eclipse.tracecompass.incubator.inandout.core/src/org/eclipse/tracecompass/incubator/internal/inandout/core/analysis/SegmentSpecifierConfiguration.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2024 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +package org.eclipse.tracecompass.incubator.internal.inandout.core.analysis; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.incubator.internal.inandout.core.Activator; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * Model of Segment specifiers + */ +@NonNullByDefault +public class SegmentSpecifierConfiguration { + + /** Configuration source*/ + public static final String IN_AND_OUT_CONFIG_SOURCE_TYPE_ID = "org.eclipse.tracecompass.incubator.internal.inandout.core.config"; //$NON-NLS-1$ + + /** The configuration schema */ + public static final String IN_AND_OUT_CONFIG_SOURCE_SCHEMA= "schema/in-and-out-analysis.json"; //$NON-NLS-1$ + + + @Expose + @SerializedName(value = "specifiers") + private @Nullable List fSpecifiers; + + SegmentSpecifierConfiguration() { + fSpecifiers = Collections.emptyList(); + } + + /** + * Get the list of {@link SegmentSpecifier} + * + * @return List of {@link SegmentSpecifier} + */ + public @Nullable List getSpecifiers() { + return fSpecifiers; + } + + /** + * Converts custom JSON parameters to InAndOut specifiers + * + * @param parameters + * the custom parameters map + * @return a SegmenSpecifierConiguration instance + * @throws TmfConfigurationException + * if an error occurred + */ + public static SegmentSpecifierConfiguration fromJsonMap(Map parameters) throws TmfConfigurationException { + try { + String jsonParameters = new Gson().toJson(parameters, Map.class); + @SuppressWarnings("null") + SegmentSpecifierConfiguration config = new Gson().fromJson(jsonParameters, SegmentSpecifierConfiguration.class); + return config; + } catch (JsonSyntaxException e) { + Activator.getInstance().logError(e.getMessage(), e); + throw new TmfConfigurationException("Can't parse json. ", e); //$NON-NLS-1$ + } + } +} diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/services/DataProviderService.java b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/services/DataProviderService.java index 3c4dd333f..1a5bfe9f5 100644 --- a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/services/DataProviderService.java +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/services/DataProviderService.java @@ -205,6 +205,10 @@ @SuppressWarnings("restriction") @Path("/experiments/{expUUID}/outputs") public class DataProviderService { + + // InAndOut analysis ID + private static final String INANDOUT_ANALYSIS_ID = "org.eclipse.tracecompass.incubator.inandout.analysis"; //$NON-NLS-1$ + private static final @NonNull Logger LOGGER = TraceCompassLog.getLogger(DataProviderService.class); private final DataProviderManager manager = DataProviderManager.getInstance(); @@ -234,11 +238,18 @@ public Response getProviders(@Parameter(description = EXP_UUID) @PathParam("expU list.sort(Comparator.comparing(IDataProviderDescriptor::getName)); /* - * Bug 576402: - * Filter out all "Event Matching Analysis" related data providers, e.g. "Latency vs Time", - * because are part in every experiment but won't provide any data. + * Remove unwanted data providers: + * + * - Bug 576402: + * Filter out all "Event Matching Analysis" related data providers, e.g. "Latency vs Time", + * because are part in every experiment but won't provide any data. + * + * - Legacy InAndOut + * Remove default InAndOutAnalysis used in legacy Trace Compass with Eclipse UI + * For trace server, InAndOutAnlaysis is done using the createDataProvider endpoint below. */ - list.removeIf(dp -> dp.getId().endsWith(EventMatchingLatencyAnalysis.ID)); + list.removeIf(dp -> dp.getId().endsWith(EventMatchingLatencyAnalysis.ID) || dp.getId().endsWith(INANDOUT_ANALYSIS_ID)); + return Response.ok(list).build(); } diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.product/traceserver.product b/trace-server/org.eclipse.tracecompass.incubator.trace.server.product/traceserver.product index bbdfe2d82..4f84437c4 100644 --- a/trace-server/org.eclipse.tracecompass.incubator.trace.server.product/traceserver.product +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.product/traceserver.product @@ -180,6 +180,7 @@ Java and all Java-based trademarks are trademarks of Oracle Corporation in the U +