census-instrumentation / opencensus-go

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

Panic when running stats.Record without importing the view package #1289

Closed tzembo closed 1 year ago

tzembo commented 1 year ago

Please answer these questions before submitting a bug report.

What version of OpenCensus are you using?

v0.24.0

What version of Go are you using?

go1.18.7 darwin/arm64

What did you do?

Here is a minimum reproducible example:

package main

import (
    "context"
    "fmt"

    "go.opencensus.io/stats"
)

func main() {
    ctx := context.Background()
    measure := stats.Int64("test", "", "bytes")
    stats.Record(ctx, measure.M(1))
    fmt.Println("SUCCESS")
}

What did you expect to see?

This code shouldn't panic.

What did you see instead?

When I run this program, I get the following error:

> go run main.go
panic: interface conversion: interface {} is nil, not func(*tag.Map, []stats.Measurement, map[string]interface {})

goroutine 1 [running]:
go.opencensus.io/stats.Record({0x102e57f78?, 0x1400009a000?}, {0x140000c00a0?, 0x0?, 0x102e20b95?})
        /Users/thomas.zembowicz/go/pkg/mod/go.opencensus.io@v0.24.0/stats/record.go:99 +0x128
main.main()
        /Users/thomas.zembowicz/opencensus-issue-repro/main.go:12 +0x108
exit status 2

This makes sense because it looks like the internal.MeasurementRecorder called by Record here is only initialized when init runs here in the view package. Sure enough, when I anonymously import the view package for its init side-effects:

_ "go.opencensus.io/stats/view"

the issue goes away:

> go run main.go
SUCCESS

Additional context

I came across this issue when upgrading an opencensus-go dependency from v0.23.0 to v0.24.0. This is causing unit tests for packages that never need to import view (directly or indirectly) to fail. We can add an anonymous import for the view package where we call stats.Record but it doesn't feel like this should be necessary. This isn't an issue when running our whole program because we use the view package to register exporters.