I was thinking about nulls in configuration files. Part of the problem is that you cannot use Optional<T> in the configuration definition, so all of your configuration is implicitly optional (i.e. it could be null). It would be nice to have missing fields be treated as a configuration-time error. If we wanted optional ones, we would explicitly state Optional<ElasticSearchConfig>. Of course, there are also some cases where you actually want an arbitrary set of completely optional parameters (HTTP clients come to mind). In this case I guess you'd have a lot of Optional<T>, but it's worth it, because you won't accidentally assume that its non-optional.
Below is how I'd do the specific problem of a Logger with an optional configuration file. I assume our configuration utility is sophisticated enough to give us Optional<T>.
Notice that ILogger implements a monoidal structure: it has a plus, a zero and satisfies the law ∀x. x.plus(zero) = x. This makes it easy to expand logging functionality in a clean way. You just plus a bunch of untangled logger logic together into one. This architecture garuntees you won't have interference between the loggers (modulo exceptions, etc.).
It's also nice that the configuration gives you a maybeEsc directly so there's no way you can accidentally forget that a parameter is optional (because the type system will complain that you have an Optional<ElasticSearchConfig> not an ElasticSearchConfig).
In fact, the ILogger interface is actually a commutative monoid since
∀x,y. x.plus(y) = y.plus(x).