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

Commit

Permalink
Make stats.{Int,Float}64 never return errors (#552)
Browse files Browse the repository at this point in the history
Updates: #544
  • Loading branch information
Ramon Nogueira committed Mar 23, 2018
1 parent 6e3f034 commit d1d14e4
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 255 deletions.
5 changes: 0 additions & 5 deletions internal/readme/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ func statsExamples() {
log.Fatal(err)
}

m := stats.FindMeasure("my.org/video_size")
if m == nil {
log.Fatalln("measure not found")
}

// START aggs
distAgg := view.Distribution(0, 1<<32, 2<<32, 3<<32)
countAgg := view.Count()
Expand Down
74 changes: 19 additions & 55 deletions stats/measure.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@
package stats

import (
"errors"
"fmt"
"sync"
"sync/atomic"

"go.opencensus.io/stats/internal"
)

// Measure represents a type of metric to be tracked and recorded.
Expand All @@ -38,69 +34,47 @@ type Measure interface {
Name() string
Description() string
Unit() string

subscribe()
subscribed() bool
}

type measure struct {
// measureDescriptor is the untyped descriptor associated with each measure.
// Int64Measure and Float64Measure wrap measureDescriptor to provide typed
// recording APIs.
// Two Measures with the same name will have the same measureDescriptor.
type measureDescriptor struct {
subs int32 // access atomically

name string
description string
unit string
}

func (m *measure) subscribe() {
func (m *measureDescriptor) subscribe() {
atomic.StoreInt32(&m.subs, 1)
}

func (m *measure) subscribed() bool {
func (m *measureDescriptor) subscribed() bool {
return atomic.LoadInt32(&m.subs) == 1
}

// Name returns the name of the measure.
func (m *measure) Name() string {
return m.name
}

// Description returns the description of the measure.
func (m *measure) Description() string {
return m.description
}

// Unit returns the unit of the measure.
func (m *measure) Unit() string {
return m.unit
}

var (
mu sync.RWMutex
measures = make(map[string]Measure)
)

var (
errDuplicate = errors.New("duplicate measure name")
errMeasureNameTooLong = fmt.Errorf("measure name cannot be longer than %v", internal.MaxNameLength)
measures = make(map[string]*measureDescriptor)
)

// FindMeasure finds the Measure instance, if any, associated with the given name.
func FindMeasure(name string) Measure {
mu.RLock()
m := measures[name]
mu.RUnlock()
return m
}

func register(m Measure) (Measure, error) {
key := m.Name()
func registerMeasureHandle(name, desc, unit string) *measureDescriptor {
mu.Lock()
defer mu.Unlock()
if stored, ok := measures[key]; ok {
return stored, errDuplicate

if stored, ok := measures[name]; ok {
return stored
}
m := &measureDescriptor{
name: name,
description: desc,
unit: unit,
}
measures[key] = m
return m, nil
measures[name] = m
return m
}

// Measurement is the numeric value measured when recording stats. Each measure
Expand All @@ -120,13 +94,3 @@ func (m Measurement) Value() float64 {
func (m Measurement) Measure() Measure {
return m.m
}

func checkName(name string) error {
if len(name) > internal.MaxNameLength {
return errMeasureNameTooLong
}
if !internal.IsPrintable(name) {
return errors.New("measure name needs to be an ASCII string")
}
return nil
}
39 changes: 17 additions & 22 deletions stats/measure_float64.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,36 @@ package stats

// Float64Measure is a measure of type float64.
type Float64Measure struct {
measure
md *measureDescriptor
}

func (m *Float64Measure) subscribe() {
m.measure.subscribe()
// Name returns the name of the measure.
func (m *Float64Measure) Name() string {
return m.md.name
}

func (m *Float64Measure) subscribed() bool {
return m.measure.subscribed()
// Description returns the description of the measure.
func (m *Float64Measure) Description() string {
return m.md.description
}

// Unit returns the unit of the measure.
func (m *Float64Measure) Unit() string {
return m.md.unit
}

// M creates a new float64 measurement.
// Use Record to record measurements.
func (m *Float64Measure) M(v float64) Measurement {
if !m.subscribed() {
if !m.md.subscribed() {
return Measurement{}
}
return Measurement{m: m, v: v}
}

// Float64 creates a new measure of type Float64Measure. It returns
// an error if a measure with the same name already exists.
// Float64 creates a new measure of type Float64Measure.
// It never returns an error.
func Float64(name, description, unit string) (*Float64Measure, error) {
if err := checkName(name); err != nil {
return nil, err
}
m := &Float64Measure{
measure: measure{
name: name,
description: description,
unit: unit,
},
}
if _, err := register(m); err != nil {
return nil, err
}
return m, nil
mi := registerMeasureHandle(name, description, unit)
return &Float64Measure{mi}, nil
}
39 changes: 17 additions & 22 deletions stats/measure_int64.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,36 @@ package stats

// Int64Measure is a measure of type int64.
type Int64Measure struct {
measure
md *measureDescriptor
}

func (m *Int64Measure) subscribe() {
m.measure.subscribe()
// Name returns the name of the measure.
func (m *Int64Measure) Name() string {
return m.md.name
}

func (m *Int64Measure) subscribed() bool {
return m.measure.subscribed()
// Description returns the description of the measure.
func (m *Int64Measure) Description() string {
return m.md.description
}

// Unit returns the unit of the measure.
func (m *Int64Measure) Unit() string {
return m.md.unit
}

// M creates a new int64 measurement.
// Use Record to record measurements.
func (m *Int64Measure) M(v int64) Measurement {
if !m.subscribed() {
if !m.md.subscribed() {
return Measurement{}
}
return Measurement{m: m, v: float64(v)}
}

// Int64 creates a new measure of type Int64Measure. It returns an
// error if a measure with the same name already exists.
// Int64 creates a new measure of type Int64Measure.
// It never returns an error.
func Int64(name, description, unit string) (*Int64Measure, error) {
if err := checkName(name); err != nil {
return nil, err
}
m := &Int64Measure{
measure: measure{
name: name,
description: description,
unit: unit,
},
}
if _, err := register(m); err != nil {
return nil, err
}
return m, nil
mi := registerMeasureHandle(name, description, unit)
return &Int64Measure{mi}, nil
}
108 changes: 0 additions & 108 deletions stats/measure_test.go

This file was deleted.

Loading

0 comments on commit d1d14e4

Please sign in to comment.