twitter/util

Make GlobalFlags java accessible

Closed this issue · 3 comments

One line summary of the issue here.

Expected behavior

As a java user, I should be able to define global flags naturally.

Actual behavior

The lookup system for global flags requires them to be scalaesque classes (ex. with a $ suffix). Also, the naming convention isn't natural in java.

Steps to reproduce the behavior

Here's what I had to do to make a valid flag in java. It would be much nicer to be able to define (and register them) with a static function vs stuff like this.

public final class ZipkinFlags {

  // this class naming convention is required for global flags to work
  public static final class initialSampleRate$ extends GlobalFlag<Float> {
    public static final initialSampleRate$ MODULE$ = new initialSampleRate$();

    // to avoid making unnatural class names, I override the name here
    @Override public String name() {
      return "zipkin.initialSampleRate";
    }

    private initialSampleRate$() {
      super(
          BoxesRunTime.boxToFloat(Sampler$.MODULE$.DefaultSampleRate()),
          "Percentage of traces to sample (report to zipkin) in the range [0.0 - 1.0]",
          Flaggable$.MODULE$.ofJavaFloat());
    }
  }

  // this class naming convention is required for global flags to work
  public static final class initialSampleRate {

    // this method is looked up at runtime
    public static Flag<?> getGlobalFlag() {
      return initialSampleRate$.MODULE$.getGlobalFlag();
    }
  }

--snip--

Ok. Yeah not too Java friendly :(

Unfortunately, the code has some pretty deep-set leanings about GlobalFlag classnames and such so there is only so much we can do.

I've got a branch up for review that, if you follow a few rules, lets you create first class GlobalFlags in Java. Here's an example:

public final class javaGlobalWithDefault$ extends JavaGlobalFlag<String> {
  private javaGlobalWithDefault$() {
    super("default value", "help string here", Flaggable.ofString());
  }

  public static final Flag<String> Flag = new javaGlobalWithDefault$();

  public static Flag<?> globalFlagInstance() {
    return Flag;
  }
}

and another without a default:

public final class javaGlobalNoDefault$ extends JavaGlobalFlag<Integer> {
  private javaGlobalNoDefault$() {
    super("help string here", Flaggable.ofJavaInteger(), Integer.class);
  }

  public static final Flag<Integer> Flag = new javaGlobalNoDefault$();

  public static Flag<?> globalFlagInstance() {
    return Flag;
  }
}

Usage of the flag isn't too bad:

assertEquals("default value", javaGlobalWithDefault$.Flag.apply());
assertTrue(javaGlobalNoDefault$.Flag.get().isEmpty());

Hopefully the patch will make it out to develop this coming week.

Merged in df5c310