func startCollector( appStats *datastructs.ApplicationStatuses, connectionErrors *connectionErrorsType, totalCounts totalCountUpdaterType, metricNameAdder suggest.Adder, memoryChecker memoryCheckerType) { collector.SetConcurrentPolls(*fPollCount) collector.SetConcurrentConnects(*fConnectionCount) sweepDurationDist := tricorder.NewGeometricBucketer(1, 100000.0).NewCumulativeDistribution() collectionBucketer := tricorder.NewGeometricBucketer(1e-4, 100.0) collectionTimesDist := collectionBucketer.NewCumulativeDistribution() tricorderCollectionTimesDist := collectionBucketer.NewCumulativeDistribution() snmpCollectionTimesDist := collectionBucketer.NewCumulativeDistribution() jsonCollectionTimesDist := collectionBucketer.NewCumulativeDistribution() changedMetricsPerEndpointDist := tricorder.NewGeometricBucketer(1.0, 10000.0).NewCumulativeDistribution() if err := tricorder.RegisterMetric( "collector/collectionTimes", collectionTimesDist, units.Second, "Collection Times"); err != nil { log.Fatal(err) } if err := tricorder.RegisterMetric( "collector/collectionTimes_tricorder", tricorderCollectionTimesDist, units.Second, "Tricorder Collection Times"); err != nil { log.Fatal(err) } if err := tricorder.RegisterMetric( "collector/collectionTimes_snmp", snmpCollectionTimesDist, units.Second, "SNMP Collection Times"); err != nil { log.Fatal(err) } if err := tricorder.RegisterMetric( "collector/collectionTimes_json", jsonCollectionTimesDist, units.Second, "JSON Collection Times"); err != nil { log.Fatal(err) } if err := tricorder.RegisterMetric( "collector/changedMetricsPerEndpoint", changedMetricsPerEndpointDist, units.None, "Changed metrics per sweep"); err != nil { log.Fatal(err) } if err := tricorder.RegisterMetric( "collector/sweepDuration", sweepDurationDist, units.Millisecond, "Sweep duration"); err != nil { log.Fatal(err) } programStartTime := time.Now() if err := tricorder.RegisterMetric( "collector/elapsedTime", func() time.Duration { return time.Now().Sub(programStartTime) }, units.Second, "elapsed time"); err != nil { log.Fatal(err) } byProtocolDist := map[string]*tricorder.CumulativeDistribution{ "tricorder": tricorderCollectionTimesDist, "snmp": snmpCollectionTimesDist, "json": jsonCollectionTimesDist, } // Metric collection goroutine. Collect metrics periodically. go func() { // We assign each endpoint its very own nameSetType instance // to store metric names already sent to suggest. // Only that endpoint's fetch goroutine reads and modifies // the contents of its nameSetType instance. Although // this goroutine creates nameSetType instances and manages // the references to them, it never reads or modifies the // contents of any nameSetType instance after creating it. endpointToNamesSentToSuggest := make( map[*collector.Endpoint]nameSetType) for { endpoints, metricStore := appStats.ActiveEndpointIds() sweepTime := time.Now() for _, endpoint := range endpoints { namesSentToSuggest := endpointToNamesSentToSuggest[endpoint] if namesSentToSuggest == nil { namesSentToSuggest = make(nameSetType) endpointToNamesSentToSuggest[endpoint] = namesSentToSuggest } logger := &loggerType{ Store: metricStore, AppStats: appStats, ConnectionErrors: connectionErrors, CollectionTimesDist: collectionTimesDist, ByProtocolDist: byProtocolDist, ChangedMetricsDist: changedMetricsPerEndpointDist, NamesSentToSuggest: namesSentToSuggest, MetricNameAdder: metricNameAdder, TotalCounts: totalCounts, } endpoint.Poll(sweepTime, logger) } sweepDuration := time.Now().Sub(sweepTime) sweepDurationDist.Add(sweepDuration) memoryChecker.Check() if sweepDuration < *fCollectionFrequency { time.Sleep((*fCollectionFrequency) - sweepDuration) } } }() }