Meta annotation, specifies that an annotation represents a content type, such
as a time span or a frequency.
The following example shows how a temperature content type can be created and
used.
First declare a temperature annotation using the ContentType
annotation:
@MetadataDefinition
@ContentType
@Name("com.example.Temperature")
@Label("Temperature")
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Temperature {
public final static String KELVIN = "KELVIN";
public final static String CELSIUS = "CELSIUS";
public final static String FAHRENEHIT = "FAHRENHEIT";
String value() default CELSIUS;
}
Then declare an event, annotate a field and commit the data:
@Name("com.example.CPU")
@Label("CPU")
@Category({ "Hardware", "CPU" })
@Period("1 s")
@StackTrace(false)
static public class CPUEvent extends Event {
@Label("ID")
String id;
@Temperature(Temperature.KELVIN)
@Label("Temperature")
float temperature;
}
public static void main(String... args) throws InterruptedException {
FlightRecorder.addPeriodicEvent(CPUEvent.class, () -> {
for (var cpu : listCPUs()) {
CPUEvent event = new CPUEvent();
event.id = cpu.id();
event.temperature = cpu.temperature(); // in Kelvin
event.commit();
}
});
Thread.sleep(10_000);
}
@Name("com.example.CPU")@Label("CPU")@Category({"Hardware","CPU"})@Period("1 s")@StackTrace(false)staticpublicclassCPUEventextendsEvent{@Label("ID")Stringid;@Temperature(Temperature.KELVIN)@Label("Temperature")floattemperature;}publicstaticvoidmain(String...args)throwsInterruptedException{FlightRecorder.addPeriodicEvent(CPUEvent.class,()->{for(varcpu:listCPUs()){CPUEventevent=newCPUEvent();event.id=cpu.id();event.temperature=cpu.temperature();// in Kelvinevent.commit();}});Thread.sleep(10_000);}
Finally, inspect the annotation when displaying event data:
void printTemperaturesInCelsius(Path file) throws IOException {
for (RecordedEvent event : RecordingFile.readAllEvents(file)) {
for (ValueDescriptor field : event.getEventType().getFields()) {
for (AnnotationElement ae : field.getAnnotationElements()) {
ContentType type = ae.getAnnotation(ContentType.class);
if (type != null) {
if (ae.getTypeName().equals("com.example.Temperature")) {
double value = event.getDouble(field.getName());
String unit = (String) ae.getValue("value");
double celsius = switch (unit) {
case "CELSIUS" -> value;
case "KELVIN" -> value - 273.15;
case "FAHRENHEIT" -> (value - 32) / 1.8;
default -> throw new IllegalStateException("Unknown temperature unit '" + unit + "'");
};
System.out.println(celsius + " C");
} else {
System.err.println("Can't format content type " + ae.getTypeName() + " for field " + field.getName());
}
}
}
}
}
}
voidprintTemperaturesInCelsius(Pathfile)throwsIOException{for(RecordedEventevent:RecordingFile.readAllEvents(file)){for(ValueDescriptorfield:event.getEventType().getFields()){for(AnnotationElementae:field.getAnnotationElements()){ContentTypetype=ae.getAnnotation(ContentType.class);if(type!=null){if(ae.getTypeName().equals("com.example.Temperature")){doublevalue=event.getDouble(field.getName());Stringunit=(String)ae.getValue("value");doublecelsius=switch(unit){case"CELSIUS"->value;case"KELVIN"->value-273.15;case"FAHRENHEIT"->(value-32)/1.8;default->thrownewIllegalStateException("Unknown temperature unit '"+unit+"'");};System.out.println(celsius+" C");}else{System.err.println("Can't format content type "+ae.getTypeName()+" for field "+field.getName());}}}}}}