@@ -251,6 +251,78 @@ def list_experiments(args):
251251 print (f"{ exp .name } - { exp .UUID } " )
252252
253253
254+ def create_field_plots (args ):
255+ """Generate XML analysis for field plots and post it to the trace server."""
256+ import tempfile
257+ import os
258+
259+ client = TMLLClient (args .host , args .port , verbose = args .verbose )
260+
261+ # Parse the series spec: JSON dict of {series_name: [[event, field], ...]}
262+ series_spec = json .loads (args .series )
263+
264+ # Build XML: state provider stores fields under series_name/*,
265+ # xyView uses entry path="series_name/*" to plot all fields in that series.
266+ analysis_id = f"org.eclipse.tracecompass.tmll.field.{ args .analysis_name } "
267+ handlers = []
268+ xy_views = []
269+
270+ for series_name , event_fields in series_spec .items ():
271+ for event_name , field_name in event_fields :
272+ handlers .append (
273+ f' <eventHandler eventName="{ event_name } ">\n '
274+ f' <stateChange>\n '
275+ f' <stateAttribute type="constant" value="{ series_name } "/>\n '
276+ f' <stateAttribute type="constant" value="{ event_name } .{ field_name } "/>\n '
277+ f' <stateValue type="eventField" value="{ field_name } "/>\n '
278+ f' </stateChange>\n '
279+ f' </eventHandler>'
280+ )
281+ xy_views .append (
282+ f' <xyView id="{ analysis_id } .{ series_name } .xy">\n '
283+ f' <head>\n '
284+ f' <analysis id="{ analysis_id } "/>\n '
285+ f' <label value="{ series_name } "/>\n '
286+ f' </head>\n '
287+ f' <entry path="{ series_name } /*">\n '
288+ f' <display type="self"/>\n '
289+ f' </entry>\n '
290+ f' </xyView>'
291+ )
292+
293+ xml = (
294+ '<?xml version="1.0" encoding="UTF-8"?>\n '
295+ '<tmfxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n '
296+ ' xsi:noNamespaceSchemaLocation="xmlDefinition.xsd">\n '
297+ f' <stateProvider id="{ analysis_id } " version="1">\n '
298+ f' <head>\n '
299+ f' <label value="{ args .analysis_name } "/>\n '
300+ f' </head>\n '
301+ + '\n ' .join (handlers ) + '\n '
302+ f' </stateProvider>\n '
303+ + '\n ' .join (xy_views ) + '\n '
304+ '</tmfxml>\n '
305+ )
306+
307+ # Write to file and post (delete first for idempotency)
308+ xml_path = os .path .join (tempfile .gettempdir (), f"{ args .analysis_name } .xml" )
309+ with open (xml_path , 'w' ) as f :
310+ f .write (xml )
311+
312+ config_type = 'org.eclipse.tracecompass.tmf.core.config.xmlsourcetype'
313+ config_id = f"{ args .analysis_name } .xml"
314+ client .tsp_client .delete_configuration (config_type , config_id )
315+
316+ response = client .tsp_client .post_configuration (config_type , {'path' : xml_path })
317+
318+ if response .status_code == 200 :
319+ print (f"Posted analysis '{ args .analysis_name } ' (file: { xml_path } )" )
320+ print (f"Analysis ID: { analysis_id } " )
321+ print (f"XY View ID: { analysis_id } .xy" )
322+ else :
323+ print (f"Failed to post analysis: { response .status_code } { response .status_text } " )
324+
325+
254326def delete_experiment (args ):
255327 """Delete an experiment"""
256328 client = TMLLClient (args .host , args .port , verbose = args .verbose )
@@ -291,6 +363,12 @@ def main():
291363 fetch_parser .add_argument ("-o" , "--output" , help = "Output file prefix" )
292364 fetch_parser .set_defaults (func = fetch_data_cmd )
293365
366+ # create-field-plots command
367+ field_plots_parser = subparsers .add_parser ("create-field-plots" , help = "Generate and post XML analysis for field plots" )
368+ field_plots_parser .add_argument ("analysis_name" , help = "Unique name for the analysis" )
369+ field_plots_parser .add_argument ("series" , help = 'JSON: {"series_name": [["event", "field"], ...], ...}' )
370+ field_plots_parser .set_defaults (func = create_field_plots )
371+
294372 # delete command
295373 delete_parser = subparsers .add_parser ("delete" , help = "Delete an experiment" )
296374 delete_parser .add_argument ("experiment" , help = "Experiment UUID" )
0 commit comments