Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit d48eb5d

Browse files
authored
Cherry-pick criticial fixes into 0.28.x branch for 0.28.3 release (#2073)
* Fix time skew exceptions crashing disruptor thread (#2071) * Add a fix to metric views when a time skew is detected rather than crashing the application/thread. * Add test for time-rewind issues, and fix problems discovered. * Mark ContextUtils as public (but deprecated) (#2072) * Mark ContextUtils as public (but deprecated) to fix bincompat issues with 0.17.x->0.18.x * Add an access mechanism for grpc context and update deprecation denotation. * Update changelog with latest releases.
1 parent ca93125 commit d48eb5d

File tree

7 files changed

+139
-9
lines changed

7 files changed

+139
-9
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
## Unreleased
22

3+
## 0.28.3 - 2021-01-12
4+
5+
- fix: Return public access to unsafe `ContextUtils` api. Remove bincompat issue from 0.27.1. (#2072)
6+
- fix: When time rewinds, avoid throwing exceptions and crashing the disruptor thread. (#2071)
7+
8+
## 0.28.2 - 2020-10-22
9+
10+
- feat: Make TracerImpl public for OpenTelemetry migration. (#2064)
11+
12+
Note: no binary available for 0.28.2
13+
14+
## 0.28.1 - 2020-10-21
15+
16+
- feat: Add Support for Opencensus to OpenTelemetry migration (#2059)
17+
18+
Breaking change: ContextUtils is no longer public
19+
20+
## 0.28.0 - 2020-10-21
21+
22+
- Remove finalize from RecordEventsSpanImpl (#2043)
23+
324
## 0.27.0 - 2020-08-14
425
- deps: update protobuf (#2029)
526
- Update release versions for all readme and build files. (#2028)

api/src/main/java/io/opencensus/trace/unsafe/ContextHandleUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.opencensus.trace.unsafe;
1818

19+
import io.grpc.Context;
1920
import io.opencensus.internal.Provider;
2021
import io.opencensus.trace.ContextHandle;
2122
import io.opencensus.trace.ContextManager;
@@ -76,4 +77,18 @@ public static ContextHandle withValue(
7677
public static Span getValue(ContextHandle context) {
7778
return CONTEXT_MANAGER.getValue(context);
7879
}
80+
81+
/**
82+
* Attempts to pull the {@link io.grpc.Context} out of an OpenCensus {@code ContextHandle}.
83+
*
84+
* @return The context, or null if not a GRPC backed context handle.
85+
*/
86+
@Nullable
87+
public static Context tryExtractGrpcContext(ContextHandle handle) {
88+
if (handle instanceof ContextHandleImpl) {
89+
return ((ContextHandleImpl) handle).getContext();
90+
}
91+
// TODO: see if we can do something for the OpenTelemetry shim.
92+
return null;
93+
}
7994
}

api/src/main/java/io/opencensus/trace/unsafe/ContextManagerImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ public ContextHandle currentContext() {
3131
}
3232

3333
@Override
34+
@SuppressWarnings({"deprecation"})
3435
public ContextHandle withValue(ContextHandle contextHandle, @Nullable Span span) {
3536
return wrapContext(ContextUtils.withValue(unwrapContext(contextHandle), span));
3637
}
3738

3839
@Override
40+
@SuppressWarnings({"deprecation"})
3941
public Span getValue(ContextHandle contextHandle) {
4042
return ContextUtils.getValue(unwrapContext(contextHandle));
4143
}

api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@
2626
*/
2727

2828
/**
29-
* Util methods/functionality to interact with the {@link io.grpc.Context}.
30-
*
31-
* <p>Users must interact with the current Context via the public APIs in {@link
32-
* io.opencensus.trace.Tracer} and avoid usages of the {@link #CONTEXT_SPAN_KEY} directly.
29+
* Utilities for grabbing manipulating current context and grabbing current span.
3330
*
31+
* @deprecated Please use {@link io.opencensus.trace.unsafe.ContextHandleUtils} Util
32+
* methods/functionality to interact with the {@link io.grpc.Context}. Users must interact with
33+
* the current Context via the public APIs in {@link io.opencensus.trace.Tracer} and avoid
34+
* usages of the {@link #CONTEXT_SPAN_KEY} directly.
3435
* @since 0.5
3536
*/
36-
final class ContextUtils {
37+
@Deprecated()
38+
public final class ContextUtils {
3739
// No instance of this class.
3840
private ContextUtils() {}
3941

api/src/test/java/io/opencensus/trace/unsafe/ContextUtilsTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,10 @@ public void testGetCurrentSpan_ContextSetToNull() {
4747
ContextHandleUtils.currentContext().detach(orig);
4848
}
4949
}
50+
51+
@Test
52+
public void testTryExtractGrpcContext_WillNotThrow() {
53+
assertThat(ContextHandleUtils.tryExtractGrpcContext(ContextHandleUtils.currentContext()))
54+
.isNotNull();
55+
}
5056
}

impl_core/src/main/java/io/opencensus/implcore/stats/MutableViewData.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ private CumulativeMutableViewData(View view, Timestamp start) {
132132
@javax.annotation.Nullable
133133
@Override
134134
Metric toMetric(Timestamp now, State state) {
135+
handleTimeRewinds(now);
135136
if (state == State.DISABLED) {
136137
return null;
137138
}
@@ -166,6 +167,7 @@ void record(
166167

167168
@Override
168169
ViewData toViewData(Timestamp now, State state) {
170+
handleTimeRewinds(now);
169171
if (state == State.ENABLED) {
170172
return ViewData.create(
171173
super.view,
@@ -180,6 +182,18 @@ ViewData toViewData(Timestamp now, State state) {
180182
}
181183
}
182184

185+
/**
186+
* This method attemps to migrate this view into a reasonable state in the event of time going
187+
* backwards.
188+
*/
189+
private void handleTimeRewinds(Timestamp now) {
190+
if (now.compareTo(start) < 0) {
191+
// Time went backwards, physics is broken, forget what we know.
192+
clearStats();
193+
start = now;
194+
}
195+
}
196+
183197
@Override
184198
void clearStats() {
185199
tagValueAggregationMap.clear();
@@ -304,10 +318,18 @@ private void refreshBucketList(Timestamp now) {
304318
}
305319
Timestamp startOfLastBucket =
306320
CheckerFrameworkUtils.castNonNull(buckets.peekLast()).getStart();
307-
// TODO(songya): decide what to do when time goes backwards
308-
checkArgument(
309-
now.compareTo(startOfLastBucket) >= 0,
310-
"Current time must be within or after the last bucket.");
321+
// Time went backwards! Physics has failed us! drop everything we know and relearn.
322+
// Prioritize: Report data we're confident is correct.
323+
if (now.compareTo(startOfLastBucket) < 0) {
324+
// TODO: configurable time-skew handling with options:
325+
// - Drop events in the future, keep others within a duration.
326+
// - Drop all events on skew
327+
// - Guess at time-skew and "fix" events
328+
// - Reset our "start" time to now if necessary.
329+
buckets.clear();
330+
shiftBucketList(N + 1, now);
331+
return;
332+
}
311333
long elapsedTimeMillis = now.subtractTimestamp(startOfLastBucket).toMillis();
312334
long numOfPadBuckets = elapsedTimeMillis / bucketDuration.toMillis();
313335

impl_core/src/test/java/io/opencensus/implcore/stats/MutableViewDataTest.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020

2121
import io.opencensus.common.Timestamp;
22+
import io.opencensus.implcore.internal.CurrentState;
23+
import io.opencensus.implcore.tags.TagMapImpl;
24+
import io.opencensus.metrics.data.AttachmentValue;
25+
import io.opencensus.stats.Aggregation;
26+
import io.opencensus.stats.Aggregation.Count;
27+
import io.opencensus.stats.Aggregation.Distribution;
28+
import io.opencensus.stats.BucketBoundaries;
29+
import io.opencensus.stats.Measure.MeasureDouble;
30+
import io.opencensus.stats.View;
31+
import io.opencensus.stats.ViewData;
32+
import io.opencensus.tags.TagKey;
33+
import java.util.Arrays;
34+
import java.util.Collections;
2235
import org.junit.Test;
2336
import org.junit.runner.RunWith;
2437
import org.junit.runners.JUnit4;
@@ -31,4 +44,53 @@ public class MutableViewDataTest {
3144
public void testConstants() {
3245
assertThat(MutableViewData.ZERO_TIMESTAMP).isEqualTo(Timestamp.create(0, 0));
3346
}
47+
48+
@Test
49+
public void testTimeRewindsOnCountViewNoThrow() {
50+
// First we set up some buckets THEN we rewind time for giggles.
51+
View tester =
52+
View.create(
53+
View.Name.create("view"),
54+
"Description",
55+
MeasureDouble.create("name", "desc", "us"),
56+
Count.create(),
57+
Collections.singletonList(TagKey.create("KEY")));
58+
Timestamp start = Timestamp.create(10000000, 0);
59+
Timestamp validPointTime = Timestamp.create(10000010, 0);
60+
CurrentState.State state = CurrentState.State.ENABLED;
61+
MutableViewData viewData = MutableViewData.create(tester, start);
62+
// Create a data points to get thrown away.
63+
viewData.record(
64+
TagMapImpl.EMPTY, 1.0, validPointTime, Collections.<String, AttachmentValue>emptyMap());
65+
// Rewind time and look for explosions.
66+
Timestamp thePast = Timestamp.create(0, 0);
67+
ViewData result = viewData.toViewData(thePast, state);
68+
assertThat(result.getAggregationMap()).isEmpty();
69+
}
70+
71+
@Test
72+
public void testTimeRewindsOnDistributionViewNoThrow() {
73+
// First we set up some buckets THEN we rewind time for giggles.
74+
Aggregation latencyDistribution =
75+
Distribution.create(
76+
BucketBoundaries.create(Arrays.asList(0.0, 25.0, 100.0, 200.0, 400.0, 800.0, 10000.0)));
77+
View tester =
78+
View.create(
79+
View.Name.create("view"),
80+
"Description",
81+
MeasureDouble.create("name", "desc", "us"),
82+
latencyDistribution,
83+
Collections.singletonList(TagKey.create("KEY")));
84+
Timestamp start = Timestamp.create(10000000, 0);
85+
Timestamp validPointTime = Timestamp.create(10000010, 0);
86+
CurrentState.State state = CurrentState.State.ENABLED;
87+
MutableViewData viewData = MutableViewData.create(tester, start);
88+
// Create a data points to get thrown away.
89+
viewData.record(
90+
TagMapImpl.EMPTY, 1.0, validPointTime, Collections.<String, AttachmentValue>emptyMap());
91+
// Rewind time and look for explosions.
92+
Timestamp thePast = Timestamp.create(0, 0);
93+
ViewData result = viewData.toViewData(thePast, state);
94+
assertThat(result.getAggregationMap()).isEmpty();
95+
}
3496
}

0 commit comments

Comments
 (0)