/**
 * Copyright 2018, OpenCensus 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.
 */ import * as defaultLogger from '../common/console-logger' ; import * as loggerTypes from '../common/types' ; import { StatsEventListener } from '../exporters/types' ; import * as cls from '../internal/cls' ; import { Metric } from '../metrics/export/types' ; import { Metrics } from '../metrics/metrics' ; import { TagMap } from '../tags/tag-map' ; import * as tagger from '../tags/tagger' ; import { TagKey } from '../tags/types' ; import { MetricProducerForStats } from './metric-producer' ; import { AggregationType , Measure , Measurement , MeasureType , MeasureUnit , Stats , View , } from './types' ; import { BaseView } from './view' ; export class BaseStats implements Stats { /** A list of Stats exporters */ private statsEventListeners : StatsEventListener [ ] = [ ] ; /** A map of Measures (name) to their corresponding Views */ private registeredViews : { [ key ] : View [ ] ; } = { } ; /** An object to log information to */ private logger : loggerTypes . Logger ; /** Singleton instance */ private static singletonInstance : BaseStats ; /** Manage context automatic propagation */ private contextManager : cls . Namespace ; param logger constructor ( logger = defaultLogger ) { this . logger = logger . logger ( ) ; this . contextManager = cls . getNamespace ( ) ; const metricProducer = new MetricProducerForStats ( this ) ; Metrics . getMetricProducerManager ( ) . add ( metricProducer ) ; } /** Gets the stats instance. */ static get instance ( ) : Stats { return this . singletonInstance || ( this . singletonInstance = new this ( ) ) ; } param view registerView ( view ) { if ( this . registeredViews [ view . measure . name ] ) { this . registeredViews [ view . measure . name ] . push ( view ) ; } else { this . registeredViews [ view . measure . name ] = [ view ] ; } view . registered = true ; for ( const exporter of this . statsEventListeners ) { exporter . onRegisterView ( view ) ; } } param name param measure param aggregation param tagKeys param description param bucketBoundaries createView ( name , measure , aggregation , tagKeys , description , bucketBoundaries ? ) { const view = new BaseView ( name , measure , aggregation , tagKeys , description , bucketBoundaries ) ; return view ; } param exporter registerExporter ( exporter ) { this . statsEventListeners . push ( exporter ) ; for ( const measureName of Object . keys ( this . registeredViews ) ) { for ( const view of this . registeredViews [ measureName ] ) { exporter . onRegisterView ( view ) ; } } exporter . start ( ) ; } param exporter unregisterExporter ( exporter ) { if ( exporter ) { this . statsEventListeners = this . statsEventListeners . filter ( currentExporter => currentExporter !== exporter ) ; exporter . stop ( ) ; } } param name param unit param description createMeasureDouble ( name , unit , description ? ) { return { name , unit , type : MeasureType . DOUBLE , description } ; } param name param unit param description createMeasureInt64 ( name , unit , description ? ) { return { name , unit , type : MeasureType . INT64 , description } ; } param measurements returns private hasNegativeValue ( measurements ) { return measurements . some ( measurement => measurement . value < 0 ) ; } returns getMetrics ( ) { const metrics = [ ] ; for ( const measureName of Object . keys ( this . registeredViews ) ) { for ( const view of this . registeredViews [ measureName ] ) { metrics . push ( view . getMetric ( view . startTime ) ) ; } } return metrics ; } param measurements param tags param attachments record ( measurements , tags ? , attachments ? ) { if ( this . hasNegativeValue ( measurements ) ) { this . logger . warn ( `Dropping measurments ${ measurements }, value to record
          must be non-negative.` ) ; return ; } if ( ! tags ) { tags = this . getCurrentTagContext ( ) ; } for ( const measurement of measurements ) { const views = this . registeredViews [ measurement . measure . name ] ; if ( ! views ) { break ; } for ( const view of views ) { view . recordMeasurement ( measurement , tags , attachments ) ; } for ( const exporter of this . statsEventListeners ) { exporter . onRecord ( views , measurement , tags . tags ) ; } } } /**
     * Remove all registered Views and exporters from the stats.
     */ clear ( ) { this . registeredViews = { } ; this . statsEventListeners = [ ] ; } param tags param fn returns withTagContext < T > ( tags , fn ) { return tagger . withTagContext < T > ( this . contextManager , tags , fn ) ; } /** Gets the current tag context. */ getCurrentTagContext ( ) { return tagger . getCurrentTagContext ( this . contextManager ) ; } }