Coverage Report - kg.apc.jmeter.reporters.LoadosophiaUploader
 
Classes in this File Line Coverage Branch Coverage Complexity
LoadosophiaUploader
74%
109/147
59%
19/32
2.304
 
 1  
 package kg.apc.jmeter.reporters;
 2  
 
 3  
 import kg.apc.jmeter.JMeterPluginsUtils;
 4  
 import org.apache.jmeter.reporters.ResultCollector;
 5  
 import org.apache.jmeter.samplers.SampleEvent;
 6  
 import org.apache.jmeter.samplers.SampleSaveConfiguration;
 7  
 import org.apache.jmeter.testelement.TestStateListener;
 8  
 import org.apache.jmeter.util.JMeterUtils;
 9  
 import org.apache.jorphan.logging.LoggingManager;
 10  
 import org.apache.log.Logger;
 11  
 import org.loadosophia.jmeter.LoadosophiaAPIClient;
 12  
 import org.loadosophia.jmeter.LoadosophiaUploadResults;
 13  
 import org.loadosophia.jmeter.StatusNotifierCallback;
 14  
 
 15  
 import java.io.File;
 16  
 import java.io.IOException;
 17  
 import java.lang.reflect.InvocationTargetException;
 18  
 import java.lang.reflect.Method;
 19  
 import java.util.concurrent.BlockingQueue;
 20  
 import java.util.concurrent.LinkedBlockingQueue;
 21  
 import java.util.concurrent.TimeUnit;
 22  
 
 23  
 public class LoadosophiaUploader extends ResultCollector implements StatusNotifierCallback, Runnable, TestStateListener {
 24  
 
 25  1
     private static final Logger log = LoggingManager.getLoggerForClass();
 26  
     public static final String TITLE = "title";
 27  
     public static final String COLOR = "color";
 28  
     public static final String UPLOAD_TOKEN = "uploadToken";
 29  
     public static final String PROJECT = "project";
 30  
     public static final String STORE_DIR = "storeDir";
 31  
     public static final String USE_ONLINE = "useOnline";
 32  
     private String fileName;
 33  1
     private static final Object LOCK = new Object();
 34  
     private boolean isSaving;
 35  25
     private LoadosophiaUploadingNotifier perfMonNotifier = LoadosophiaUploadingNotifier.getInstance();
 36  
     private String address;
 37  25
     private boolean isOnlineInitiated = false;
 38  
     private LoadosophiaAPIClient apiClient;
 39  
     private BlockingQueue<SampleEvent> processingQueue;
 40  
     private Thread processorThread;
 41  
     private LoadosophiaAggregator aggregator;
 42  
 
 43  
     public LoadosophiaUploader() {
 44  25
         super();
 45  25
         address = JMeterUtils.getPropDefault("loadosophia.address", "https://loadosophia.org/");
 46  25
     }
 47  
 
 48  
     @Override
 49  
     public void testStarted(String host) {
 50  4
         synchronized (LOCK) {
 51  4
             this.apiClient = getAPIClient();
 52  
 
 53  
             try {
 54  4
                 if (!isSaving) {
 55  4
                     isSaving = true;
 56  4
                     setupSaving();
 57  
                 }
 58  0
             } catch (IOException ex) {
 59  0
                 log.error("Error setting up saving", ex);
 60  4
             }
 61  
 
 62  4
             initiateOnline();
 63  4
         }
 64  4
         super.testStarted(host);
 65  4
         perfMonNotifier.startCollecting();
 66  4
     }
 67  
 
 68  
     @Override
 69  
     public void testEnded(String host) {
 70  3
         super.testEnded(host);
 71  3
         synchronized (LOCK) {
 72  
             // FIXME: trying to handle safe upgrade, needs to be removed in the future
 73  
             // @see https://issues.apache.org/bugzilla/show_bug.cgi?id=56807
 74  
             try {
 75  3
                 Class<ResultCollector> c = ResultCollector.class;
 76  3
                 Method m = c.getDeclaredMethod("flushFile");
 77  3
                 m.invoke(this);
 78  3
                 log.info("Successfully flushed results file");
 79  0
             } catch (NoSuchMethodException ex) {
 80  0
                 log.warn("Cannot flush results file since you are using old version of JMeter, consider upgrading to latest. Currently the results may be incomplete.");
 81  0
             } catch (InvocationTargetException e) {
 82  0
                 log.error("Failed to flush file", e);
 83  0
             } catch (IllegalAccessException e) {
 84  0
                 log.error("Failed to flush file", e);
 85  3
             }
 86  
 
 87  3
             if (isOnlineInitiated) {
 88  1
                 finishOnline();
 89  
             }
 90  
 
 91  
             try {
 92  3
                 if (fileName == null) {
 93  0
                     throw new IOException("File for upload was not set, search for errors above in log");
 94  
                 }
 95  
 
 96  3
                 isSaving = false;
 97  3
                 LoadosophiaUploadResults uploadResult = this.apiClient.sendFiles(new File(fileName), perfMonNotifier.getFiles());
 98  3
                 informUser("Uploaded successfully, go to results: " + uploadResult.getRedirectLink());
 99  0
             } catch (IOException ex) {
 100  0
                 informUser("Failed to upload results to Loadosophia.org, see log for detais");
 101  0
                 log.error("Failed to upload results to loadosophia", ex);
 102  3
             }
 103  3
         }
 104  3
         clearData();
 105  3
         perfMonNotifier.endCollecting();
 106  3
     }
 107  
 
 108  
     private void setupSaving() throws IOException {
 109  4
         String dir = getStoreDir();
 110  
         File tmpFile;
 111  
         try {
 112  4
             File storeDir = null;
 113  4
             if (dir != null && !dir.trim().isEmpty()) {
 114  3
                 storeDir = new File(dir);
 115  
             }
 116  4
             tmpFile = File.createTempFile("Loadosophia_", ".jtl", storeDir);
 117  0
         } catch (IOException ex) {
 118  0
             informUser("Unable to create temp file: " + ex.getMessage());
 119  0
             informUser("Try to set another directory in the above field.");
 120  0
             throw ex;
 121  4
         }
 122  
 
 123  4
         fileName = tmpFile.getAbsolutePath();
 124  4
         tmpFile.delete(); // IMPORTANT! this is required to have CSV headers
 125  4
         informUser("Storing results for upload to Loadosophia.org: " + fileName);
 126  4
         setFilename(fileName);
 127  
         // OMG, I spent 2 days finding that setting properties in testStarted
 128  
         // marks them temporary, though they cleared in some places.
 129  
         // So we do dirty(?) hack here...
 130  4
         clearTemporary(getProperty(FILENAME));
 131  
 
 132  4
         SampleSaveConfiguration conf = getSaveConfig();
 133  4
         JMeterPluginsUtils.doBestCSVSetup(conf);
 134  
 
 135  4
         setSaveConfig(conf);
 136  4
     }
 137  
 
 138  
     public void setProject(String proj) {
 139  5
         setProperty(PROJECT, proj);
 140  5
     }
 141  
 
 142  
     public String getProject() {
 143  4
         return getPropertyAsString(PROJECT);
 144  
     }
 145  
 
 146  
     public void setUploadToken(String token) {
 147  5
         setProperty(UPLOAD_TOKEN, token);
 148  5
     }
 149  
 
 150  
     public String getUploadToken() {
 151  4
         return getPropertyAsString(UPLOAD_TOKEN);
 152  
     }
 153  
 
 154  
     public void setTitle(String prefix) {
 155  7
         setProperty(TITLE, prefix);
 156  7
     }
 157  
 
 158  
     public String getTitle() {
 159  5
         return getPropertyAsString(TITLE);
 160  
     }
 161  
 
 162  
     private void informUser(String string) {
 163  20
         log.info(string);
 164  20
         if (getVisualizer() != null && getVisualizer() instanceof LoadosophiaUploaderGui) {
 165  0
             ((LoadosophiaUploaderGui) getVisualizer()).inform(string);
 166  
         } else {
 167  20
             log.info(string);
 168  
         }
 169  20
     }
 170  
 
 171  
     public String getStoreDir() {
 172  6
         return getPropertyAsString(STORE_DIR);
 173  
     }
 174  
 
 175  
     public void setStoreDir(String prefix) {
 176  7
         setProperty(STORE_DIR, prefix);
 177  7
     }
 178  
 
 179  
     public void setColorFlag(String color) {
 180  5
         setProperty(COLOR, color);
 181  5
     }
 182  
 
 183  
     public String getColorFlag() {
 184  4
         return getPropertyAsString(COLOR);
 185  
     }
 186  
 
 187  
     protected LoadosophiaAPIClient getAPIClient() {
 188  2
         return new LoadosophiaAPIClient(this, address, getUploadToken(), getProject(), getColorFlag(), getTitle());
 189  
     }
 190  
 
 191  
     @Override
 192  
     public void notifyAbout(String info) {
 193  12
         informUser(info);
 194  12
     }
 195  
 
 196  
     public boolean isUseOnline() {
 197  6
         return getPropertyAsBoolean(USE_ONLINE);
 198  
     }
 199  
 
 200  
     public void setUseOnline(boolean selected) {
 201  4
         setProperty(USE_ONLINE, selected);
 202  4
     }
 203  
 
 204  
     @Override
 205  
     public void sampleOccurred(SampleEvent event) {
 206  103
         super.sampleOccurred(event);
 207  103
         if (isOnlineInitiated) {
 208  
             try {
 209  100
                 if (!processingQueue.offer(event, 1, TimeUnit.SECONDS)) {
 210  0
                     log.warn("Failed first dequeue insert try, retrying");
 211  0
                     if (!processingQueue.offer(event, 1, TimeUnit.SECONDS)) {
 212  0
                         log.error("Failed second try to inser into deque, dropped sample");
 213  
                     }
 214  
                 }
 215  0
             } catch (InterruptedException ex) {
 216  0
                 log.info("Interrupted while putting sample event into deque", ex);
 217  100
             }
 218  
         }
 219  103
     }
 220  
 
 221  
     @Override
 222  
     public void run() {
 223  102
         while (isOnlineInitiated) {
 224  
             try {
 225  101
                 SampleEvent event = processingQueue.poll(1, TimeUnit.SECONDS);
 226  100
                 if (event != null) {
 227  100
                     aggregator.addSample(event.getResult());
 228  
                 }
 229  
 
 230  100
                 if (aggregator.haveDataToSend()) {
 231  
                     try {
 232  0
                         apiClient.sendOnlineData(aggregator.getDataToSend());
 233  0
                     } catch (IOException ex) {
 234  0
                         log.warn("Failed to send active test data", ex);
 235  0
                     }
 236  
                 }
 237  1
             } catch (InterruptedException ex) {
 238  1
                 log.debug("Interrupted while taking sample event from deque", ex);
 239  1
                 break;
 240  100
             }
 241  
         }
 242  2
     }
 243  
 
 244  
     private void initiateOnline() {
 245  4
         if (isUseOnline()) {
 246  
             try {
 247  1
                 log.info("Starting Loadosophia online test");
 248  1
                 informUser("Started active test: " + apiClient.startOnline());
 249  1
                 aggregator = new LoadosophiaAggregator();
 250  1
                 processingQueue = new LinkedBlockingQueue<SampleEvent>();
 251  1
                 processorThread = new Thread(this);
 252  1
                 processorThread.setDaemon(true);
 253  1
                 isOnlineInitiated = true;
 254  1
                 processorThread.start();
 255  0
             } catch (IOException ex) {
 256  0
                 informUser("Failed to start active test");
 257  0
                 log.warn("Failed to initiate active test", ex);
 258  0
                 this.isOnlineInitiated = false;
 259  1
             }
 260  
         }
 261  4
     }
 262  
 
 263  
     private void finishOnline() {
 264  1
         isOnlineInitiated = false;
 265  1
         processorThread.interrupt();
 266  1
         while (processorThread.isAlive() && !processorThread.isInterrupted()) {
 267  0
             log.info("Waiting for aggregator thread to stop...");
 268  
             try {
 269  0
                 Thread.sleep(50);
 270  0
                 processorThread.interrupt();
 271  0
             } catch (InterruptedException ex) {
 272  0
                 log.warn("Interrupted sleep", ex);
 273  0
             }
 274  
         }
 275  1
         log.info("Ending Loadosophia online test");
 276  
         try {
 277  1
             apiClient.endOnline();
 278  0
         } catch (IOException ex) {
 279  0
             log.warn("Failed to finalize active test", ex);
 280  1
         }
 281  1
     }
 282  
 }