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}