001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.epilogue; 006 007import java.lang.annotation.ElementType; 008import java.lang.annotation.Retention; 009import java.lang.annotation.RetentionPolicy; 010import java.lang.annotation.Target; 011 012/** 013 * Place this annotation on a class to automatically log every field and every public accessor 014 * method (methods with no arguments and return a loggable data type). Use {@link #strategy()} to 015 * flag a class as logging everything it can, except for those elements tagged with 016 * {@code @Logged(importance = NONE)}; or for logging only specific items also tagged with 017 * {@code @Logged}. 018 * 019 * <p>Logged fields may have any access modifier. Logged methods must be public; non-public methods 020 * will be ignored. 021 * 022 * <p>Epilogue can log all primitive types, arrays of primitive types (except char and short), 023 * Strings, arrays of Strings, sendable objects, objects with a struct serializer, and arrays of 024 * objects with struct serializers. 025 */ 026@Retention(RetentionPolicy.RUNTIME) 027@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) 028public @interface Logged { 029 /** 030 * The name for the annotated element to be logged as. Does nothing on class-level annotations. 031 * Fields and methods will default to be logged using their in-code names; use this attribute to 032 * set it to something custom. 033 * 034 * <p>If the annotation is placed on a class, the specified name will not change logged data 035 * (since that uses the names of the specific usages of the class in fields and methods); however, 036 * it will be used to set the names of the generated logger that Logged will use to log instances 037 * of the class. This can be used to avoid name conflicts if you have multiple classes with the 038 * same name, but in different packages, and want to be able to log both. 039 * 040 * @return the name to use to log the field or method under; or the name of the generated 041 * class-specific logger 042 */ 043 String name() default ""; 044 045 /** Opt-in or opt-out strategies for logging. */ 046 enum Strategy { 047 /** 048 * Log everything except for those elements explicitly opted out of with the skip = true 049 * attribute. This is the default behavior. 050 */ 051 OPT_OUT, 052 053 /** Log only fields and methods tagged with an {@link Logged} annotation. */ 054 OPT_IN 055 } 056 057 /** 058 * The strategy to use for logging. Only has an effect on annotations on class or interface 059 * declarations. 060 * 061 * @return the strategy to use to determine which fields and methods in the class to log 062 */ 063 Strategy strategy() default Strategy.OPT_OUT; 064 065 /** 066 * Data importance. Can be used at the class level to set the default importance for all data 067 * points in the class, and can be used on individual fields and methods to set a specific 068 * importance level overriding the class-level default. 069 */ 070 enum Importance { 071 /** Debug information. Useful for low-level information like raw sensor values. */ 072 DEBUG, 073 074 /** 075 * Informational data. Useful for higher-level information like pose estimates or subsystem 076 * state. 077 */ 078 INFO, 079 080 /** Critical data that should always be present in logs. */ 081 CRITICAL 082 } 083 084 /** 085 * The importance of the annotated data. If placed on a class or interface, this will be the 086 * default importance of all data within that class; this can be overridden on a per-element basis 087 * by annotating fields and methods with their own {@code @Logged(importance = ...)} annotation. 088 * 089 * @return the importance of the annotated element 090 */ 091 Importance importance() default Importance.DEBUG; 092 093 /** 094 * Different behaviors for how Epilogue will generate the names of logged data points. This only 095 * applies to automatically generated names; any specific name provided with {@link #name()} will 096 * take precedence over an automatically generated name. 097 */ 098 enum Naming { 099 /** 100 * Sets the default naming strategy to use the name of the element as it appears in source code. 101 * For example, a field {@code double m_x} would be labeled as {@code "m_x"} by default, and a 102 * {@code getX()} accessor would be labeled as {@code "getX"}. 103 */ 104 USE_CODE_NAME, 105 106 /** 107 * Sets the default naming strategy to use a human-readable name based on the name of the name 108 * of the element as it appears in source code. For example, a field {@code double m_x} would be 109 * labeled as {@code "X"} by default, and a {@code getX()} accessor would also be labeled as 110 * {@code "X"}. Because logged names must be unique, this configuration would fail to compile 111 * and require either one of the fields to be excluded from logs (which, for simple accessors, 112 * would be ideal to avoid duplicate data), or to rename one or both elements so the logged data 113 * fields would have unique names. 114 */ 115 USE_HUMAN_NAME 116 } 117 118 /** 119 * The default naming behavior to use. Defaults to {@link Naming#USE_CODE_NAME}, which uses the 120 * raw code name directly in logs. Any configuration of the {@link #name()} attribute on logged 121 * fields and methods will take precedence over an automatically generated name. 122 * 123 * @return the naming strategy for and annotated field or method, or the default naming strategy 124 * for all logged fields and methods in an annotated class 125 */ 126 Naming defaultNaming() default Naming.USE_CODE_NAME; 127}