1 /* 2 * Copyright (c) 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.jfr.api.event.dynamic; 27 28 import java.io.IOException; 29 import java.lang.annotation.ElementType; 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 import java.lang.annotation.Target; 33 import java.util.ArrayList; 34 import java.util.Collections; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 39 import jdk.jfr.AnnotationElement; 40 import jdk.jfr.Category; 41 import jdk.jfr.Description; 42 import jdk.jfr.Event; 43 import jdk.jfr.EventFactory; 44 import jdk.jfr.EventType; 45 import jdk.jfr.Label; 46 import jdk.jfr.MetadataDefinition; 47 import jdk.jfr.Name; 48 import jdk.jfr.Recording; 49 import jdk.jfr.Relational; 50 import jdk.jfr.ValueDescriptor; 51 import jdk.jfr.consumer.RecordedEvent; 52 import jdk.test.lib.jfr.Events; 53 54 /* 55 * @test 56 * @key jfr 57 * @library /test/lib 58 * @run main/othervm jdk.jfr.api.event.dynamic.TestDynamicAnnotations 59 */ 60 public class TestDynamicAnnotations { 61 62 @Label("Execution Context Id") 63 @Description("A unique identifier to correlate events or requests associated with the same task across several components") 64 @Relational 65 @MetadataDefinition 66 @Target(ElementType.FIELD) 67 @Retention(RetentionPolicy.RUNTIME) 68 private @interface ECID { 69 } 70 71 @MetadataDefinition 72 @Target({ ElementType.FIELD, ElementType.TYPE }) 73 @Retention(RetentionPolicy.RUNTIME) 74 private @interface Array { 75 String[] stringArray(); 76 77 int[] intArray(); 78 79 long[] longArray(); 80 81 float[] floatArray(); 82 83 double[] doubleArray(); 84 85 boolean[] booleanArray(); 86 87 short[] shortArray(); 88 89 byte[] byteArray(); 90 91 char[] charArray(); 92 } 93 94 public static void main(String[] args) throws Throwable { 95 testEventFactoryExample(); 96 testECID(); 97 testArray(); 98 } 99 100 // Copy of sample code in Javadoc for jdk.jfr.EVentFactory 101 public static void testEventFactoryExample() throws IOException { 102 List<ValueDescriptor> fields = new ArrayList<>(); 103 List<AnnotationElement> messageAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Message")); 104 fields.add(new ValueDescriptor(String.class, "message", messageAnnotations)); 105 List<AnnotationElement> numberAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Number")); 106 fields.add(new ValueDescriptor(int.class, "number", numberAnnotations)); 107 108 String[] category = { "Example", "Getting Started" }; 109 List<AnnotationElement> eventAnnotations = new ArrayList<>(); 110 eventAnnotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld")); 111 eventAnnotations.add(new AnnotationElement(Label.class, "Hello World")); 112 eventAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started")); 113 eventAnnotations.add(new AnnotationElement(Category.class, category)); 114 115 EventFactory f = EventFactory.create(eventAnnotations, fields); 116 117 Event event = f.newEvent(); 118 event.set(0, "hello, world!"); 119 event.set(1, 4711); 120 event.commit(); 121 } 122 123 public static void testECID() throws Exception { 124 List<ValueDescriptor> fields = new ArrayList<>(); 125 126 List<AnnotationElement> fieldAnnotations = new ArrayList<>(); 127 fieldAnnotations.add(new AnnotationElement(ECID.class)); 128 ValueDescriptor ecidField = new ValueDescriptor(String.class, "ecid", fieldAnnotations); 129 fields.add(ecidField); 130 131 EventFactory f = EventFactory.create(fieldAnnotations, fields); 132 133 String ecidValue = "131739871298371279812"; 134 try (Recording r = new Recording()) { 135 r.start(); 136 Event event = f.newEvent(); 137 event.set(0, ecidValue); 138 event.commit(); 139 r.stop(); 140 List<RecordedEvent> events = Events.fromRecording(r); 141 Events.hasEvents(events); 142 Events.assertField(events.get(0), "ecid").equal(ecidValue); 143 } 144 EventType type = f.getEventType(); 145 ECID e = type.getAnnotation(ECID.class); 146 if (e == null) { 147 throw new Exception("Missing ECID annotation"); 148 } 149 } 150 151 public static void testArray() throws Exception { 152 List<AnnotationElement> annotations = new ArrayList<>(); 153 Map<String, Object> values = new HashMap<>(); 154 values.put("stringArray", new String[] {"zero", "one"}); 155 values.put("intArray", new int[] {0, 1}); 156 values.put("longArray", new long[] {0L, 1L}); 157 values.put("floatArray", new float[] {0.0f, 1.0f}); 158 values.put("doubleArray", new double[] {0.0, 1.0}); 159 values.put("booleanArray", new boolean[] {false, true}); 160 values.put("shortArray", new short[] {(short)0, (short)1}); 161 values.put("byteArray", new byte[] {(byte)0, (byte)1}); 162 values.put("charArray", new char[] {'0','1'}); 163 164 annotations.add(new AnnotationElement(Array.class, values)); 165 EventFactory f = EventFactory.create(annotations, Collections.emptyList()); 166 Array a = f.getEventType().getAnnotation(Array.class); 167 if (a == null) { 168 throw new Exception("Missing array annotation"); 169 } 170 verifyArrayAnnotation(a); 171 System.out.println("Event metadata is correct"); 172 try (Recording r = new Recording()) { 173 r.start(); 174 Event e = f.newEvent(); 175 e.commit(); 176 r.stop(); 177 List<RecordedEvent> events = Events.fromRecording(r); 178 Events.hasEvents(events); 179 RecordedEvent re = events.get(0); 180 Array arrayAnnotation = re.getEventType().getAnnotation(Array.class); 181 if (arrayAnnotation== null) { 182 throw new Exception("Missing array annotation"); 183 } 184 verifyArrayAnnotation(arrayAnnotation); 185 System.out.println("Persisted event metadata is correct"); 186 } 187 } 188 189 private static void verifyArrayAnnotation(Array a) throws Exception { 190 if (!a.stringArray()[0].equals("zero") || !a.stringArray()[1].equals("one")) { 191 throw new Exception("string[] doesn't match"); 192 } 193 if (a.intArray()[0] != 0 || a.intArray()[1] != 1) { 194 throw new Exception("int[] doesn't match"); 195 } 196 if (a.longArray()[0] != 0 || a.longArray()[1] != 1) { 197 throw new Exception("long[] doesn't match"); 198 } 199 if (a.floatArray()[0] != 0.0f || a.floatArray()[1] != 1.0f) { 200 throw new Exception("float[] doesn't match"); 201 } 202 if (a.doubleArray()[0] != 0.0 || a.doubleArray()[1] != 1.0) { 203 throw new Exception("double[] doesn't match"); 204 } 205 if (a.booleanArray()[0] != false || a.booleanArray()[1] != true) { 206 throw new Exception("boolean[] doesn't match"); 207 } 208 if (a.shortArray()[0] != (short)0 || a.shortArray()[1] != (short)1) { 209 throw new Exception("short[] doesn't match"); 210 } 211 if (a.byteArray()[0] != (byte)0 || a.byteArray()[1] != (byte)1) { 212 throw new Exception("byte[] doesn't match"); 213 } 214 if (a.charArray()[0] != '0' || a.charArray()[1] != '1') { 215 throw new Exception("char[] doesn't match"); 216 } 217 } 218 }