Skip to content

Commit

Permalink
InAndOut Analysis using ITmfDataProviderConfigurator extension
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
bhufmann committed Nov 4, 2024
1 parent 4b30641 commit 426c2e4
Show file tree
Hide file tree
Showing 8 changed files with 604 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@
</tracetype>
</module>
</extension>
<extension
point="org.eclipse.tracecompass.tmf.core.dataprovider">
<dataProviderFactory
class="org.eclipse.tracecompass.incubator.internal.inandout.core.analysis.InAndOutDataProviderFactory"
id="org.eclipse.tracecompass.incubator.inandout.core.analysis.inAndOutdataProviderFactory">
</dataProviderFactory>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -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"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -50,23 +59,69 @@ 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.
*/
public static final SegmentSpecifier REFERENCE = new SegmentSpecifier("latency", "(\\S*)_entry", "(\\S*)_exit", "(\\S*)_entry", "(\\S*)_exit", "CPU"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$

@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()) {
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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<ITmfConfiguration> readConfigurations(@NonNull ITmfTrace trace) throws TmfConfigurationException {
IPath rootPath = getTraceRootFolder(trace, SegmentSpecifierConfiguration.IN_AND_OUT_CONFIG_SOURCE_TYPE_ID);
File folder = rootPath.toFile();
List<ITmfConfiguration> 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;
}

}
Loading

0 comments on commit 426c2e4

Please sign in to comment.