mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-30 22:54:18 +00:00 
			
		
		
		
	wa: Rename Instrumentation to Instruments
				
					
				
			To be maintain a consistent naming scheme, rename all instances of `Instrumentation` to `Instruments`
This commit is contained in:
		
							
								
								
									
										17
									
								
								wa/instruments/poller/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								wa/instruments/poller/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # CROSS_COMPILE=aarch64-linux-gnu- make | ||||
| # | ||||
| CC=gcc | ||||
|  | ||||
| ifdef DEBUG | ||||
| 	CFLAGS=-static -lc -g | ||||
| else | ||||
| 	CFLAGS=-static -lc -O2 | ||||
| endif | ||||
|  | ||||
| poller: poller.c | ||||
| 	$(CROSS_COMPILE)$(CC) $(CFLAGS) poller.c -o poller | ||||
|  | ||||
| clean: | ||||
| 	rm -rf poller | ||||
|  | ||||
| .PHONY: clean | ||||
							
								
								
									
										122
									
								
								wa/instruments/poller/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								wa/instruments/poller/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| #    Copyright 2015 ARM Limited | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| # pylint: disable=access-member-before-definition,attribute-defined-outside-init,unused-argument | ||||
| import os | ||||
|  | ||||
| from wa import Instrument, Parameter, Executable | ||||
| from wa.framework.exception import ConfigError, InstrumentError | ||||
| from wa.utils.types import list_or_string | ||||
|  | ||||
|  | ||||
| class FilePoller(Instrument): | ||||
|     name = 'file_poller' | ||||
|     description = """ | ||||
|     Polls the given files at a set sample interval. The values are output in CSV format. | ||||
|  | ||||
|     This instrument places a file called poller.csv in each iterations result directory. | ||||
|     This file will contain a timestamp column which will be in uS, the rest of the columns | ||||
|     will be the contents of the polled files at that time. | ||||
|  | ||||
|     This instrument will strip any commas or new lines for the files' values | ||||
|     before writing them. | ||||
|     """ | ||||
|  | ||||
|     parameters = [ | ||||
|         Parameter('sample_interval', kind=int, default=1000, | ||||
|                   description="""The interval between samples in mS."""), | ||||
|         Parameter('files', kind=list_or_string, mandatory=True, | ||||
|                   description="""A list of paths to the files to be polled"""), | ||||
|         Parameter('labels', kind=list_or_string, | ||||
|                   description="""A list of lables to be used in the CSV output for | ||||
|                                  the corresponding files. This cannot be used if | ||||
|                                  a `*` wildcard is used in a path."""), | ||||
|         Parameter('as_root', kind=bool, default=False, | ||||
|                   description=""" | ||||
|                   Whether or not the poller will be run as root. This should be | ||||
|                   used when the file you need to poll can only be accessed by root. | ||||
|                   """), | ||||
|     ] | ||||
|  | ||||
|     def validate(self): | ||||
|         if not self.files: | ||||
|             raise ConfigError('You must specify atleast one file to poll') | ||||
|         if self.labels and any(['*' in f for f in self.files]): | ||||
|             raise ConfigError('You cannot used manual labels with `*` wildcards') | ||||
|  | ||||
|     def initialize(self, context): | ||||
|         if not self.target.is_rooted and self.as_root: | ||||
|             raise ConfigError('The target is not rooted, cannot run poller as root.') | ||||
|         host_poller = context.resolver.get(Executable(self, self.target.abi, | ||||
|                                                       "poller")) | ||||
|         target_poller = self.target.install(host_poller) | ||||
|  | ||||
|         expanded_paths = [] | ||||
|         for path in self.files: | ||||
|             if "*" in path: | ||||
|                 for p in self.target.list_directory(path): | ||||
|                     expanded_paths.append(p) | ||||
|             else: | ||||
|                 expanded_paths.append(path) | ||||
|         self.files = expanded_paths | ||||
|         if not self.labels: | ||||
|             self.labels = self._generate_labels() | ||||
|  | ||||
|         self.target_output_path = self.target.path.join(self.target.working_directory, 'poller.csv') | ||||
|         self.target_log_path = self.target.path.join(self.target.working_directory, 'poller.log') | ||||
|         self.command = '{} -t {} -l {} {} > {} 2>{}'.format(target_poller, | ||||
|                                                             self.sample_interval * 1000, | ||||
|                                                             ','.join(self.labels), | ||||
|                                                             ' '.join(self.files), | ||||
|                                                             self.target_output_path, | ||||
|                                                             self.target_log_path) | ||||
|  | ||||
|     def start(self, context): | ||||
|         self.target.kick_off(self.command, as_root=self.as_root) | ||||
|  | ||||
|     def stop(self, context): | ||||
|         self.target.killall('poller', signal='TERM', as_root=self.as_root) | ||||
|  | ||||
|     def update_output(self, context): | ||||
|         host_output_file = os.path.join(context.output_directory, 'poller.csv') | ||||
|         self.target.pull(self.target_output_path, host_output_file) | ||||
|         context.add_artifact('poller_output', host_output_file, kind='data') | ||||
|         host_log_file = os.path.join(context.output_directory, 'poller.log') | ||||
|         self.target.pull(self.target_log_path, host_log_file) | ||||
|         context.add_artifact('poller_log', host_log_file, kind='log') | ||||
|  | ||||
|         with open(host_log_file) as fh: | ||||
|             for line in fh: | ||||
|                 if 'ERROR' in line: | ||||
|                     raise InstrumentError(line.strip()) | ||||
|                 if 'WARNING' in line: | ||||
|                     self.logger.warning(line.strip()) | ||||
|  | ||||
|     def teardown(self, context): | ||||
|         self.target.remove(self.target_output_path) | ||||
|         self.target.remove(self.target_log_path) | ||||
|  | ||||
|     def _generate_labels(self): | ||||
|         # Split paths into their parts | ||||
|         path_parts = [f.split(self.target.path.sep) for f in self.files] | ||||
|         # Identify which parts differ between at least two of the paths | ||||
|         differ_map = [len(set(x)) > 1 for x in zip(*path_parts)] | ||||
|  | ||||
|         # compose labels from path parts that differ | ||||
|         labels = [] | ||||
|         for pp in path_parts: | ||||
|             label_parts = [p for i, p in enumerate(pp[:-1]) | ||||
|                            if i >= len(differ_map) or differ_map[i]] | ||||
|             label_parts.append(pp[-1])  # always use file name even if same for all | ||||
|             labels.append('-'.join(label_parts)) | ||||
|         return labels | ||||
							
								
								
									
										
											BIN
										
									
								
								wa/instruments/poller/bin/arm64/poller
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								wa/instruments/poller/bin/arm64/poller
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								wa/instruments/poller/bin/armeabi/poller
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								wa/instruments/poller/bin/armeabi/poller
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										163
									
								
								wa/instruments/poller/poller.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								wa/instruments/poller/poller.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/poll.h> | ||||
