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