All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gridkit.jvmtool.AbstractEventDumpSource Maven / Gradle / Ivy

There is a newer version: 0.23
Show newest version
/**
 * Copyright 2017 Alexey Ragozin
 *
 * 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.
 */
package org.gridkit.jvmtool;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.TimeZone;

import org.gridkit.jvmtool.cli.CommandLauncher;
import org.gridkit.jvmtool.cmd.AntPathMatcher;
import org.gridkit.jvmtool.event.ChainedEventReader;
import org.gridkit.jvmtool.event.ErrorHandler;
import org.gridkit.jvmtool.event.Event;
import org.gridkit.jvmtool.event.EventDumpParser;
import org.gridkit.jvmtool.event.EventMorpher;
import org.gridkit.jvmtool.event.EventReader;
import org.gridkit.jvmtool.event.ShieldedEventReader;
import org.gridkit.jvmtool.event.SimpleErrorEvent;
import org.gridkit.jvmtool.event.SingleEventReader;
import org.gridkit.jvmtool.event.TimestampedEvent;
import org.gridkit.jvmtool.stacktrace.ThreadEventCodec;
import org.gridkit.jvmtool.stacktrace.analytics.TimeRangeChecker;

import com.beust.jcommander.Parameter;

public abstract class AbstractEventDumpSource {

    protected CommandLauncher host;

    @Parameter(names={"-tr", "--time-range"}, required = false, description="Time range filter")
    protected String timeRange = null;

    @Parameter(names={"--parsers-info"}, required = false, description="Print parsers available in classpath")
    protected boolean reportParsers = false;
    
    private boolean wildcardFileMatching = true;
    
    protected TimeZone timeZone;
    
    private List matchedInputFiles;
    
    public AbstractEventDumpSource(CommandLauncher host) {
        this.host = host;
    }
    
    public void setTimeZone(TimeZone tz) {
        this.timeZone = tz;
    }
    
    public void useWildcards(boolean enabled) {
    	wildcardFileMatching = enabled;
    }
    

    protected abstract List inputFiles();
    
    public List sourceFiles() {
    	if (matchedInputFiles == null) {

    		matchedInputFiles = new ArrayList();
    		
        	if (wildcardFileMatching) {
    	    	List rawInput = inputFiles();
    	
    		    AntPathMatcher matcher = new AntPathMatcher();
    		    matcher.setPathSeparator("/");
    		    
    			
    			for(String f: rawInput) {
    				f = f.replace('\\', '/');
    		        for(File ff: matcher.findFiles(new File("."), f)) {
    		            if (ff.isFile()) {
    		                matchedInputFiles.add(ff.getPath());
    		            }
    		        }
    			}
        	}
        	else {
        		matchedInputFiles.addAll(inputFiles());
        	}

    		if (matchedInputFiles.isEmpty()) {
                host.fail("No input files provided");
            }    		
    	}
    	return matchedInputFiles;
    }
    
    public EventReader getFilteredRawReader() {
    	if (timeRange != null) {
	        String[] lh = timeRange.split("[-]");
	        if (lh.length != 2) {
	            host.fail("Invalid time range '" + timeRange + "'", "Valid format yyyy.MM.dd_HH:mm:ss-yyyy.MM.dd_HH:mm:ss hours and higher parts can be ommited");
	        }
	        TimeRangeChecker checker = new TimeRangeChecker(lh[0], lh[1], timeZone);
	    	return getRawReader().morph(new TimeFilter(checker));
    	}
    	else {
    		return getRawReader();
    	}
    }
    
    public EventReader getRawReader() {

        final Iterator it = sourceFiles().iterator();
        ChainedEventReader reader = new ChainedEventReader() {

            @Override
            protected EventReader produceNext() {
                return it.hasNext() ? openReader(it.next()) : null;
            }
        };

        ShieldedEventReader shieldedReader = new ShieldedEventReader(reader, Event.class, new ErrorHandler() {
            @Override
            public boolean onException(Exception e) {
                System.err.println("Stream reader error: " + e);
                return true;
            }
        });


        return shieldedReader;
    }    
    
    protected EventReader openReader(String file) {
    	if (reportParsers) {
    		printParsers();
    	}
        try {
            return ThreadEventCodec.createEventReader(new FileInputStream(file));
        } catch (IOException e) {
        	EventReader reader = openGenericDump(file);
        	if (reader != null) {
        		return reader;
        	}
        	else {
        		return new SingleEventReader(new SimpleErrorEvent(e));
        	}
        }
    }
    
    private void printParsers() {
    	System.out.println("Available file parsers");
    	for(String parser: ThreadEventCodec.listSupportedFormats()) {
    		System.out.println(" - " + parser);
    	}
    	ServiceLoader loader = ServiceLoader.load(EventDumpParser.class);
		for(EventDumpParser edp: loader) {
			System.out.println(" - " + edp);
		}
	}

    private String getParserString() {
    	StringBuilder sb = new StringBuilder();
    	for(String parser: ThreadEventCodec.listSupportedFormats()) {
    		sb.append(parser).append(", ");
    	}
    	ServiceLoader loader = ServiceLoader.load(EventDumpParser.class);
		for(EventDumpParser edp: loader) {
			sb.append(edp).append(", ");
		}
		if (sb.length() > 0) {
			sb.setLength(sb.length() - 2);
		}
		return sb.toString();
	}

	protected EventReader openGenericDump(String file) {
		ServiceLoader loader = ServiceLoader.load(EventDumpParser.class);
		FileSource fs = new FileSource(file);
		for(EventDumpParser edp: loader) {
			try {
				EventReader r = edp.open(fs);
				if (r != null) {
					return r;
				}
			}
			catch(Exception e) {
				// ignore
			}
			catch(NoClassDefFoundError ee) {
				ee.printStackTrace();
				// ignore
			}
		}
		if (new File(file).isFile() && new File(file).length() > 0) {
			host.logError("Unable to parse file '" + file + "'. Parser config: " + getParserString());
		}
		return null;
    }
    
    static class TimeFilter implements EventMorpher {
        
        TimeRangeChecker checker;
        
        public TimeFilter(TimeRangeChecker checker) {
            this.checker = checker;
        }

        @Override
        public Event morph(Event event) {
        	if (event instanceof TimestampedEvent) {
        		return checker.evaluate(((TimestampedEvent)event).timestamp()) ? event : null;
        	}
        	else {
        		return null;
        	}
        }
    }
    
    private static class FileSource implements EventDumpParser.InputStreamSource {

    	final String file;
    	InputStream is;
    	
		public FileSource(String file) {
			this.file = file;
		}

		@Override
		public InputStream open() throws IOException {
			if (is != null) {
				try {
					is.close();
				} catch (Exception e) {
					// ignore
				}
			}
			return is = new FileInputStream(file);
		}
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy