Description
[ Note related QUARKS-195 ]
Manually added CounterOp or RateMeter oplets results in undesirable additional CounterOp (and StreamScope) injection in the DevelopmentProvider. e.g.
poll -> pipe(new CounterOp) /* Metrics.counter(stream) */ -> sink
results in
poll -> CounterOp -> StreamScope -> the-manual-CounterOp -> CounterOp -> StreamScope -> sink
The injection code doesn't recognize that a counter op is already present - i.e., it treats the manual CounterOp (or a manual RateMeter) as any other oplet, resulting in injecting a CounterOp between it and the poll / sink.
As it turns out, the manual CounterOp/RateMeter is included in the "counter metrics" retrieved by the Console and used for tuple-count info, so the additional injections aren't really needed... and they look odd in the Console because you see a sequence of 5 small rectangles... because the Console renders all metric ops as small rectangles whether they're injected or not. Of course, one of the StreamScope injections is needed.
I suspect all that's needed is to enhance Metric.counter(Topology)'s peekAll selector so that it excludes instanceof CounterOp and RateMeter.