Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Commit

Permalink
add metric producer manager. (#1039)
Browse files Browse the repository at this point in the history
* add metric producer manager.

* added immutable test and removed contains method.

* fix fmt and lint.

* fix immutability.

* add nil check and fix test.

* fix review comment.
  • Loading branch information
rghetia committed Mar 4, 2019
1 parent dc0ac5c commit f305e5c
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 2 deletions.
89 changes: 89 additions & 0 deletions metric/producer/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2019, 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.

package producer

import (
"sync"
)

type manager struct {
mu sync.RWMutex
producers map[Producer]struct{}
}

var prodMgr *manager
var once sync.Once

func getManager() *manager {
once.Do(func() {
prodMgr = &manager{}
prodMgr.producers = make(map[Producer]struct{})
})
return prodMgr
}

// Add adds the producer to the manager if it is not already present.
// The manager maintains the list of active producers. It provides
// this list to a reader to read metrics from each producer and then export.
func Add(producer Producer) {
if producer == nil {
return
}
pm := getManager()
pm.add(producer)
}

// Delete deletes the producer from the manager if it is present.
func Delete(producer Producer) {
if producer == nil {
return
}
pm := getManager()
pm.delete(producer)
}

// GetAll returns a slice of all producer currently registered with
// the manager. For each call it generates a new slice. The slice
// should not be cached as registration may change at any time. It is
// typically called periodically by exporter to read metrics from
// the producers.
func GetAll() []Producer {
pm := getManager()
return pm.getAll()
}

func (pm *manager) getAll() []Producer {
pm.mu.Lock()
defer pm.mu.Unlock()
producers := make([]Producer, len(pm.producers))
i := 0
for producer := range pm.producers {
producers[i] = producer
i++
}
return producers
}

func (pm *manager) add(producer Producer) {
pm.mu.Lock()
defer pm.mu.Unlock()
pm.producers[producer] = struct{}{}
}

func (pm *manager) delete(producer Producer) {
pm.mu.Lock()
defer pm.mu.Unlock()
delete(pm.producers, producer)
}
147 changes: 147 additions & 0 deletions metric/producer/manager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright 2019, 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.

package producer

import (
"testing"

"go.opencensus.io/metric/metricdata"
)

type testProducer struct {
name string
}

var (
myProd1 = newTestProducer("foo")
myProd2 = newTestProducer("bar")
myProd3 = newTestProducer("foobar")
)

func newTestProducer(name string) *testProducer {
return &testProducer{name}
}

func (mp *testProducer) Read() []*metricdata.Metric {
return nil
}

func TestAdd(t *testing.T) {
Add(myProd1)
Add(myProd2)

got := GetAll()
want := []*testProducer{myProd1, myProd2}
checkSlice(got, want, t)
deleteAll()
}

func TestAddExisting(t *testing.T) {
Add(myProd1)
Add(myProd2)
Add(myProd1)

got := GetAll()
want := []*testProducer{myProd2, myProd1}
checkSlice(got, want, t)
deleteAll()
}

func TestAddNil(t *testing.T) {
Add(nil)

got := GetAll()
want := []*testProducer{}
checkSlice(got, want, t)
deleteAll()
}

func TestDelete(t *testing.T) {
Add(myProd1)
Add(myProd2)
Add(myProd3)
Delete(myProd2)

got := GetAll()
want := []*testProducer{myProd1, myProd3}
checkSlice(got, want, t)
deleteAll()
}

func TestDeleteNonExisting(t *testing.T) {
Add(myProd1)
Add(myProd3)
Delete(myProd2)

got := GetAll()
want := []*testProducer{myProd1, myProd3}
checkSlice(got, want, t)
deleteAll()
}

func TestDeleteNil(t *testing.T) {
Add(myProd1)
Add(myProd3)
Delete(nil)

got := GetAll()
want := []*testProducer{myProd1, myProd3}
checkSlice(got, want, t)
deleteAll()
}

func TestGetAllNil(t *testing.T) {
got := GetAll()
want := []*testProducer{}
checkSlice(got, want, t)
deleteAll()
}

func TestImmutableProducerList(t *testing.T) {
Add(myProd1)
Add(myProd2)

producersToMutate := GetAll()
producersToMutate[0] = myProd3
got := GetAll()
want := []*testProducer{myProd1, myProd2}
checkSlice(got, want, t)
deleteAll()
}

func checkSlice(got []Producer, want []*testProducer, t *testing.T) {
gotLen := len(got)
wantLen := len(want)
if gotLen != wantLen {
t.Errorf("got len: %d want: %d\n", gotLen, wantLen)
} else {
gotMap := map[Producer]struct{}{}
for i := 0; i < gotLen; i++ {
gotMap[got[i]] = struct{}{}
}
for i := 0; i < wantLen; i++ {
delete(gotMap, want[i])
}
if len(gotMap) > 0 {
t.Errorf("got %v, want %v\n", got, want)
}
}
}

func deleteAll() {
Delete(myProd1)
Delete(myProd2)
Delete(myProd3)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018, OpenCensus Authors
// Copyright 2019, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package metricexport
package producer

import (
"go.opencensus.io/metric/metricdata"
Expand Down

0 comments on commit f305e5c

Please sign in to comment.