|
1 /* |
|
2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 package jdk.management.jfr; |
|
27 |
|
28 import java.nio.file.Path; |
|
29 import java.time.Duration; |
|
30 import java.time.Instant; |
|
31 import java.util.LinkedHashMap; |
|
32 import java.util.List; |
|
33 import java.util.Map; |
|
34 |
|
35 import javax.management.openmbean.CompositeData; |
|
36 import javax.management.openmbean.TabularData; |
|
37 |
|
38 import jdk.jfr.Recording; |
|
39 import jdk.jfr.RecordingState; |
|
40 |
|
41 /** |
|
42 * Management representation of a {@code Recording}. |
|
43 * |
|
44 * @see Recording |
|
45 * |
|
46 * @since 9 |
|
47 */ |
|
48 public final class RecordingInfo { |
|
49 private final long id; |
|
50 private final String name; |
|
51 private final String state; |
|
52 private final boolean dumpOnExit; |
|
53 private final long size; |
|
54 private final boolean disk; |
|
55 private final long maxAge; |
|
56 private final long maxSize; |
|
57 private final long startTime; |
|
58 private final long stopTime; |
|
59 private final String destination; |
|
60 private final long durationInSeconds; |
|
61 private final Map<String, String> settings; |
|
62 |
|
63 // package private |
|
64 RecordingInfo(Recording recording) { |
|
65 id = recording.getId(); |
|
66 name = recording.getName(); |
|
67 state = recording.getState().toString(); |
|
68 dumpOnExit = recording.getDumpOnExit(); |
|
69 size = recording.getSize(); |
|
70 disk = recording.isToDisk(); |
|
71 |
|
72 Duration d = recording.getMaxAge(); |
|
73 if (d == null) { |
|
74 maxAge = 0; |
|
75 } else { |
|
76 maxAge = d.getSeconds(); |
|
77 } |
|
78 maxSize = recording.getMaxSize(); |
|
79 Instant s = recording.getStartTime(); |
|
80 startTime = s == null ? 0L : s.toEpochMilli(); |
|
81 Instant st = recording.getStopTime(); |
|
82 stopTime = st == null ? 0L : st.toEpochMilli(); |
|
83 Path p = recording.getDestination(); |
|
84 destination = p == null ? null : p.toString(); |
|
85 Duration duration = recording.getDuration(); |
|
86 durationInSeconds = duration == null ? 0 : duration.getSeconds(); |
|
87 settings = recording.getSettings(); |
|
88 } |
|
89 |
|
90 private RecordingInfo(CompositeData cd) { |
|
91 id = (int) cd.get("id"); |
|
92 name = (String) cd.get("name"); |
|
93 state = (String) cd.get("state"); |
|
94 dumpOnExit = (boolean) cd.get("dumpOnExit"); |
|
95 size = (long) cd.get("size"); |
|
96 disk = (boolean) cd.get("disk"); |
|
97 maxAge = (Long) cd.get("maxAge"); |
|
98 maxSize = (Long) cd.get("maxSize"); |
|
99 startTime = (Long) cd.get("startTime"); |
|
100 stopTime = (Long) cd.get("stopTime"); |
|
101 destination = (String) cd.get("destination"); |
|
102 durationInSeconds = (long) cd.get("duration"); |
|
103 settings = new LinkedHashMap<>(); |
|
104 Object map = cd.get("settings"); |
|
105 if (map instanceof TabularData) { |
|
106 TabularData td = (TabularData) map; |
|
107 List<String> keyNames = td.getTabularType().getIndexNames(); |
|
108 int size = keyNames.size(); |
|
109 for (Object keys : td.keySet()) { |
|
110 Object[] keyValues = ((List<?>) keys).toArray(); |
|
111 for (int i = 0; i < size; i++) { |
|
112 String key = keyNames.get(i); |
|
113 Object value = keyValues[i]; |
|
114 if (value instanceof String) { |
|
115 settings.put(key, (String) value); |
|
116 } |
|
117 } |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 /** |
|
123 * Returns the name of the recording associated with this |
|
124 * {@code RecordingInfo}. |
|
125 * |
|
126 * @return the recording name, not {@code null} |
|
127 * |
|
128 * @see Recording#getName() |
|
129 */ |
|
130 public String getName() { |
|
131 return name; |
|
132 } |
|
133 |
|
134 /** |
|
135 * Returns the unique ID for the recording associated with this |
|
136 * {@code RecordingInfo}. |
|
137 * |
|
138 * @return the recording ID |
|
139 * |
|
140 * @see Recording#getId() |
|
141 */ |
|
142 public long getId() { |
|
143 return id; |
|
144 } |
|
145 |
|
146 /** |
|
147 * Returns if the recording associated with this {@code RecordingInfo} |
|
148 * should be dumped to file when the JVM exits. |
|
149 * |
|
150 * @return {@code true} if recording should be dumped on exit, {@code false} |
|
151 * otherwise |
|
152 * |
|
153 * @see Recording#getDumpOnExit() |
|
154 */ |
|
155 public boolean getDumpOnExit() { |
|
156 return dumpOnExit; |
|
157 } |
|
158 |
|
159 /** |
|
160 * Returns how many seconds data should be kept on disk, or {@code 0} if |
|
161 * data is to be kept forever. |
|
162 * <p> |
|
163 * In-memory recordings are not affected by maximum age. |
|
164 * |
|
165 * @see Recording#getMaxAge() |
|
166 * @see Recording#setToDisk(boolean) |
|
167 * @return how long data should be kept on disk, measured in seconds |
|
168 * |
|
169 */ |
|
170 public long getMaxAge() { |
|
171 return maxAge; |
|
172 } |
|
173 |
|
174 /** |
|
175 * Returns the amount of data, measured in bytes, the recording associated |
|
176 * with this {@code RecordingInfo}, should be kept on disk, before it's |
|
177 * rotated away, or {@code 0} if data is to be kept indefinitely. |
|
178 * <p> |
|
179 * In-memory recordings are not affected by maximum size. |
|
180 * |
|
181 * @return the amount of data should be kept on disk, in bytes |
|
182 * |
|
183 * @see Recording#setToDisk(boolean) |
|
184 * @see Recording#getMaxSize() |
|
185 */ |
|
186 public long getMaxSize() { |
|
187 return maxSize; |
|
188 } |
|
189 |
|
190 /** |
|
191 * Returns a {@code String} representation of state of the recording |
|
192 * associated with this {@code RecordingInfo}. |
|
193 * <p> |
|
194 * Valid return values are {@code "NEW"}, {@code "DELAYED"}, {@code "STARTING"}, |
|
195 * {@code "RUNNING"}, {@code "STOPPING"}, {@code "STOPPED"} and {@code "CLOSED"}. |
|
196 * |
|
197 * @return the recording state, not {@code null} |
|
198 * |
|
199 * @see RecordingState#toString() |
|
200 * @see Recording#getState() |
|
201 */ |
|
202 public String getState() { |
|
203 return state; |
|
204 } |
|
205 |
|
206 /** |
|
207 * Returns start time of the recording associated with this |
|
208 * {@code RecordingInfo}, measured as ms since epoch, or {@code null} if the |
|
209 * recording hasn't started. |
|
210 * |
|
211 * @return the start time of the recording, or {@code null} if the recording |
|
212 * hasn't started |
|
213 * |
|
214 * @see Recording#getStartTime() |
|
215 */ |
|
216 public long getStartTime() { |
|
217 return startTime; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Returns the actual or expected stop time of the recording associated with |
|
222 * this {@code RecordingInfo}, measured as ms since epoch, or {@code null} |
|
223 * if the expected or actual stop time is not known, which can only happen |
|
224 * if the recording has not yet been stopped. |
|
225 * |
|
226 * @return the stop time of recording, or {@code null} if recording hasn't |
|
227 * been stopped. |
|
228 * |
|
229 * @see Recording#getStopTime() |
|
230 */ |
|
231 public long getStopTime() { |
|
232 return stopTime; |
|
233 } |
|
234 |
|
235 /** |
|
236 * Returns the settings for the recording associated with this |
|
237 * {@code RecordingInfo}. |
|
238 * |
|
239 * @return the recording settings, not {@code null} |
|
240 * |
|
241 * @see Recording#getSettings() |
|
242 */ |
|
243 public Map<String, String> getSettings() { |
|
244 return settings; |
|
245 } |
|
246 |
|
247 /** |
|
248 * Returns destination path where data, for the recording associated with |
|
249 * this {@link RecordingInfo}, should be written when the recording stops, |
|
250 * or {@code null} if the recording should not be written. |
|
251 * |
|
252 * @return the destination, or {@code null} if not set |
|
253 * |
|
254 * @see Recording#getDestination() |
|
255 */ |
|
256 public String getDestination() { |
|
257 return destination; |
|
258 } |
|
259 |
|
260 /** |
|
261 * Returns a string description of the recording associated with this |
|
262 * {@code RecordingInfo} |
|
263 * |
|
264 * @return description, not {@code null} |
|
265 */ |
|
266 @Override |
|
267 public String toString() { |
|
268 Stringifier s = new Stringifier(); |
|
269 s.add("name", name); |
|
270 s.add("id", id); |
|
271 s.add("maxAge", maxAge); |
|
272 s.add("maxSize", maxSize); |
|
273 return s.toString(); |
|
274 } |
|
275 |
|
276 /** |
|
277 * Returns the amount data recorded by recording. associated with this |
|
278 * {@link RecordingInfo}. |
|
279 * |
|
280 * @return the amount of recorded data, measured in bytes |
|
281 */ |
|
282 public long getSize() { |
|
283 return size; |
|
284 } |
|
285 |
|
286 /** |
|
287 * Returns {@code true} if the recording associated with this |
|
288 * {@code RecordingInfo} should be flushed to disk, when memory buffers are |
|
289 * full, {@code false} otherwise. |
|
290 * |
|
291 * @return {@code true} if recording is to disk, {@code false} otherwise |
|
292 */ |
|
293 public boolean isToDisk() { |
|
294 return disk; |
|
295 } |
|
296 |
|
297 /** |
|
298 * Returns the desired duration, measured in seconds, of the recording |
|
299 * associated with this {@link RecordingInfo}, or {code 0} if no duration |
|
300 * has been set. |
|
301 * |
|
302 * @return the desired duration, or {code 0} if no duration has been set |
|
303 * |
|
304 * @see Recording#getDuration() |
|
305 */ |
|
306 public long getDuration() { |
|
307 return durationInSeconds; |
|
308 } |
|
309 |
|
310 /** |
|
311 * Returns a {@code RecordingInfo} represented by the specified |
|
312 * {@code CompositeData} object. |
|
313 * <p> |
|
314 * The specified {@code CompositeData} must have the following item names and |
|
315 * item types to be valid. <blockquote> |
|
316 * <table class="striped"> |
|
317 * <caption>Supported names and types in a specified {@code CompositeData} object</caption> |
|
318 * <thead> |
|
319 * <tr> |
|
320 * <th scope="col" style="text-align:left">Name</th> |
|
321 * <th scope="col" style="text-align:left">Type</th> |
|
322 * </tr> |
|
323 * </thead> |
|
324 * <tbody> |
|
325 * <tr> |
|
326 * <th scope="row">id</th> |
|
327 * <td>{@code Long}</td> |
|
328 * </tr> |
|
329 * <tr> |
|
330 * <th scope="row">name</th> |
|
331 * <td>{@code String}</td> |
|
332 * </tr> |
|
333 * <tr> |
|
334 * <th scope="row">state</th> |
|
335 * <td>{@code String}</td> |
|
336 * </tr> |
|
337 * <tr> |
|
338 * <th scope="row">dumpOnExit</th> |
|
339 * <td>{@code Boolean}</td> |
|
340 * </tr> |
|
341 * <tr> |
|
342 * <th scope="row">size</th> |
|
343 * <td>{@code Long}</td> |
|
344 * </tr> |
|
345 * <tr> |
|
346 * <th scope="row">disk</th> |
|
347 * <td>{@code Boolean}</td> |
|
348 * </tr> |
|
349 * <tr> |
|
350 * <th scope="row">maxAge</th> |
|
351 * <td>{@code Long}</td> |
|
352 * </tr> |
|
353 * <tr> |
|
354 * <th scope="row">maxSize</th> |
|
355 * <td>{@code Long}</td> |
|
356 * </tr> |
|
357 * <tr> |
|
358 * <th scope="row">startTime</th> |
|
359 * <td>{@code Long}</td> |
|
360 * </tr> |
|
361 * <tr> |
|
362 * <th scope="row">stopTime</th> |
|
363 * <td>{@code Long}</td> |
|
364 * </tr> |
|
365 * <tr> |
|
366 * <th scope="row">destination</th> |
|
367 * <td>{@code String}</td> |
|
368 * </tr> |
|
369 * <tr> |
|
370 * <th scope="row">duration</th> |
|
371 * <td>{@code Long}</td> |
|
372 * </tr> |
|
373 * <tr> |
|
374 * <th scope="row">settings</th> |
|
375 * <td>{@code javax.management.openmbean.CompositeData[]} whose element type |
|
376 * is the mapped type for {@link SettingDescriptorInfo} as specified in the |
|
377 * {@link SettingDescriptorInfo#from} method.</td> |
|
378 * </tr> |
|
379 * </tbody> |
|
380 * </table> |
|
381 * </blockquote> |
|
382 * |
|
383 * @param cd {@code CompositeData} representing the {@code RecordingInfo} to |
|
384 * return |
|
385 * |
|
386 * @throws IllegalArgumentException if {@code cd} does not represent a valid |
|
387 * {@code RecordingInfo} |
|
388 * |
|
389 * @return the {@code RecordingInfo} represented by {@code cd}, or |
|
390 * {@code null} if {@code cd} is {@code null} |
|
391 */ |
|
392 public static RecordingInfo from(CompositeData cd) { |
|
393 if (cd == null) { |
|
394 return null; |
|
395 } |
|
396 return new RecordingInfo(cd); |
|
397 } |
|
398 } |