All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.hystrix.metric.consumer.BucketedCounterStream Maven / Gradle / Ivy

There is a newer version: 1.5.18
Show newest version
/**
 * Copyright 2015 Netflix, Inc.
 * 

* 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 com.netflix.hystrix.metric.consumer; import com.netflix.hystrix.metric.HystrixEvent; import com.netflix.hystrix.metric.HystrixEventStream; import rx.Observable; import rx.Subscription; import rx.functions.Func0; import rx.functions.Func1; import rx.functions.Func2; import rx.subjects.BehaviorSubject; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; /** * Abstract class that imposes a bucketing structure and provides streams of buckets * * @param type of raw data that needs to get summarized into a bucket * @param type of data contained in each bucket * @param type of data emitted to stream subscribers (often is the same as A but does not have to be) */ public abstract class BucketedCounterStream { protected final int numBuckets; protected final Observable bucketedStream; protected final AtomicReference subscription = new AtomicReference(null); private final Func1, Observable> reduceBucketToSummary; private final BehaviorSubject counterSubject = BehaviorSubject.create(getEmptyOutputValue()); protected BucketedCounterStream(final HystrixEventStream inputEventStream, final int numBuckets, final int bucketSizeInMs, final Func2 appendRawEventToBucket) { this.numBuckets = numBuckets; this.reduceBucketToSummary = new Func1, Observable>() { @Override public Observable call(Observable eventBucket) { return eventBucket.reduce(getEmptyBucketSummary(), appendRawEventToBucket); } }; final List emptyEventCountsToStart = new ArrayList(); for (int i = 0; i < numBuckets; i++) { emptyEventCountsToStart.add(getEmptyBucketSummary()); } this.bucketedStream = Observable.defer(new Func0>() { @Override public Observable call() { return inputEventStream .observe() .window(bucketSizeInMs, TimeUnit.MILLISECONDS) //bucket it by the counter window so we can emit to the next operator in time chunks, not on every OnNext .flatMap(reduceBucketToSummary) //for a given bucket, turn it into a long array containing counts of event types .startWith(emptyEventCountsToStart); //start it with empty arrays to make consumer logic as generic as possible (windows are always full) } }); } abstract Bucket getEmptyBucketSummary(); abstract Output getEmptyOutputValue(); /** * Return the stream of buckets * @return stream of buckets */ public abstract Observable observe(); public void startCachingStreamValuesIfUnstarted() { if (subscription.get() == null) { //the stream is not yet started Subscription candidateSubscription = observe().subscribe(counterSubject); if (subscription.compareAndSet(null, candidateSubscription)) { //won the race to set the subscription } else { //lost the race to set the subscription, so we need to cancel this one candidateSubscription.unsubscribe(); } } } /** * Synchronous call to retrieve the last calculated bucket without waiting for any emissions * @return last calculated bucket */ public Output getLatest() { startCachingStreamValuesIfUnstarted(); if (counterSubject.hasValue()) { return counterSubject.getValue(); } else { return getEmptyOutputValue(); } } public void unsubscribe() { Subscription s = subscription.get(); if (s != null) { s.unsubscribe(); subscription.compareAndSet(s, null); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy