Isolate the functions for executing shell commands in a new ShellUtils
[lttng-ust-java-tests.git] / src / test / java / org / lttng / ust / agent / utils / LttngSession.java
1 /*
2 * Copyright (C) 2015, EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 package org.lttng.ust.agent.utils;
20
21 import static org.lttng.ust.agent.utils.ShellUtils.executeCommand;
22
23 import java.io.IOException;
24 import java.nio.file.FileVisitResult;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.nio.file.SimpleFileVisitor;
29 import java.nio.file.attribute.BasicFileAttributes;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.UUID;
33 import java.util.stream.Collectors;
34
35 /**
36 * Java representation of a LTTng tracing session. It uses the command-line
37 * "lttng" tool to manipulate the session. Creating an instance will run
38 * "lttng create", close()'ing it will run "lttng destroy".
39 *
40 * @author Alexandre Montplaisir
41 */
42 public class LttngSession implements AutoCloseable {
43
44 /**
45 * Tracing domains as they are defined by lttng-tools
46 */
47 public enum Domain {
48 /** The JUL (java.util.logging) domain */
49 JUL("-j"), /** The log4j (org.apache.log4j) domain */
50 LOG4J("-l");
51
52 private final String flag;
53
54 private Domain(String flag) {
55 this.flag = flag;
56 }
57
58 /**
59 * @return The corresponding command-line flag to pass to options like
60 * "lttng enable-event"
61 */
62 public String flag() {
63 return flag;
64 }
65 }
66
67 private final String sessionName;
68 private final Domain domain;
69
70 private volatile boolean channelCreated = false;
71
72 /**
73 * Constructor to create a new LTTng tracing session.
74 *
75 * @param sessionName
76 * The name of the session to use. It can be null, in which case
77 * we will provide a unique random name.
78 * @param domain
79 * The tracing domain of this session
80 */
81 public LttngSession(String sessionName, Domain domain) {
82 if (sessionName != null) {
83 this.sessionName = sessionName;
84 } else {
85 this.sessionName = UUID.randomUUID().toString();
86 }
87 this.domain = domain;
88
89 /* Create the session in LTTng */
90 executeCommand(Arrays.asList("lttng", "create", this.sessionName));
91 }
92
93 @Override
94 public void close() {
95 /* Destroy the session */
96 executeCommand(Arrays.asList("lttng", "destroy", sessionName));
97 // FIXME also delete the trace we generated ?
98 }
99
100 // ------------------------------------------------------------------------
101 // Public methods
102 // ------------------------------------------------------------------------
103
104 /**
105 * Enable all events in the given session (enable-event -a)
106 *
107 * @return If the command executed successfully (return code = 0).
108 */
109 public boolean enableAllEvents() {
110 channelCreated = true;
111 return executeCommand(Arrays.asList(
112 "lttng", "enable-event", domain.flag(), "-a", "-s", sessionName));
113 }
114
115 /**
116 * Enable individual event(s).
117 *
118 * @param enabledEvents
119 * The list of events to enable. Should not be null or empty
120 * @return If the command executed successfully (return code = 0).
121 */
122 public boolean enableEvents(String... enabledEvents) {
123 if (enabledEvents == null || enabledEvents.length == 0) {
124 throw new IllegalArgumentException();
125 }
126 channelCreated = true;
127 return executeCommand(Arrays.asList(
128 "lttng", "enable-event", domain.flag(),
129 Arrays.stream(enabledEvents).collect(Collectors.joining(",")),
130 "-s", sessionName));
131 }
132
133 /**
134 * Send a disable-event command. Used to disable events that were previously
135 * enabled.
136 *
137 * @param disabledEvents
138 * The list of disabled events. Should not be null or empty
139 * @return If the command executed successfully (return code = 0).
140 */
141 public boolean disableEvents(String... disabledEvents) {
142 if (disabledEvents == null || disabledEvents.length == 0) {
143 throw new IllegalArgumentException();
144 }
145 return executeCommand(Arrays.asList(
146 "lttng", "disable-event", domain.flag(),
147 Arrays.stream(disabledEvents).collect(Collectors.joining(",")),
148 "-s", sessionName));
149 }
150
151 /**
152 * Start tracing
153 *
154 * @return If the command executed successfully (return code = 0).
155 */
156 public boolean start() {
157 /*
158 * We have to enable a channel for 'lttng start' to work. However, we
159 * cannot enable a channel directly, see
160 * https://bugs.lttng.org/issues/894 . Instead we will enable an event
161 * we know does not exist
162 */
163 if (!channelCreated) {
164 enableEvents("non-event");
165 }
166 return executeCommand(Arrays.asList("lttng", "start", sessionName));
167 }
168
169 /**
170 * Stop the tracing session
171 *
172 * @return If the command executed successfully (return code = 0).
173 */
174 public boolean stop() {
175 return executeCommand(Arrays.asList("lttng", "stop", sessionName));
176 }
177
178 /**
179 * Issue a "lttng view" command on the session, and returns its output. This
180 * effectively returns the current content of the trace in text form.
181 *
182 * @return The output of Babeltrace on the session's current trace
183 */
184 public List<String> view() {
185 return ShellUtils.getOutputFromCommand(true, Arrays.asList("lttng", "view", sessionName));
186 }
187
188 /**
189 * Utility method to destroy all existing sessions. Useful when first
190 * setting up a test to make sure no existing session interferes.
191 */
192 public static void destroyAllSessions() {
193 executeCommand(Arrays.asList("lttng", "destroy", "-a"));
194 }
195
196 /**
197 * Outside of the scope of lttng-tools, but this utility method can be used
198 * to delete all traces currently under ~/lttng-traces/. This can be used by
199 * tests to cleanup a trace they have created.
200 *
201 * @return True if the command completes successfully, false if there was an
202 * error.
203 */
204 public static boolean deleteAllTracee() {
205 String tracesDir = new String(System.getProperty("user.home") + "/lttng-traces/");
206 return deleteDirectory(Paths.get(tracesDir));
207 }
208
209 // ------------------------------------------------------------------------
210 // Private helper methods
211 // ------------------------------------------------------------------------
212
213 private static boolean deleteDirectory(Path directory) {
214 try {
215 Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
216 @Override
217 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
218 Files.delete(file);
219 return FileVisitResult.CONTINUE;
220 }
221
222 @Override
223 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
224 Files.delete(dir);
225 return FileVisitResult.CONTINUE;
226 }
227 });
228 } catch (IOException e) {
229 /* At least we tried... */
230 return false;
231 }
232 return true;
233 }
234
235 }
This page took 0.033163 seconds and 4 git commands to generate.