• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.stats;
18 
19 import io.opencensus.common.Functions;
20 import io.opencensus.common.Timestamp;
21 import io.opencensus.internal.Utils;
22 import io.opencensus.stats.Measure.MeasureDouble;
23 import io.opencensus.stats.Measure.MeasureLong;
24 import io.opencensus.tags.TagContext;
25 import io.opencensus.tags.TagValue;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import javax.annotation.concurrent.GuardedBy;
34 import javax.annotation.concurrent.Immutable;
35 import javax.annotation.concurrent.ThreadSafe;
36 
37 /*>>>
38 import org.checkerframework.checker.nullness.qual.Nullable;
39 */
40 
41 /** No-op implementations of stats classes. */
42 final class NoopStats {
43 
NoopStats()44   private NoopStats() {}
45 
46   /**
47    * Returns a {@code StatsComponent} that has a no-op implementation for {@link StatsRecorder}.
48    *
49    * @return a {@code StatsComponent} that has a no-op implementation for {@code StatsRecorder}.
50    */
newNoopStatsComponent()51   static StatsComponent newNoopStatsComponent() {
52     return new NoopStatsComponent();
53   }
54 
55   /**
56    * Returns a {@code StatsRecorder} that does not record any data.
57    *
58    * @return a {@code StatsRecorder} that does not record any data.
59    */
getNoopStatsRecorder()60   static StatsRecorder getNoopStatsRecorder() {
61     return NoopStatsRecorder.INSTANCE;
62   }
63 
64   /**
65    * Returns a {@code MeasureMap} that ignores all calls to {@link MeasureMap#put}.
66    *
67    * @return a {@code MeasureMap} that ignores all calls to {@code MeasureMap#put}.
68    */
getNoopMeasureMap()69   static MeasureMap getNoopMeasureMap() {
70     return NoopMeasureMap.INSTANCE;
71   }
72 
73   /**
74    * Returns a {@code ViewManager} that maintains a map of views, but always returns empty {@link
75    * ViewData}s.
76    *
77    * @return a {@code ViewManager} that maintains a map of views, but always returns empty {@code
78    *     ViewData}s.
79    */
newNoopViewManager()80   static ViewManager newNoopViewManager() {
81     return new NoopViewManager();
82   }
83 
84   @ThreadSafe
85   private static final class NoopStatsComponent extends StatsComponent {
86     private final ViewManager viewManager = newNoopViewManager();
87     private volatile boolean isRead;
88 
89     @Override
getViewManager()90     public ViewManager getViewManager() {
91       return viewManager;
92     }
93 
94     @Override
getStatsRecorder()95     public StatsRecorder getStatsRecorder() {
96       return getNoopStatsRecorder();
97     }
98 
99     @Override
getState()100     public StatsCollectionState getState() {
101       isRead = true;
102       return StatsCollectionState.DISABLED;
103     }
104 
105     @Override
106     @Deprecated
setState(StatsCollectionState state)107     public void setState(StatsCollectionState state) {
108       Utils.checkNotNull(state, "state");
109       Utils.checkState(!isRead, "State was already read, cannot set state.");
110     }
111   }
112 
113   @Immutable
114   private static final class NoopStatsRecorder extends StatsRecorder {
115     static final StatsRecorder INSTANCE = new NoopStatsRecorder();
116 
117     @Override
newMeasureMap()118     public MeasureMap newMeasureMap() {
119       return getNoopMeasureMap();
120     }
121   }
122 
123   @Immutable
124   private static final class NoopMeasureMap extends MeasureMap {
125     static final MeasureMap INSTANCE = new NoopMeasureMap();
126 
127     @Override
put(MeasureDouble measure, double value)128     public MeasureMap put(MeasureDouble measure, double value) {
129       return this;
130     }
131 
132     @Override
put(MeasureLong measure, long value)133     public MeasureMap put(MeasureLong measure, long value) {
134       return this;
135     }
136 
137     @Override
record()138     public void record() {}
139 
140     @Override
record(TagContext tags)141     public void record(TagContext tags) {
142       Utils.checkNotNull(tags, "tags");
143     }
144   }
145 
146   @ThreadSafe
147   private static final class NoopViewManager extends ViewManager {
148     private static final Timestamp ZERO_TIMESTAMP = Timestamp.create(0, 0);
149 
150     @GuardedBy("registeredViews")
151     private final Map<View.Name, View> registeredViews = new HashMap<View.Name, View>();
152 
153     // Cached set of exported views. It must be set to null whenever a view is registered or
154     // unregistered.
155     @javax.annotation.Nullable private volatile Set<View> exportedViews;
156 
157     @Override
registerView(View newView)158     public void registerView(View newView) {
159       Utils.checkNotNull(newView, "newView");
160       synchronized (registeredViews) {
161         exportedViews = null;
162         View existing = registeredViews.get(newView.getName());
163         Utils.checkArgument(
164             existing == null || newView.equals(existing),
165             "A different view with the same name already exists.");
166         if (existing == null) {
167           registeredViews.put(newView.getName(), newView);
168         }
169       }
170     }
171 
172     @Override
173     @javax.annotation.Nullable
174     @SuppressWarnings("deprecation")
getView(View.Name name)175     public ViewData getView(View.Name name) {
176       Utils.checkNotNull(name, "name");
177       synchronized (registeredViews) {
178         View view = registeredViews.get(name);
179         if (view == null) {
180           return null;
181         } else {
182           return ViewData.create(
183               view,
184               Collections.<List</*@Nullable*/ TagValue>, AggregationData>emptyMap(),
185               view.getWindow()
186                   .match(
187                       Functions.<ViewData.AggregationWindowData>returnConstant(
188                           ViewData.AggregationWindowData.CumulativeData.create(
189                               ZERO_TIMESTAMP, ZERO_TIMESTAMP)),
190                       Functions.<ViewData.AggregationWindowData>returnConstant(
191                           ViewData.AggregationWindowData.IntervalData.create(ZERO_TIMESTAMP)),
192                       Functions.<ViewData.AggregationWindowData>throwAssertionError()));
193         }
194       }
195     }
196 
197     @Override
getAllExportedViews()198     public Set<View> getAllExportedViews() {
199       Set<View> views = exportedViews;
200       if (views == null) {
201         synchronized (registeredViews) {
202           exportedViews = views = filterExportedViews(registeredViews.values());
203         }
204       }
205       return views;
206     }
207 
208     // Returns the subset of the given views that should be exported
209     @SuppressWarnings("deprecation")
filterExportedViews(Collection<View> allViews)210     private static Set<View> filterExportedViews(Collection<View> allViews) {
211       Set<View> views = new HashSet<View>();
212       for (View view : allViews) {
213         if (view.getWindow() instanceof View.AggregationWindow.Interval) {
214           continue;
215         }
216         views.add(view);
217       }
218       return Collections.unmodifiableSet(views);
219     }
220   }
221 }
222