census-instrumentation / opencensus-go

A stats collection and distributed tracing framework
http://opencensus.io
Apache License 2.0
2.06k stars 327 forks source link

How to test/use correctly OpenCensus stats in an application using opencensus-go? #462

Open slok opened 6 years ago

slok commented 6 years ago

Hi!

First of all, I want to let you know that I'm new to OpenCensus so maybe I'm taking a bad approach :)

I'm trying to add OpenCensus stats as part of instrumentation to one of the libraries I maintain.

I started getting familiar with some of the concepts and reading internal library code so I could create a OpenCensus Recorder on Kooper.

The problem is that I would like to inject an OpenCensus "registry", "recorder" or similar (the name doesn't matter) object, and (I think that) OpenCensus works at global level https://github.com/census-instrumentation/opencensus-go/blob/904befae6040396f202efd5a06d2a2d87d521424/stats/internal/record.go#L12 https://github.com/census-instrumentation/opencensus-go/blob/904befae6040396f202efd5a06d2a2d87d521424/stats/view/worker.go#L28-L32 https://github.com/census-instrumentation/opencensus-go/blob/904befae6040396f202efd5a06d2a2d87d521424/stats/view/worker.go#L156-L166

I've checked the tests of the worker and they work at the same package as the worker itself (go.opencensus.io/stats/view) so they can create new worker instances without problem, but outside the library that's not possible.

https://github.com/census-instrumentation/opencensus-go/blob/30bf88b1914cbf6e5ff9347a4e2880cb6691aafa/stats/view/worker_test.go#L579-L583

So, in other words, I can't decouple my code correctly, inject the dependencies and make each test to be idempotent and independent without small hacks like reset functions. Appart from this, working in global context I can't make my tests run in parallel.

I'm missing something or there is an established approach when using and testing opencensus-go in other applications?

Is there out there any Go application or library using OpenCensus and tested so I can read the code as an example? I did not found.

Thank you for your time and OSS contributions!

semistrict commented 6 years ago

Yeah I have had the same complaint writing tests. I don't like all the global state we use, and there's a lot. We try to hide it all internally. Of course, this makes it very difficult to write tests against the library.

I have a few suggestions:

  1. OpenCensus is really not ready to be depended on by other libraries without vendoring, since the APIs are changing rapidly. So in this case, you might want to wrap OpenCensus and have your wrapper be non-global and mock it out for testing.

  2. Create new measures and view for every test (gets very ugly fast)

  3. Help us make it better somehow - TBH I don't know what we should really do here. On the one hand I really don't want to require people to pass around a Recorder object. But maybe that's not so bad. I'm intrigued by the possibility of overriding the recording with a Context value, but that sounds like it might be an abuse of context.Context.

@rakyll @odeke-em your thoughts?

cyriltovena commented 5 years ago

Hello,

I'm currently integrating OpenCensus too and I would also like a way to test.

I have thought of two options :

WDYT ?

cyriltovena commented 5 years ago

In the end I'm testing with prometheus ouput using custom registry and the testutil package from prometheus.

My only issue was to flush the data before tests end, I hacked my way by unregistering all views (I saw a flush at that specific time :) ).

So https://github.com/census-instrumentation/opencensus-go/issues/862 will also help testing.

rghetia commented 5 years ago

@Kuqd and @slok, we recently added Reader and IntervalReader. You can call ReadAndExport. Does that help?

jkohen commented 5 years ago

I'm not the original poster, but I just tried ReadAndExport and it's working for me without the sleep.