source: trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/web/WeblogParser.java @ 203

Last change on this file since 203 was 203, checked in by sherbold, 13 years ago
  • Changed data type for handling of sequence-sets. Before, List<List<Event<?>>> was used, now Collection<List<Event<?>>> is used.
  • Property svn:mime-type set to text/plain
File size: 7.5 KB
Line 
1package de.ugoe.cs.eventbench.web;
2
3import java.io.FileNotFoundException;
4import java.io.IOException;
5import java.net.URI;
6import java.net.URISyntaxException;
7import java.text.ParseException;
8import java.text.SimpleDateFormat;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.HashMap;
12import java.util.LinkedList;
13import java.util.List;
14import java.util.Map;
15
16import de.ugoe.cs.eventbench.web.data.WebEvent;
17import de.ugoe.cs.util.FileTools;
18import de.ugoe.cs.util.console.Console;
19
20/**
21 * <p>
22 * Provides functionality to parse log files with web request.
23 * </p>
24 *
25 * @author Steffen Herbold
26 * @version 1.0
27 */
28public class WeblogParser {
29
30        /**
31         * <p>
32         * Timeout between two sessions in milliseconds.
33         * </p>
34         */
35        private long timeout;
36
37        /**
38         * <p>
39         * Minimal length of a session. All shorter sessions will be pruned.
40         * Default: 2
41         * </p>
42         */
43        private int minLength = 2;
44
45        /**
46         * <p>
47         * Collection of generated sequences.
48         * </p>
49         */
50        private List<List<WebEvent>> sequences;
51
52        /**
53         * <p>
54         * Name and path of the robot filter.
55         * </p>
56         */
57        private static final String ROBOTFILTERFILE = "misc/robotfilter.txt";
58
59        /**
60         * <p>
61         * Field that contains a regular expression that matches all robots
62         * contained in {@link #ROBOTFILTERFILE}.
63         * </p>
64         */
65        private String robotRegex = null;
66
67        /**
68         * <p>
69         * Constructor. Creates a new WeblogParser with a default timeout of
70         * 3,600,000 milliseconds (1 hour).
71         * </p>
72         */
73        public WeblogParser() {
74                this(3600000);
75        }
76
77        /**
78         * <p>
79         * Constructor. Creates a new WeblogParser.
80         * </p>
81         *
82         * @param timeout
83         *            session timeout
84         */
85        public WeblogParser(long timeout) {
86                this.timeout = timeout;
87        }
88
89        /**
90         * <p>
91         * Returns the generated event sequences.
92         * </p>
93         *
94         * @return generated event sequences
95         */
96        public Collection<List<WebEvent>> getSequences() {
97                return sequences;
98        }
99
100        /**
101         * <p>
102         * Sets the session timeout.
103         * </p>
104         *
105         * @param timeout
106         *            new session timeout
107         */
108        public void setTimeout(long timeout) {
109                this.timeout = timeout;
110        }
111
112        /**
113         * <p>
114         * Sets the minimal length of a session. All sessions that contain less
115         * events will be pruned.
116         * </p>
117         *
118         * @param minLength
119         *            new minimal length
120         */
121        public void setMinLength(int minLength) {
122                this.minLength = minLength;
123        }
124
125        /**
126         * <p>
127         * Parses a web log file.
128         * </p>
129         *
130         * @param filename
131         *            name and path of the log file
132         * @throws IOException
133         *             thrown if there is a problem with reading the log file
134         * @throws FileNotFoundException
135         *             thrown if the log file is not found
136         * @throws ParseException
137         *             thrown the date format is invalid
138         */
139        public void parseFile(String filename) throws IOException,
140                        FileNotFoundException, ParseException {
141                String[] lines = FileTools.getLinesFromFile(filename);
142
143                Map<String, List<Integer>> cookieSessionMap = new HashMap<String, List<Integer>>();
144                int lastId = -1;
145
146                SimpleDateFormat dateFormat = new SimpleDateFormat(
147                                "yyyy-MM-dd HH:mm:ss");
148                loadRobotRegex();
149
150                sequences = new ArrayList<List<WebEvent>>();
151
152                int lineCounter = 0;
153                for (String line : lines) {
154                        lineCounter++;
155                        String[] values = line.substring(1, line.length() - 1).split(
156                                        "\" \"");
157
158                        // use cookie as session identifier
159                        int cookieStart = values[0].lastIndexOf('.');
160                        String cookie = values[0].substring(cookieStart + 1);
161                        String dateString = values[1];
162                        long timestamp = dateFormat.parse(dateString).getTime();
163                        String uriString = values[2];
164                        // String ref = values[3]; // referer is not yet used!
165                        String agent;
166                        if (values.length > 4) {
167                                agent = values[4];
168                        } else {
169                                agent = "noagent";
170                        }
171
172                        List<String> postedVars = new ArrayList<String>();
173                        if (values.length == 6) { // post vars found
174                                for (String postVar : values[5].trim().split(" ")) {
175                                        postedVars.add(postVar);
176                                }
177                        }
178                        if (!isRobot(agent)) {
179                                try {
180                                        URI uri = new URI(uriString);
181                                        String path = uri.getPath();
182                                        List<String> getVars = extractGetVarsFromUri(uri);
183       
184                                        WebEvent event = new WebEvent(path, timestamp, postedVars,
185                                                        getVars);
186       
187                                        // find session and add event
188                                        List<Integer> sessionIds = cookieSessionMap.get(cookie);
189                                        if (sessionIds == null) {
190                                                sessionIds = new ArrayList<Integer>();
191                                                // start new session
192                                                sessionIds.add(++lastId);
193                                                cookieSessionMap.put(cookie, sessionIds);
194                                                sequences.add(new LinkedList<WebEvent>());
195                                        }
196                                        Integer lastSessionIndex = sessionIds
197                                                        .get(sessionIds.size() - 1);
198                                        List<WebEvent> lastSession = sequences.get(lastSessionIndex);
199                                        long lastEventTime = timestamp;
200                                        if (!lastSession.isEmpty()) {
201                                                lastEventTime = lastSession.get(lastSession.size() - 1)
202                                                                .getTimestamp();
203                                        }
204                                        if (timestamp - lastEventTime > timeout) {
205                                                sessionIds.add(++lastId);
206                                                List<WebEvent> newSession = new LinkedList<WebEvent>();
207                                                newSession.add(event);
208                                                sequences.add(newSession);
209                                        } else {
210                                                lastSession.add(event);
211                                        }
212                                } catch (URISyntaxException e) {
213                                        Console.traceln("Ignored line " + lineCounter + ": " + e.getMessage());
214                                }
215                        }
216                }
217                pruneShortSequences();
218        }
219
220        /**
221         * <p>
222         * Prunes sequences shorter than {@link #minLength}.
223         * </p>
224         */
225        private void pruneShortSequences() {
226                Console.traceln("" + sequences.size() + " user sequences found");
227                // prune sequences shorter than min-length
228                int i = 0;
229                while (i < sequences.size()) {
230                        if (sequences.get(i).size() < minLength) {
231                                sequences.remove(i);
232                        } else {
233                                i++;
234                        }
235                }
236                Console.traceln("" + sequences.size()
237                                + " remaining after pruning of sequences shorter than "
238                                + minLength);
239        }
240
241        /**
242         * <p>
243         * Reads {@link #ROBOTFILTERFILE} and creates a regular expression that
244         * matches all the robots defined in the file. The regular expression is
245         * stored in the field {@link #robotRegex}.
246         * </p>
247         *
248         * @throws IOException
249         *             thrown if there is a problem reading the robot filter
250         * @throws FileNotFoundException
251         *             thrown if the robot filter is not found
252         */
253        private void loadRobotRegex() throws IOException, FileNotFoundException {
254                String[] lines = FileTools.getLinesFromFile(ROBOTFILTERFILE);
255                StringBuilder regex = new StringBuilder();
256                for (int i = 0; i < lines.length; i++) {
257                        regex.append("(.*" + lines[i] + ".*)");
258                        if (i != lines.length - 1) {
259                                regex.append('|');
260                        }
261                }
262                robotRegex = regex.toString();
263        }
264
265        /**
266         * <p>
267         * Checks whether an agent is a robot.
268         * </p>
269         *
270         * @param agent
271         *            agent that is checked
272         * @return true, if the agent is a robot; false otherwise
273         */
274        private boolean isRobot(String agent) {
275                return agent.matches(robotRegex);
276        }
277
278        /**
279         * <p>
280         * Parses the URI and extracts the GET variables that have been passed.
281         * </p>
282         *
283         * @param uri
284         *            URI that is parsed
285         * @return a list with all GET variables
286         */
287        private List<String> extractGetVarsFromUri(URI uri) {
288                List<String> getVars = new ArrayList<String>();
289                String query = uri.getQuery();
290                if (query != null) {
291                        String[] paramPairs = query.split("&");
292                        for (String paramPair : paramPairs) {
293                                String[] paramSplit = paramPair.split("=");
294                                getVars.add(paramSplit[0]);
295                        }
296                }
297                return getVars;
298        }
299}
Note: See TracBrowser for help on using the repository browser.