Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
SDI-1394 a metric can be changed from static to dynamic by setting na…
Browse files Browse the repository at this point in the history
…me parameter
  • Loading branch information
candysmurf committed Jun 13, 2016
1 parent 5192dc4 commit 899a42f
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 78 deletions.
2 changes: 1 addition & 1 deletion control/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func (mc *metricCatalog) removeMatchedKey(key string) {
func validateMetricNamespace(ns core.Namespace) error {
name := ""
for _, i := range ns {
name += i.Value
name += i.Value()
}
for _, chars := range notAllowedChars {
for _, ch := range chars {
Expand Down
36 changes: 36 additions & 0 deletions control/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,39 @@ func TestMetricNamespaceValidation(t *testing.T) {
})
})
}

func TestIsDynamicNamespace(t *testing.T) {
Convey("isDynamicNamespace()", t, func() {
Convey("has dynamic element", func() {
ns := core.NewNamespace("mock", "foo", "bar").AddDynamicElement("version", "the number of the version")
isDynamic, _ := ns.IsDynamic()
So(isDynamic, ShouldEqual, true)
})
Convey("has no dynamic element", func() {
ns := core.NewNamespace("mock", "foo").AddStaticElement("bar")
isDynamic, _ := ns.IsDynamic()
So(isDynamic, ShouldEqual, false)
})
Convey("is static but try to set name and desc", func() {
ns := core.NewNamespace("mock", "foo").AddStaticElement("bar")
nse := ns.Element(0)
nse.SetName("fake name")
nse.SetDescription("fake desc")
isDynamic, _ := ns.IsDynamic()
So(isDynamic, ShouldEqual, false)
})
Convey("is dynamic but try to change name and desc", func() {
ns := core.NewNamespace("mock", "foo").AddDynamicElement("bar", "the value of bar")
nse := ns.Element(2)
So(nse.Name(), ShouldEqual, "bar")
So(nse.Description(), ShouldEqual, "the value of bar")

nse.SetName("fake name")
nse.SetDescription("fake desc")
isDynamic, _ := ns.IsDynamic()
So(isDynamic, ShouldEqual, true)
So(nse.Name(), ShouldEqual, "fake name")
So(nse.Description(), ShouldEqual, "fake desc")
})
})
}
4 changes: 2 additions & 2 deletions control/mttrie.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ func (mtt *mttNode) Add(mt *metricType) {
if node.children == nil {
node.children = make(map[string]*mttNode)
}
node.children[n.Value] = &mttNode{}
node = node.children[n.Value]
node.children[n.Value()] = &mttNode{}
node = node.children[n.Value()]
}
node.mts = make(map[int]*metricType)
node.mts[mt.Version()] = mt
Expand Down
1 change: 1 addition & 0 deletions control/plugin/client/httpjsonrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ func (h *httpJSONRPCClient) GetMetricTypes(config plugin.ConfigType) ([]core.Met
if err != nil {
return nil, err
}

metrics := make([]core.Metric, len(mtr.MetricTypes))
for i, mt := range mtr.MetricTypes {
mt.LastAdvertisedTime_ = time.Now()
Expand Down
3 changes: 3 additions & 0 deletions control/plugin/client/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"crypto/rsa"
"encoding/gob"
"errors"
"fmt"
"net"
"net/rpc"
"time"
Expand Down Expand Up @@ -181,6 +182,8 @@ func (p *PluginNativeClient) GetMetricTypes(config plugin.ConfigType) ([]core.Me

args := plugin.GetMetricTypesArgs{PluginConfig: config}

fmt.Println("---args NATIVE---", args)

out, err := p.encoder.Encode(args)
if err != nil {
log.Error("error while encoding args for getmetrictypes :(")
Expand Down
2 changes: 1 addition & 1 deletion control/plugin/collector_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (p *mockPlugin) GetMetricTypes(cfg ConfigType) ([]MetricType, error) {
func (p *mockPlugin) CollectMetrics(mockMetricTypes []MetricType) ([]MetricType, error) {
for i := range mockMetricTypes {
if mockMetricTypes[i].Namespace().String() == "/foo/*/bar" {
mockMetricTypes[i].Namespace_[1].Value = "test"
mockMetricTypes[i].Namespace_[1].SetValue("test")
}
}
return mockMetricTypes, nil
Expand Down
4 changes: 2 additions & 2 deletions control/plugin/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ func NewPluginConfigType() ConfigType {
// Represents a metric type. Only used within plugins and across plugin calls.
// Converted to core.MetricType before being used within modules.
type MetricType struct {
// Namespace is the identifier for a metric.
Namespace_ []core.NamespaceElement `json:"namespace"`
// Namespace_ is the identifier for a metric.
Namespace_ core.Namespace `json:"namespace"`

// Last advertised time is the last time the snap agent was told about
// a metric.
Expand Down
204 changes: 159 additions & 45 deletions core/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,21 @@ limitations under the License.
package core

import (
"encoding/gob"
"encoding/json"
"reflect"
"strings"
"time"

"github.com/intelsdi-x/snap/control/plugin/cpolicy"
"github.com/intelsdi-x/snap/core/cdata"
)

// const defines contants
const (
DefaultName = "DefaultName"
)

var (
// Standard Tags are in added to the metric by the framework on plugin load.
// STD_TAG_PLUGIN_RUNNING_ON describes where the plugin is running (hostname).
Expand All @@ -45,8 +53,102 @@ type Metric interface {
Unit() string
}

// NamespaceElement defines the method set for the namespace elements
type NamespaceElement interface {
IsDynamic() bool
Value() string
Name() string
Description() string
SetValue(value string)
SetName(name string)
SetDescription(desc string)
}

// Namespace defines array of namespace elements
type Namespace []NamespaceElement

// DynamicElement defines the dynamic element of a namespace
type DynamicElement struct {
Value_ string
Description_ string
Name_ string
}

// StaticElement defines the static element of a namespace
type StaticElement struct {
Value_ string
}

// Value returns the string value of the static element
func (se *StaticElement) Value() string {
return se.Value_
}

// Name returns the empty string
func (se *StaticElement) Name() string {
return ""
}

// Description returns the empty string
func (se *StaticElement) Description() string {
return ""
}

// SetValue sets the element value
func (se *StaticElement) SetValue(value string) {
se.Value_ = value
}

// SetName returns for the static elements
func (se *StaticElement) SetName(name string) {
return
}

// SetDescription returns for the static elements
func (se *StaticElement) SetDescription(desc string) {
return
}

// IsDynamic returns false for the static element.
func (se *StaticElement) IsDynamic() bool {
return false
}

// Value returns the string value of the dynamic element
func (de *DynamicElement) Value() string {
return de.Value_
}

// Name returns the name of a dynamic element
func (de *DynamicElement) Name() string {
return de.Name_
}

// Description returns the description of a dynamic element
func (de *DynamicElement) Description() string {
return de.Description_
}

// SetValue sets the element value
func (de *DynamicElement) SetValue(value string) {
de.Value_ = value
}

// SetName sets the name of a dynamic element
func (de *DynamicElement) SetName(name string) {
de.Name_ = name
}

// SetDescription sets the description of a dynamic element
func (de *DynamicElement) SetDescription(desc string) {
de.Description_ = desc
}

// IsDynamic returns true
func (de *DynamicElement) IsDynamic() bool {
return true
}

// String returns the string representation of the namespace with "/" joining
// the elements of the namespace. A leading "/" is added.
func (n Namespace) String() string {
Expand All @@ -58,8 +160,8 @@ func (n Namespace) String() string {
// namespace.
func (n Namespace) Strings() []string {
var ns []string
for _, namespaceElement := range n {
ns = append(ns, namespaceElement.Value)
for _, elem := range n {
ns = append(ns, elem.Value())
}
return ns
}
Expand All @@ -70,88 +172,100 @@ func (n Namespace) Key() string {
return strings.Join(n.Strings(), ".")
}

// IsDynamic returns true if there is any element of the namespace which is
// dynamic. If the namespace is dynamic the second return value will contain
// an array of namespace elements (indexes) where there are dynamic namespace
// elements. A dynamic component of the namespace are those elements that
// contain variable data.
func (n Namespace) IsDynamic() (bool, []int) {
var idx []int
ret := false
for i := range n {
if n[i].IsDynamic() {
ret = true
idx = append(idx, i)
}
}
return ret, idx
}

// NewNamespace takes an array of strings and returns a Namespace. A Namespace
// is an array of NamespaceElements. The provided array of strings is used to
// set the corresponding Value fields in the array of NamespaceElements.
// set the corresponding Value fields in the array of StaticElements.
func NewNamespace(ns ...string) Namespace {
n := make([]NamespaceElement, len(ns))
for i, ns := range ns {
n[i] = NamespaceElement{Value: ns}
n[i] = &StaticElement{Value_: ns}
}
return n
}

// AddDynamicElement adds a dynamic element to the given Namespace. A dynamic
// NamespaceElement is defined by having a nonempty Name field.
func (n Namespace) AddDynamicElement(name, description string) Namespace {
nse := NamespaceElement{Name: name, Description: description, Value: "*"}
return append(n, nse)
nse := DynamicElement{Name_: name, Description_: description, Value_: "*"}
return append(n, &nse)
}

// AddStaticElement adds a static element to the given Namespace. A static
// NamespaceElement is defined by having an empty Name field.
func (n Namespace) AddStaticElement(value string) Namespace {
nse := NamespaceElement{Value: value}
return append(n, nse)
nse := StaticElement{Value_: value}
return append(n, &nse)
}

// AddStaticElements adds a static elements to the given Namespace. A static
// NamespaceElement is defined by having an empty Name field.
func (n Namespace) AddStaticElements(values ...string) Namespace {
for _, value := range values {
n = append(n, NamespaceElement{Value: value})
n = append(n, &StaticElement{Value_: value})
}
return n
}

// IsDynamic returns true if there is any element of the namespace which is
// dynamic. If the namespace is dynamic the second return value will contain
// an array of namespace elements (indexes) where there are dynamic namespace
// elements. A dynamic component of the namespace are those elements that
// contain variable data.
func (n Namespace) IsDynamic() (bool, []int) {
var idx []int
ret := false
for i := range n {
if n[i].IsDynamic() {
ret = true
idx = append(idx, i)
}
}
return ret, idx
}

// Element returns the NamespaceElement at the giving index
func (n Namespace) Element(idx int) NamespaceElement {
if idx >= 0 && idx < len(n) {
return n[idx]
}
return NamespaceElement{}
return &StaticElement{}
}

// NamespaceElement provides meta data related to the namespace. This is of particular importance when
// the namespace contains data.
type NamespaceElement struct {
Value string
Description string
Name string
// NamespaceJSON represents a persistable Namespace
type NamespaceJSON struct {
Type string
Data json.RawMessage
}

// NewNamespaceElement tasks a string and returns a NamespaceElement where the
// Value field is set to the provided string argument.
func NewNamespaceElement(e string) NamespaceElement {
if e != "" {
return NamespaceElement{Value: e}
// NewNamespaceJSON returns a new instance of NamespaceJSON object
func NewNamespaceJSON(v interface{}) (*NamespaceJSON, error) {
b, err := json.Marshal(v)
if err != nil {
return nil, err
}
return NamespaceElement{}
return &NamespaceJSON{
reflect.Indirect(reflect.ValueOf(v)).Type().Name(), b}, nil
}

// IsDynamic returns true if the namespace element contains data. A namespace
// element that has a nonempty Name field is considered dynamic.
func (n *NamespaceElement) IsDynamic() bool {
if n.Name != "" {
return true
// MarshalJSON marshals a Namespace into JSON
func (n Namespace) MarshalJSON() ([]byte, error) {
objs := []*NamespaceJSON{}
for _, elem := range n {
obj, _ := NewNamespaceJSON(elem)
objs = append(objs, obj)
}
return false
return json.Marshal(objs)
}

// UnmarshalJSON unmarshals JSON into a Namespace
func (n Namespace) UnmarshalJSON(data []byte) error {
objs := []*NamespaceJSON{}
return json.Unmarshal(data, &objs)
}

func init() {
gob.Register(&StaticElement{})
gob.Register(&DynamicElement{})
}

// RequestedMetric is a metric requested for collection
Expand Down
Loading

0 comments on commit 899a42f

Please sign in to comment.