Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WithClock TracerProviderOption #2052

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5d0f379
add clock/SetClock to trace provider (fix #2043)
Frefreak Jul 3, 2021
a8a08d4
fix lint (goimports)
Frefreak Jul 3, 2021
08351ed
fix missing license, modify changelog and fix test on windows
Frefreak Jul 4, 2021
6aaec19
adjustment
Frefreak Jul 6, 2021
33e4408
renaming, adjust changelog
Frefreak Jul 6, 2021
af73898
various change
Frefreak Jul 7, 2021
401d125
lint
Frefreak Jul 7, 2021
d41de7d
fix godoc, change CHANGELOG and unexport test struct
Frefreak Jul 7, 2021
39af369
fix changelog PR reference, fix typo and inaccurate wordings
Frefreak Jul 8, 2021
049cd2e
unexport `NowFunc` & `SinceFunc`
Frefreak Jul 8, 2021
dcc82b0
Update sdk/trace/provider.go
Frefreak Jul 8, 2021
e80a1fe
Update CHANGELOG.md
Frefreak Jul 8, 2021
8340380
add "stopwatch" to clock
Frefreak Jul 9, 2021
3f1a87d
improve doc
Frefreak Jul 9, 2021
f506ac3
Merge remote-tracking branch 'origin/main' into clock
Frefreak Jul 9, 2021
b9250b3
lint
Frefreak Jul 10, 2021
c7c088b
change interface signature
Frefreak Jul 10, 2021
d1a5ae0
small refactor
Frefreak Jul 10, 2021
51e400e
doc
Frefreak Jul 10, 2021
d5514dd
remove one unnecessary allocation
Frefreak Jul 21, 2021
04ef13c
Merge branch 'main' into clock
Frefreak Jul 21, 2021
8075f98
remove duplicated changelog items
Frefreak Jul 21, 2021
4f68db3
remove unsed defaultStopwatch
Frefreak Jul 21, 2021
beba0cb
rename Elapsed to Stop and modify documentation
Frefreak Jul 29, 2021
1cb2208
fix doc
Frefreak Jul 30, 2021
3aee73f
Merge branch 'main' into clock
Frefreak Jul 30, 2021
ccb0eda
Merge branch 'main' into clock
Frefreak Aug 4, 2021
bffe943
Update sdk/trace/time.go
Frefreak Aug 6, 2021
e2d7e8f
update test
Frefreak Aug 6, 2021
6173f5c
add nilStopwatch
Frefreak Aug 13, 2021
a81a903
refactor test
Frefreak Aug 13, 2021
670c671
refactor test again
Frefreak Aug 13, 2021
5206913
lowercase "should"
Frefreak Aug 13, 2021
9ef9a5a
fix doc
Frefreak Aug 26, 2021
e924492
pass user provided timestamp to stopwatch
Frefreak Sep 14, 2021
2f86f78
Merge branch 'main' into clock
Frefreak Sep 14, 2021
094b868
fix
Frefreak Sep 14, 2021
498dc4f
modify CHANGELOG and format
Frefreak Sep 14, 2021
1139987
Merge branch 'main' into clock
Frefreak Jan 19, 2022
bfc222e
move CHANGELOG content to unreleased
Frefreak Jan 19, 2022
e5c647d
fix vanity-import-check
Frefreak Jan 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Changed

- The `SpanModels` function is now exported from the `go.opentelemetry.io/otel/exporters/zipkin` package to convert OpenTelemetry spans into Zipkin model spans. (#2027)
- Now `TraceProvider` includes a `Clock` field to provide span startTime/endTime generation. This defaults to use `time` module but users can provide their own implemention by calling `SetClock` to change it. (#2043)

### Deprecated

Expand Down
6 changes: 4 additions & 2 deletions sdk/internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"fmt"
"time"

tracetime "go.opentelemetry.io/otel/sdk/trace/time"

"go.opentelemetry.io/otel"
)

Expand All @@ -32,6 +34,6 @@ var UserAgent = fmt.Sprintf("opentelemetry-go/%s", otel.Version())
// the duration since start added back to start gives
// end as a monotonic time.
// See https://golang.org/pkg/time/#hdr-Monotonic_Clocks
func MonotonicEndTime(start time.Time) time.Time {
return start.Add(time.Since(start))
func MonotonicEndTime(start time.Time, clock tracetime.Clock) time.Time {
return start.Add(clock.Since(start))
}
11 changes: 11 additions & 0 deletions sdk/trace/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/resource"
tracetime "go.opentelemetry.io/otel/sdk/trace/time"
)

const (
Expand Down Expand Up @@ -61,6 +62,7 @@ type TracerProvider struct {
idGenerator IDGenerator
spanLimits SpanLimits
resource *resource.Resource
clock tracetime.Clock
}

var _ trace.TracerProvider = &TracerProvider{}
Expand Down Expand Up @@ -90,6 +92,7 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
idGenerator: o.idGenerator,
spanLimits: o.spanLimits,
resource: o.resource,
clock: tracetime.DefaultClock{},
}

for _, sp := range o.processors {
Expand All @@ -99,6 +102,14 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
return tp
}

// SetClock supports setting a mock clock for testing or some clock with custom
// time correction logic.
func (p *TracerProvider) SetClock(clock tracetime.Clock) {
p.mu.Lock()
defer p.mu.Unlock()
p.clock = clock
}
pellared marked this conversation as resolved.
Show resolved Hide resolved
pellared marked this conversation as resolved.
Show resolved Hide resolved

// Tracer returns a Tracer with the given name and options. If a Tracer for
// the given name and options does not exist it is created, otherwise the
// existing Tracer is returned.
Expand Down
4 changes: 2 additions & 2 deletions sdk/trace/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func (s *span) End(options ...trace.SpanEndOption) {

// Store the end time as soon as possible to avoid artificially increasing
// the span's duration in case some operation below takes a while.
et := internal.MonotonicEndTime(s.startTime)
et := internal.MonotonicEndTime(s.startTime, s.tracer.provider.clock)

// Do relative expensive check now that we have an end time and see if we
// need to do any more processing.
Expand Down Expand Up @@ -610,7 +610,7 @@ func startSpanInternal(ctx context.Context, tr *tracer, name string, o *trace.Sp

startTime := o.Timestamp()
if startTime.IsZero() {
startTime = time.Now()
startTime = tr.provider.clock.Now()
}
span.startTime = startTime

Expand Down
36 changes: 36 additions & 0 deletions sdk/trace/time/time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package time

import (
lib "time"
)

type Clock interface {
Now() lib.Time
Since(t lib.Time) lib.Duration
Frefreak marked this conversation as resolved.
Show resolved Hide resolved
}

type DefaultClock struct {
}

func (c DefaultClock) Now() lib.Time {
return lib.Now()
}
func (c DefaultClock) Since(t lib.Time) lib.Duration {
return lib.Since(t)
}

var _ Clock = DefaultClock{}
44 changes: 44 additions & 0 deletions sdk/trace/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,50 @@ func TestAddLinksWithMoreAttributesThanLimit(t *testing.T) {
}
}

type FrozenClock struct {
Frefreak marked this conversation as resolved.
Show resolved Hide resolved
now time.Time
}

// NewFrozenClock returns a clock which stops at time t
func NewFrozenClock(t time.Time) FrozenClock {
return FrozenClock{
now: t,
}
}

func (c FrozenClock) Now() time.Time {
return c.now
}

func (c FrozenClock) Since(time.Time) time.Duration {
return 0
}

func TestCustomClock(t *testing.T) {
te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
tracer := tp.Tracer("custom-clock")
now := time.Now()
time.Sleep(time.Microsecond * 3)
_, span := tracer.Start(context.Background(), "test-original-clock")
time.Sleep(time.Microsecond * 3)
span.End()
got := te.Spans()[0]
assert.True(t, now.Before(got.StartTime()))
assert.True(t, got.StartTime().Before(got.EndTime()))

te.Reset()

tp.SetClock(NewFrozenClock(now))
time.Sleep(time.Microsecond * 3)
_, span = tracer.Start(context.Background(), "test-frozen-clock")
time.Sleep(time.Microsecond * 3)
span.End()
got = te.Spans()[0]
assert.Equal(t, now, got.StartTime())
assert.Equal(t, now, got.EndTime())
}

type stateSampler struct {
prefix string
f func(trace.TraceState) trace.TraceState
Expand Down