| #include <sys/time.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
| #include <signal.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| volatile sig_atomic_t done = 0; | ||||
| void term(int signum) | ||||
| { | ||||
|     done = 1; | ||||
| } | ||||
|  | ||||
| void strip(char *s) { | ||||
|     char *stripped_s = s; | ||||
|     while(*s != '\0') { | ||||
|         if(*s != ',' && *s != '\n') { | ||||
|             *stripped_s++ = *s++; | ||||
|         } else { | ||||
|             ++s; | ||||
|         } | ||||
|     } | ||||
|     *stripped_s = '\0'; | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|         int fd; | ||||
|         char *path; | ||||
| } poll_source_t; | ||||
|  | ||||
| int main(int argc, char ** argv) { | ||||
|  | ||||
|     extern char *optarg; | ||||
|     extern int optind; | ||||
|     int c = 0; | ||||
|     int show_help = 0; | ||||
|     useconds_t interval = 1000000; | ||||
|     char buf[1024]; | ||||
|     memset(buf, 0, sizeof(buf)); | ||||
|     struct timeval current_time; | ||||
|     double time_float; | ||||
|     char *labels; | ||||
|     int labelCount = 0; | ||||
|  | ||||
|     static char usage[] = "usage: %s [-h] [-t INTERVAL] FILE [FILE ...]\n" | ||||
|                           "polls FILE(s) every INTERVAL microseconds and outputs\n" | ||||
|                           "the results in CSV format including a timestamp to STDOUT\n" | ||||
|                           "\n" | ||||
|                           "    -h     Display this message\n" | ||||
|                           "    -t     The polling sample interval in microseconds\n" | ||||
|                           "           Defaults to 1000000 (1 second)\n" | ||||
|                           "    -l     Comma separated list of labels to use in the CSV\n" | ||||
|                           "           output. This should match the number of files\n"; | ||||
|  | ||||
|  | ||||
|     //Handling command line arguments | ||||
|     while ((c = getopt(argc, argv, "ht:l:")) != -1) | ||||
|     { | ||||
|         switch(c) { | ||||
|             case 'h': | ||||
|             case '?': | ||||
|             default: | ||||
|                 show_help = 1; | ||||
|                 break; | ||||
|             case 't': | ||||
|                 interval = (useconds_t)atoi(optarg); | ||||
|                 break; | ||||
|             case 'l': | ||||
|                 labels = optarg; | ||||
|                 labelCount = 1; | ||||
|                 int i; | ||||
|                 for (i=0; labels[i]; i++) | ||||
|                     labelCount += (labels[i] == ','); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (show_help) { | ||||
|         fprintf(stderr, usage, argv[0]); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     if (optind >= argc) { | ||||
|         fprintf(stderr, "ERROR: %s: missing file path(s)\n", argv[0]); | ||||
|         fprintf(stderr, usage, argv[0]); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     int num_files = argc - optind; | ||||
|     poll_source_t files_to_poll[num_files]; | ||||
|  | ||||
|     if (labelCount && labelCount != num_files) | ||||
|     { | ||||
|         fprintf(stderr, "ERROR: %s: %d labels specified but %d files specified\n", | ||||
|                 argv[0], labelCount, num_files); | ||||
|         fprintf(stderr, usage, argv[0]); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     //Print headers and open files to poll | ||||
|     printf("time"); | ||||
|     if(labelCount) | ||||
|     { | ||||
|         printf(",%s", labels); | ||||
|     } | ||||
|     int i; | ||||
|     for (i = 0; i < num_files; i++) | ||||
|     { | ||||
|         files_to_poll[i].path = argv[optind + i]; | ||||
|         files_to_poll[i].fd = open(files_to_poll[i].path, O_RDONLY); | ||||
|         if (files_to_poll[i].fd == -1) { | ||||
|             fprintf(stderr, "ERROR: Could not open \"%s\", got: %s\n", | ||||
|                     files_to_poll[i].path, strerror(errno)); | ||||
|             exit(2); | ||||
|         } | ||||
|  | ||||
|         if(!labelCount) { | ||||
|             printf(",%s", argv[optind + i]); | ||||
|         } | ||||
|     } | ||||
|     printf("\n"); | ||||
|  | ||||
|     //Setup SIGTERM handler | ||||
|     struct sigaction action; | ||||
|     memset(&action, 0, sizeof(struct sigaction)); | ||||
|     action.sa_handler = term; | ||||
|     sigaction(SIGTERM, &action, NULL); | ||||
|  | ||||
|     //Poll files  | ||||
|     int bytes_read = 0; | ||||
|     while (!done) { | ||||
|         gettimeofday(¤t_time, NULL); | ||||
|         time_float = (double)current_time.tv_sec; | ||||
|         time_float += ((double)current_time.tv_usec)/1000/1000; | ||||
|         printf("%f", time_float); | ||||
|         for (i = 0; i < num_files; i++) { | ||||
|             lseek(files_to_poll[i].fd, 0, SEEK_SET); | ||||
|             bytes_read = read(files_to_poll[i].fd, buf, 1024); | ||||
|  | ||||
|             if (bytes_read < 0) { | ||||
|                 fprintf(stderr, "WARNING: Read nothing from \"%s\"\n", | ||||
|                         files_to_poll[i].path); | ||||
|                 printf(","); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             strip(buf); | ||||
|             printf(",%s", buf); | ||||
|             buf[0] = '\0'; // "Empty" buffer | ||||
|         } | ||||
|         printf("\n"); | ||||
|         usleep(interval); | ||||
|     } | ||||
|  | ||||
|     //Close files | ||||
|     for (i = 0; i < num_files; i++) | ||||
|     { | ||||
|         close(files_to_poll[i].fd); | ||||
|     } | ||||
|     exit(0); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user