diff --git a/src/treetop/notebooks/server.py b/src/treetop/notebooks/server.py index 8a1ac58c59..20a0ba7f1b 100755 --- a/src/treetop/notebooks/server.py +++ b/src/treetop/notebooks/server.py @@ -146,7 +146,6 @@ class TreetopServer(): def __init__(self): self.client = None self.source = None - self.datasets = None self.timestamp = None self.timestamp_s = None self.start_time = None @@ -178,31 +177,17 @@ def __init__(self): def options(self): """ Setup default command line argument option handling """ opts = pmapi.pmOptions() - opts.pmSetShortOptions("a:h:D:V?A:S:T:O:s:t:Z:z") + opts.pmSetShortOptions("D:V?") opts.pmSetShortUsage("[option...]") - opts.pmSetLongOptionArchive() # -a/--archive - opts.pmSetLongOptionArchiveFolio() # --archive-folio - opts.pmSetLongOptionHost() # -h/--host opts.pmSetLongOptionDebug() # -D/--debug opts.pmSetLongOptionVersion() # -V/--version opts.pmSetLongOptionHelp() # -?/--help - opts.pmSetLongOptionAlign() # -A/--align - opts.pmSetLongOptionStart() # -S/--start - opts.pmSetLongOptionFinish() # -T/--finish - opts.pmSetLongOptionOrigin() # -O/--origin - opts.pmSetLongOptionSamples() # -s/--samples - opts.pmSetLongOptionInterval() # -t/--interval - opts.pmSetLongOptionTimeZone() # -Z/--timezone - opts.pmSetLongOptionHostZone() # -z/--hostzone return opts def configure(self): os.putenv('PCP_DERIVED_CONFIG', '') self.config = self.pmconfig.set_config_path([]) self.pmconfig.read_cmd_line() - self.datasets = self.opts.pmGetOptionArchives() - if not self.datasets: - raise pmapi.pmUsageErr("no dataset provided (-a/--archive)\n") def mapping(self): """ Helper which creates MMV instances, indoms, metrics @@ -561,6 +546,8 @@ def client_connect(self): mtype = MMV_TYPE_U32) self.sample_time = mmv.extend_item(top + 'timestamp', mtype = MMV_TYPE_FLOAT) + self.dataset = mmv.extend_item(top + 'archive', + mtype = MMV_TYPE_STRING) self.target = mmv.extend_item(top + 'target', mtype = MMV_TYPE_STRING) self.filter = mmv.extend_item(top + 'filter', @@ -575,7 +562,8 @@ def client_connect(self): def source_connect(self): try: - log = self.datasets[0] + self.client.fetch() # refresh value for which archive to use + log = self.dataset() # TODO- nuke ctx, src = pmapi.pmContext.set_connect_options(self.opts, log, None) self.pmfg = pmapi.fetchgroup(ctx, src) self.pmfg_ts = self.pmfg.extend_timestamp() @@ -621,7 +609,7 @@ def refresh(self): if not self.connect(): sys.stderr.write('Cannot refresh\n') return - print('Server refreshing') + print('Refreshing from', self.dataset()) # refresh information from the client self.client.fetch() reset = self.settings() diff --git a/src/treetop/pcp/TreeTop.c b/src/treetop/pcp/TreeTop.c index 24ff68ece3..1a464afbd2 100644 --- a/src/treetop/pcp/TreeTop.c +++ b/src/treetop/pcp/TreeTop.c @@ -46,17 +46,25 @@ in the source distribution for its full text. Platform* pcp; +/* command line options... */ +static const char* target = "disk.all.avactive"; +static const char* ignore = "disk.all.aveq,disk.all.read,disk.all.blkread,disk.all.read_bytes,disk.all.total,disk.all.blktotal,disk.all.total_bytes,disk.all.write,disk.all.blkwrite,disk.all.write_bytes"; +static size_t sample_count = 720; +static double sample_interval = 10; +static double training_interval = 1; + const ScreenDefaults Platform_defaultScreens[] = { { .name = "Model importance", .columns = "MODEL_FEATURE MODEL_IMPORTANCE MODEL_MUTUALINFO", - .sortKey = "MODEL_IMPORTANCE", + .sortKey = "MODEL_MUTUALINFO", }, { .name = "Sample importance", .columns = "LOCAL_FEATURE LOCAL_IMPORTANCE LOCAL_MUTUALINFO", - .sortKey = "LOCAL_IMPORTANCE", + .sortKey = "LOCAL_MUTUALINFO", }, { .name = "Optimum importance", .columns = "OPTIM_FEATURE OPTIM_MIN_MAX OPTIM_DIFFERENCE OPTIM_MUTUALINFO", + .sortKey = "OPTIM_MUTUALINFO", }, }; @@ -445,19 +453,64 @@ void Platform_getHostname(char* buffer, size_t size) { void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { printf( +" --target=METRICSPEC target performance metric [see pmParseMetricSpec(1)]\n" +" --filter=METRICSPECS comma-separated metric list, removed before training\n" +" --archive=FILE metrics source is PCP archive FILE [see PCPIntro(1)]\n" " --host=HOSTSPEC metrics source is PMCD at HOSTSPEC [see PCPIntro(1)]\n" +" --training-interval=N time delay (waited) between training evaluations\n" +" --sample-interval=N sample interval used within the training window\n" +" --samples=N number of samples used in training time window\n" " --hostzone set reporting timezone to local time of metrics source\n" " --timezone=TZ set reporting timezone\n"); } CommandLineStatus Platform_getLongOption(int opt, ATTR_UNUSED int argc, char** argv) { - /* libpcp export without a header definition */ + /* libpcp exports without any header definitions */ + extern void __pmAddOptArchive(pmOptions*, char*); extern void __pmAddOptHost(pmOptions*, char*); + char* endnum; switch (opt) { + case PLATFORM_LONGOPT_TARGET: /* --target=METRICSPEC */ + target = optarg; + return STATUS_OK; + + case PLATFORM_LONGOPT_IGNORE: /* --ignore=METRICSPECS */ + ignore = optarg; + return STATUS_OK; + + case PLATFORM_LONGOPT_ARCHIVE: /* --archive=FILE */ + __pmAddOptArchive(&opts, optarg); + return STATUS_OK; + + case PLATFORM_LONGOPT_SAMPLES: /* --samples=N */ + sample_count = (size_t)strtoull(optarg, &endnum, 10); + if (*endnum != '\0') { + pmprintf("%s: --%s requires a positive numeric argument\n", pmGetProgname(), PMLONGOPT_SAMPLES); + opts.errors++; + break; + } + return STATUS_OK; + + case PLATFORM_LONGOPT_SAMPLE_INTERVAL: /* --sample-interval=N */ + sample_interval = strtod(optarg, &endnum); + if (*endnum != '\0' || sample_interval <= 0) { + pmprintf("%s: --%s requires a positive floating point argument\n", pmGetProgname(), "--sample-interval"); + opts.errors++; + break; + } + return STATUS_OK; + + case PLATFORM_LONGOPT_TRAINING_INTERVAL: /* --training-interval=N */ + training_interval = strtod(optarg, &endnum); + if (*endnum != '\0' || training_interval <= 0) { + pmprintf("%s: --%s requires a positive floating point argument\n", pmGetProgname(), "--training-interval"); + opts.errors++; + break; + } + return STATUS_OK; + case PLATFORM_LONGOPT_HOST: /* --host=HOSTSPEC */ - if (argv[optind][0] == '\0') - return STATUS_ERROR_EXIT; __pmAddOptHost(&opts, optarg); return STATUS_OK; @@ -465,9 +518,9 @@ CommandLineStatus Platform_getLongOption(int opt, ATTR_UNUSED int argc, char** a if (opts.timezone) { pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname()); opts.errors++; - } else { - opts.tzflag = 1; + break; } + opts.tzflag = 1; return STATUS_OK; case PLATFORM_LONGOPT_TIMEZONE: /* --timezone=TZ */ @@ -476,9 +529,9 @@ CommandLineStatus Platform_getLongOption(int opt, ATTR_UNUSED int argc, char** a if (opts.tzflag) { pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname()); opts.errors++; - } else { - opts.timezone = optarg; + break; } + opts.timezone = optarg; return STATUS_OK; default: @@ -641,17 +694,26 @@ static mmv_metric2_t metrics[] = { .shorttext = "Current prediction timestamp (time since the epoch)", .helptext = "Prediction time string, training ends on prior sample", }, + { .name = "archive", + .item = 8, + .type = MMV_TYPE_STRING, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "Metrics source is a recorded archive", + .helptext = "Path to PCP archive from which to source metrics", + }, + { .name = "hostspec", + .item = 9, + .type = MMV_TYPE_STRING, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "Metrics source is host specification", + .helptext = "Host specification from which to source metrics", + }, }; static const char* file = "treetop.client"; -/* command line options... */ -static const char* target = "disk.all.avactive"; -static const char* notrain = "disk.all.aveq,disk.all.read,disk.all.blkread,disk.all.read_bytes,disk.all.total,disk.all.blktotal,disk.all.total_bytes,disk.all.write,disk.all.blkwrite,disk.all.write_bytes"; -static size_t sample_count = 720; -static double sample_interval = 10; -static double training_interval = 1; - static void* MMV_init(void) { // TODO: flags = MMV_FLAG_PROCESS (cull file at stop) --v mmv_registry_t* registry = mmv_stats_registry(file, 40, 0); @@ -681,8 +743,15 @@ void MMV_update(void* map, double timestamp) { size_t length; double sample_time = timestamp; time_t seconds = (int)timestamp; + char* hostspec = ""; + char* archive = ""; char buffer[64]; + if (opts.nhosts > 0) + hostspec = opts.hosts[0]; + if (opts.narchives > 0) + archive = opts.archives[0]; + timestamp -= seconds; timestamp *= 1000000; // usec component pmLocaltime(&seconds, &tms); @@ -691,8 +760,10 @@ void MMV_update(void* map, double timestamp) { snprintf(buffer+length, sizeof(buffer)-length, ".%d", (int)timestamp); mmv_stats_set_string(map, "target", "", target); - mmv_stats_set_string(map, "filter", "", notrain); + mmv_stats_set_string(map, "filter", "", ignore); mmv_stats_set_string(map, "timestamp_s", "", buffer); + mmv_stats_set_string(map, "archive", "", archive); + mmv_stats_set_string(map, "hostspec", "", hostspec); mmv_stats_set(map, "timestamp", "", sample_time); mmv_stats_set(map, "sampling.count", "", sample_count); diff --git a/src/treetop/pcp/TreeTop.h b/src/treetop/pcp/TreeTop.h index e750fee7e5..9c3a8b0566 100644 --- a/src/treetop/pcp/TreeTop.h +++ b/src/treetop/pcp/TreeTop.h @@ -110,15 +110,27 @@ void Platform_getHostname(char* buffer, size_t size); Table* Platform_getTable(const char* name); enum { - PLATFORM_LONGOPT_HOST = 128, + PLATFORM_LONGOPT_TARGET = 180, + PLATFORM_LONGOPT_IGNORE, + PLATFORM_LONGOPT_ARCHIVE, + PLATFORM_LONGOPT_SAMPLES, + PLATFORM_LONGOPT_SAMPLE_INTERVAL, + PLATFORM_LONGOPT_TRAINING_INTERVAL, + PLATFORM_LONGOPT_HOST, PLATFORM_LONGOPT_TIMEZONE, PLATFORM_LONGOPT_HOSTZONE, }; #define PLATFORM_LONG_OPTIONS \ - {PMLONGOPT_HOST, optional_argument, 0, PLATFORM_LONGOPT_HOST}, \ - {PMLONGOPT_TIMEZONE, optional_argument, 0, PLATFORM_LONGOPT_TIMEZONE}, \ - {PMLONGOPT_HOSTZONE, optional_argument, 0, PLATFORM_LONGOPT_HOSTZONE}, \ + {"target", required_argument, 0, PLATFORM_LONGOPT_TARGET}, \ + {"ignore", required_argument, 0, PLATFORM_LONGOPT_IGNORE}, \ + {PMLONGOPT_ARCHIVE, required_argument, 0, PLATFORM_LONGOPT_ARCHIVE}, \ + {PMLONGOPT_SAMPLES, required_argument, 0, PLATFORM_LONGOPT_SAMPLES}, \ + {"sample-interval", required_argument, 0, PLATFORM_LONGOPT_SAMPLE_INTERVAL}, \ + {"training-interval", required_argument, 0, PLATFORM_LONGOPT_TRAINING_INTERVAL}, \ + {PMLONGOPT_HOST, required_argument, 0, PLATFORM_LONGOPT_HOST}, \ + {PMLONGOPT_TIMEZONE, required_argument, 0, PLATFORM_LONGOPT_TIMEZONE}, \ + {PMLONGOPT_HOSTZONE, no_argument, 0, PLATFORM_LONGOPT_HOSTZONE}, \ void Platform_longOptionsUsage(const char* name);