Skip to content
Closed
16 changes: 8 additions & 8 deletions docstore/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,12 @@
// the returned error. See the specific driver's package doc for the supported
// types.
//
// # OpenCensus Integration
// # OpenTelemetry Integration
//
// OpenCensus supports tracing and metric collection for multiple languages and
// backend providers. See https://opencensus.io.
// OpenTelemetry supports tracing, metrics, and logs collection for multiple languages and
// backend providers. See https://opentelemetry.io.
//
// This API collects OpenCensus traces and metrics for the following methods:
// This API collects OpenTelemetry traces and metrics for the following methods:
// - ActionList.Do
// - Query.Get (for the first query only; drivers may make additional calls while iterating over results)
//
Expand All @@ -270,10 +270,10 @@
// by driver and method.
// For example, "gocloud.dev/docstore/latency".
//
// To enable trace collection in your application, see "Configure Exporter" at
// https://opencensus.io/quickstart/go/tracing.
// To enable metric collection in your application, see "Exporting stats" at
// https://opencensus.io/quickstart/go/metrics.
// To enable trace collection in your application, see the documentation at
// https://opentelemetry.io/docs/instrumentation/go/getting-started/.
// To enable metric collection in your application, see the documentation at
// https://opentelemetry.io/docs/instrumentation/go/manual/.
//
// # GORM-like Code Generation
//
Expand Down
93 changes: 76 additions & 17 deletions docstore/docstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ import (
"sort"
"strings"
"sync"
"time"
"unicode/utf8"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/trace"
"gocloud.dev/docstore/driver"
"gocloud.dev/gcerrors"
"gocloud.dev/internal/gcerr"
"gocloud.dev/internal/oc"
gcdkotel "gocloud.dev/internal/otel"
)

// A Document is a set of field-value pairs. One or more fields, called the key
Expand All @@ -46,34 +51,61 @@ type Document = interface{}
// To create a Collection, use constructors found in driver subpackages.
type Collection struct {
driver driver.Collection
tracer *oc.Tracer
tracer *gcdkotel.Tracer
mu sync.Mutex
closed bool
}

const pkgName = "gocloud.dev/docstore"

var (
latencyMeasure = oc.LatencyMeasure(pkgName)
// Initialize OpenTelemetry meter and tracer
meter = otel.GetMeterProvider().Meter(pkgName)

// OpenCensusViews are predefined views for OpenCensus metrics.
// The views include counts and latency distributions for API method calls.
// See the example at https://godoc.org/go.opencensus.io/stats/view for usage.
OpenCensusViews = oc.Views(pkgName, latencyMeasure)
// Define counter instrument for completed calls (replaces the previous OpenCensus metrics)
completedCallsCounter metric.Int64Counter

// Define histogram instrument for latency measurement
latencyHistogram metric.Float64Histogram

// Tracer for creating spans
tracer = otel.GetTracerProvider().Tracer(pkgName)
)

// Initialize the metrics
func init() {
var err error

// Create the completed calls counter
completedCallsCounter, err = meter.Int64Counter(
pkgName+"/completed_calls",
metric.WithDescription("Total number of completed method calls"),
metric.WithUnit("{call}"),
)
if err != nil {
log.Printf("Failed to create completed_calls counter: %v", err)
}

// Create the latency histogram
latencyHistogram, err = meter.Float64Histogram(
pkgName+"/latency",
metric.WithDescription("Latency of method calls"),
metric.WithUnit("ms"),
)
if err != nil {
log.Printf("Failed to create latency histogram: %v", err)
}
}

// NewCollection is intended for use by drivers only. Do not use in application code.
var NewCollection = newCollection

// newCollection makes a Collection.
func newCollection(d driver.Collection) *Collection {
providerName := gcdkotel.ProviderName(d)
c := &Collection{
driver: d,
tracer: &oc.Tracer{
Package: pkgName,
Provider: oc.ProviderName(d),
LatencyMeasure: latencyMeasure,
},
tracer: gcdkotel.NewTracer(pkgName, providerName),
}
_, file, lineno, ok := runtime.Caller(1)
runtime.SetFinalizer(c, func(c *Collection) {
Expand Down Expand Up @@ -338,15 +370,42 @@ func (l *ActionList) Do(ctx context.Context) error {
return l.do(ctx, true)
}

// do implements Do with optional OpenCensus tracing, so it can be used internally.
func (l *ActionList) do(ctx context.Context, oc bool) (err error) {
// do implements Do with optional OpenTelemetry tracing, so it can be used internally.
func (l *ActionList) do(ctx context.Context, withTracing bool) (err error) {
if err := l.coll.checkClosed(); err != nil {
return ActionListError{{-1, errClosed}}
}

if oc {
ctx = l.coll.tracer.Start(ctx, "ActionList.Do")
defer func() { l.coll.tracer.End(ctx, err) }()
var startTime time.Time
var span trace.Span

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could these two be defined in the scope of
if withTracing {} below. Seems we dont need them outside the scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pramineni01 this has been moved to the withTracing scope


if withTracing {
startTime = time.Now()
ctx, span = l.coll.tracer.Start(ctx, "ActionList.Do")
defer func() {
l.coll.tracer.End(span, err)

// Record metrics
if completedCallsCounter != nil {
attr := []attribute.KeyValue{
gcdkotel.MethodKey.String("ActionList.Do"),
gcdkotel.ProviderKey.String(l.coll.tracer.Provider),
}
completedCallsCounter.Add(context.Background(), 1, metric.WithAttributes(attr...))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not ctx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jba This has been resolved appropriately

}

if latencyHistogram != nil {
attr := []attribute.KeyValue{
gcdkotel.MethodKey.String("ActionList.Do"),
gcdkotel.ProviderKey.String(l.coll.tracer.Provider),
}
latencyHistogram.Record(
context.Background(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

float64(time.Since(startTime).Milliseconds()),
metric.WithAttributes(attr...),
)
}
}()
}

das, err := l.toDriverActions()
Expand Down
2 changes: 1 addition & 1 deletion docstore/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type Collection interface {
//
// Implementations can choose to execute the Query as one single request or
// multiple ones, depending on their service offerings. The portable type
// exposes OpenCensus metrics for the call to RunGetQuery (but not for
// exposes OpenTelemetry metrics for the call to RunGetQuery (but not for
// subsequent calls to DocumentIterator.Next), so drivers should prefer to
// make at least one RPC during RunGetQuery itself instead of lazily waiting
// for the first call to Next.
Expand Down
23 changes: 14 additions & 9 deletions docstore/mongodocstore/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ require (
cloud.google.com/go/compute/metadata v0.6.0 // indirect
github.com/aws/aws-sdk-go v1.55.6 // indirect
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.29.12 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.65 // indirect
github.com/aws/aws-sdk-go-v2/config v1.29.13 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.66 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.18 // indirect
github.com/aws/smithy-go v1.22.3 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/go-replayers/grpcreplay v1.3.0 // indirect
github.com/google/go-replayers/httpreplay v1.2.0 // indirect
Expand All @@ -53,19 +53,23 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
Expand All @@ -74,8 +78,9 @@ require (
golang.org/x/text v0.23.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/api v0.228.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
google.golang.org/grpc v1.71.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250404141209-ee84b53bf3d0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250404141209-ee84b53bf3d0 // indirect
google.golang.org/grpc v1.71.1 // indirect
google.golang.org/protobuf v1.36.6 // indirect
)

Expand Down
Loading