コード例 #1
0
ファイル: grpc.go プロジェクト: yxzoro/snap
func (g *grpcClient) CollectMetrics(mts []core.Metric) ([]core.Metric, error) {
	arg := &rpc.CollectMetricsArg{
		Metrics: common.NewMetrics(mts),
	}
	reply, err := g.collector.CollectMetrics(getContext(g.timeout), arg)

	if err != nil {
		return nil, err
	}

	if reply.Error != "" {
		return nil, errors.New(reply.Error)
	}

	metrics := common.ToCoreMetrics(reply.Metrics)
	var results []core.Metric
	// Convert it to plugin.MetricType because scheduler/job.go checks that is the type before encoding
	// and sending to the plugin.
	//TODO(CDR): Decide what to do here if/when content-type handling is refactored
	for _, metric := range metrics {
		mt := plugin.MetricType{
			Namespace_:          metric.Namespace(),
			LastAdvertisedTime_: metric.LastAdvertisedTime(),
			Version_:            metric.Version(),
			Config_:             metric.Config(),
			Data_:               metric.Data(),
			Tags_:               metric.Tags(),
			Unit_:               metric.Unit(),
			Description_:        metric.Description(),
			Timestamp_:          metric.Timestamp(),
		}
		results = append(results, mt)
	}
	return results, nil
}
コード例 #2
0
ファイル: controlproxy.go プロジェクト: lynxbat/snap
func depsRequest(taskID string, mts []core.Metric, plugins []core.Plugin) *rpc.SubscribeDepsRequest {
	req := &rpc.SubscribeDepsRequest{
		Metrics: common.NewMetrics(mts),
		Plugins: common.ToCorePluginsMsg(plugins),
		TaskId:  taskID,
	}
	return req
}
コード例 #3
0
ファイル: controlproxy.go プロジェクト: lynxbat/snap
func (c ControlProxy) ValidateDeps(mts []core.Metric, plugins []core.SubscribedPlugin) []serror.SnapError {
	req := &rpc.ValidateDepsRequest{
		Metrics: common.NewMetrics(mts),
		Plugins: common.ToSubPluginsMsg(plugins),
	}
	reply, err := c.Client.ValidateDeps(getContext(), req)
	if err != nil {
		return []serror.SnapError{serror.New(err)}
	}
	serrs := common.ConvertSnapErrors(reply.Errors)
	return serrs
}
コード例 #4
0
ファイル: control_grpc_server.go プロジェクト: IRCody/snap
func (pc *ControlGRPCServer) ProcessMetrics(ctx context.Context, r *rpc.PubProcMetricsRequest) (*rpc.ProcessMetricsReply, error) {
	metrics := common.ToCoreMetrics(r.Metrics)
	mts, errs := pc.control.ProcessMetrics(
		metrics,
		common.ParseConfig(r.Config),
		r.TaskId, r.PluginName,
		int(r.PluginVersion))

	reply := &rpc.ProcessMetricsReply{
		Metrics: common.NewMetrics(mts),
		Errors:  errorsToStrings(errs),
	}
	return reply, nil
}
コード例 #5
0
ファイル: control_grpc_server.go プロジェクト: IRCody/snap
func (pc *ControlGRPCServer) CollectMetrics(ctx context.Context, r *rpc.CollectMetricsRequest) (*rpc.CollectMetricsResponse, error) {
	var AllTags map[string]map[string]string
	for k, v := range r.AllTags {
		AllTags[k] = make(map[string]string)
		for _, entry := range v.Entries {
			AllTags[k][entry.Key] = entry.Value
		}
	}
	mts, errs := pc.control.CollectMetrics(r.TaskID, AllTags)
	var reply *rpc.CollectMetricsResponse
	if mts == nil {
		reply = &rpc.CollectMetricsResponse{
			Errors: errorsToStrings(errs),
		}
	} else {
		reply = &rpc.CollectMetricsResponse{
			Metrics: common.NewMetrics(mts),
			Errors:  errorsToStrings(errs),
		}
	}
	return reply, nil
}
コード例 #6
0
ファイル: controlproxy.go プロジェクト: IRCody/snap
func (c ControlProxy) ProcessMetrics(metrics []core.Metric,
	config map[string]ctypes.ConfigValue,
	taskId string,
	pluginName string,
	pluginVersion int) ([]core.Metric, []error) {
	req := &rpc.PubProcMetricsRequest{
		Metrics:       common.NewMetrics(metrics),
		PluginName:    pluginName,
		PluginVersion: int64(pluginVersion),
		TaskId:        taskId,
		Config:        common.ToConfigMap(config),
	}
	reply, err := c.Client.ProcessMetrics(getContext(), req)
	var errs []error
	if err != nil {
		errs = append(errs, err)
		return nil, errs
	}
	rerrs := replyErrorsToErrors(reply.Errors)
	errs = append(errs, rerrs...)
	return common.ToCoreMetrics(reply.Metrics), errs
}
コード例 #7
0
ファイル: controlproxy.go プロジェクト: lynxbat/snap
func (c ControlProxy) CollectMetrics(mts []core.Metric, deadline time.Time, taskID string, AllTags map[string]map[string]string) ([]core.Metric, []error) {
	var allTags map[string]*rpc.Map
	for k, v := range AllTags {
		tags := &rpc.Map{}
		for kn, vn := range v {
			entry := &rpc.MapEntry{
				Key:   kn,
				Value: vn,
			}
			tags.Entries = append(tags.Entries, entry)
		}
		allTags[k] = tags
	}
	req := &rpc.CollectMetricsRequest{
		Metrics: common.NewMetrics(mts),
		Deadline: &common.Time{
			Sec:  deadline.Unix(),
			Nsec: int64(deadline.Nanosecond()),
		},
		TaskID:  taskID,
		AllTags: allTags,
	}
	reply, err := c.Client.CollectMetrics(getContext(), req)
	var errs []error
	if err != nil {
		errs = append(errs, err)
		return nil, errs
	}
	rerrs := replyErrorsToErrors(reply.Errors)
	if len(rerrs) > 0 {
		errs = append(errs, rerrs...)
		return nil, errs
	}
	metrics := common.ToCoreMetrics(reply.Metrics)
	return metrics, nil
}
コード例 #8
0
ファイル: control_grpc_server.go プロジェクト: lynxbat/snap
func (pc *ControlGRPCServer) CollectMetrics(ctx context.Context, r *rpc.CollectMetricsRequest) (*rpc.CollectMetricsReply, error) {
	metrics := common.ToCoreMetrics(r.Metrics)
	deadline := time.Unix(r.Deadline.Sec, r.Deadline.Nsec)
	var AllTags map[string]map[string]string
	for k, v := range r.AllTags {
		AllTags[k] = make(map[string]string)
		for _, entry := range v.Entries {
			AllTags[k][entry.Key] = entry.Value
		}
	}
	mts, errs := pc.control.CollectMetrics(metrics, deadline, r.TaskID, AllTags)
	var reply *rpc.CollectMetricsReply
	if mts == nil {
		reply = &rpc.CollectMetricsReply{
			Errors: errorsToStrings(errs),
		}
	} else {
		reply = &rpc.CollectMetricsReply{
			Metrics: common.NewMetrics(mts),
			Errors:  errorsToStrings(errs),
		}
	}
	return reply, nil
}
コード例 #9
0
// This test is meant to cover the grpc implementation of the subset of control
// features that scheduler uses. It is not intended to test the control features
// themselves, only that we are correctly passing data over grpc and correctly
// passing success/errors.
func TestGRPCServerScheduler(t *testing.T) {
	l, _ := net.Listen("tcp", ":0")
	l.Close()
	cfg := GetDefaultConfig()
	cfg.ListenPort = l.Addr().(*net.TCPAddr).Port
	c := New(cfg)
	err := c.Start()

	lpe := newFoo()
	c.eventManager.RegisterHandler("Control.PluginLoaded", lpe)

	Convey("Starting control_proxy server/client", t, func() {
		Convey("So err should be nil", func() {
			So(err, ShouldBeNil)
		})
	})
	// Load 3 plugins
	// collector -- mock
	// processor -- passthru
	// publisher -- file
	mock, err := core.NewRequestedPlugin(fixtures.JSONRPCPluginPath)
	if err != nil {
		log.Fatal(err)
	}
	_, serr := c.Load(mock)
	Convey("Loading mock collector", t, func() {
		Convey("should not error", func() {
			So(serr, ShouldBeNil)
		})
	})
	<-lpe.done
	passthru, err := core.NewRequestedPlugin(helper.PluginFilePath("snap-plugin-processor-passthru"))
	if err != nil {
		log.Fatal(err)
	}
	catalogedPassthru, serr := c.Load(passthru)
	Convey("Loading passthru processor", t, func() {
		Convey("should not error", func() {
			So(serr, ShouldBeNil)
		})
	})
	subscribedPassThruPlugin := subscribedPlugin{
		name:     catalogedPassthru.Name(),
		version:  catalogedPassthru.Version(),
		typeName: catalogedPassthru.TypeName(),
	}
	<-lpe.done
	filepub, err := core.NewRequestedPlugin(helper.PluginFilePath("snap-plugin-publisher-mock-file"))
	if err != nil {
		log.Fatal(err)
	}
	catalogedFile, serr := c.Load(filepub)
	Convey("Loading file publisher", t, func() {
		Convey("should not error", func() {
			So(serr, ShouldBeNil)
		})
	})
	subscribedFilePlugin := subscribedPlugin{
		name:     catalogedFile.Name(),
		version:  catalogedFile.Version(),
		typeName: catalogedFile.TypeName(),
	}

	<-lpe.done
	conn, err := rpcutil.GetClientConnection(c.Config.ListenAddr, c.Config.ListenPort)

	Convey("Creating an rpc connection", t, func() {
		Convey("Should not error", func() {
			So(err, ShouldBeNil)
		})
	})

	client := rpc.NewMetricManagerClient(conn)

	Convey("Creating an RPC client to control RPC server", t, func() {
		Convey("And a client should exist", func() {
			So(client, ShouldNotBeNil)
		})
	})

	// Verify that validate deps is properly passing through errors
	Convey("Validating Deps", t, func() {
		Convey("Should Fail if given invalid info", func() {
			req := &rpc.ValidateDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.InvalidMetric}),
				Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
			}
			reply, err := client.ValidateDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
		Convey("with valid metrics", func() {
			req := &rpc.ValidateDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
			}
			reply, err := client.ValidateDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
	})
	//Subscribe Deps: valid/invalid
	Convey("SubscribeDeps", t, func() {
		Convey("Should Error with invalid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.InvalidMetric.Namespace()), Version: int64(fixtures.InvalidMetric.Version())}},
				Plugins:   common.ToSubPluginsMsg([]core.SubscribedPlugin{subscribedFilePlugin, subscribedPassThruPlugin}),
				TaskId:    "my-snowflake-id",
			}
			reply, err := client.SubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			So(reply.Errors[0].ErrorString, ShouldResemble, "Metric not found: /this/is/invalid (version: 1000)")
		})
		Convey("Should not error with valid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
				Plugins:   common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
				TaskId:    "my-snowflake-valid",
			}
			reply, err := client.SubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
	//our returned metrics
	var mts []core.Metric
	//collect
	Convey("CollectMetrics", t, func() {
		req := &rpc.SubscribeDepsRequest{
			Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
			Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{
				subscribedPassThruPlugin,
				subscribedFilePlugin,
			},
			),
			TaskId: "my-snowflake-id",
		}
		_, err := client.SubscribeDeps(context.Background(), req)
		So(err, ShouldBeNil)

		Convey("should error with invalid inputs", func() {
			req := &rpc.CollectMetricsRequest{
				TaskID: "my-fake-snowflake-id",
			}
			reply, err := client.CollectMetrics(context.Background(), req)
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})

		Convey("should not error with valid inputs", func() {
			req := &rpc.CollectMetricsRequest{
				TaskID: "my-snowflake-valid",
			}
			reply, err := client.CollectMetrics(context.Background(), req)
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
			So(reply.Metrics[0].Namespace, ShouldResemble, common.ToNamespace(fixtures.ValidMetric.Namespace()))
			// Used in a later test as metrics to be passed to processor
			mts = common.ToCoreMetrics(reply.Metrics)
		})
	})

	//process
	Convey("ProcessMetrics", t, func() {
		req := &rpc.SubscribeDepsRequest{
			Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
			Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{
				subscribedPassThruPlugin,
				subscribedFilePlugin,
			},
			),
			TaskId: "my-snowflake-id",
		}
		_, err := client.SubscribeDeps(context.Background(), req)
		So(err, ShouldBeNil)
		Convey("should error with invalid inputs", func() {
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				PluginName:    "passthru-invalid",
				PluginVersion: 1,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(map[string]ctypes.ConfigValue{}),
			}
			reply, err := client.ProcessMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			// content to pass to publisher
		})
		Convey("should not error with valid inputs", func() {
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics(mts),
				PluginName:    "passthru",
				PluginVersion: 1,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(map[string]ctypes.ConfigValue{}),
			}
			reply, err := client.ProcessMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)

		})
	})
	//publishmetrics
	Convey("PublishMetrics", t, func() {
		req := &rpc.SubscribeDepsRequest{
			Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
			Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{
				subscribedPassThruPlugin,
				subscribedFilePlugin,
			},
			),
			TaskId: "my-snowflake-id",
		}
		_, err := client.SubscribeDeps(context.Background(), req)
		So(err, ShouldBeNil)

		Convey("Should error with invalid inputs", func() {
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				PluginName:    "mock-file-invalid",
				PluginVersion: 3,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(map[string]ctypes.ConfigValue{}),
			}
			reply, err := client.PublishMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})

		// Publish only returns no errors on success
		Convey("should not error with valid inputs", func() {
			config := make(map[string]ctypes.ConfigValue)
			config["file"] = ctypes.ConfigValueStr{Value: "/tmp/grpcservertest.snap"}
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				PluginName:    "mock-file",
				PluginVersion: 3,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(config),
			}
			reply, err := client.PublishMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
}
コード例 #10
0
// This test is meant to cover the grpc implementation of the subset of control
// features that scheduler uses. It is not intended to test the control features
// themselves, only that we are correctly passing data over grpc and correctly
// passing success/errors.
func TestGRPCServerScheduler(t *testing.T) {
	l, _ := net.Listen("tcp", ":0")
	l.Close()
	cfg := GetDefaultConfig()
	cfg.ListenPort = l.Addr().(*net.TCPAddr).Port
	c := New(cfg)
	err := c.Start()

	Convey("Starting control_proxy server/client", t, func() {
		Convey("So err should be nil", func() {
			So(err, ShouldBeNil)
		})
	})
	// Load 3 plugins
	// collector -- mock
	// processor -- passthru
	// publisher -- file
	mock, err := core.NewRequestedPlugin(fixtures.JSONRPCPluginPath)
	if err != nil {
		log.Fatal(err)
	}
	c.Load(mock)
	passthru, err := core.NewRequestedPlugin(path.Join(fixtures.SnapPath, "plugin", "snap-processor-passthru"))
	if err != nil {
		log.Fatal(err)
	}
	c.Load(passthru)
	filepub, err := core.NewRequestedPlugin(path.Join(fixtures.SnapPath, "plugin", "snap-publisher-file"))
	if err != nil {
		log.Fatal(err)
	}
	c.Load(filepub)

	conn, err := rpcutil.GetClientConnection(c.Config.ListenAddr, c.Config.ListenPort)

	Convey("Creating an rpc connection", t, func() {
		Convey("Should not error", func() {
			So(err, ShouldBeNil)
		})
	})

	client := rpc.NewMetricManagerClient(conn)

	Convey("Creating an RPC client to control RPC server", t, func() {
		Convey("And a client should exist", func() {
			So(client, ShouldNotBeNil)
		})
	})
	//GetContentTypes
	Convey("Getting Content Types", t, func() {
		Convey("Should err if invalid plugin given", func() {
			req := &rpc.GetPluginContentTypesRequest{
				Name:       "bogus",
				PluginType: int32(0),
				Version:    int32(0),
			}
			reply, err := client.GetPluginContentTypes(context.Background(), req)
			// We don't expect rpc errors
			So(err, ShouldBeNil)
			So(reply.Error, ShouldNotEqual, "")
			So(reply.Error, ShouldResemble, "plugin not found")
		})
		Convey("Should return content types with valid plugin", func() {
			req := &rpc.GetPluginContentTypesRequest{
				Name:       "mock",
				PluginType: int32(0),
				Version:    0,
			}
			reply, err := client.GetPluginContentTypes(context.Background(), req)
			So(err, ShouldBeNil)
			So(reply.Error, ShouldEqual, "")
			So(reply.AcceptedTypes, ShouldContain, "snap.gob")
			So(reply.ReturnedTypes, ShouldContain, "snap.gob")
		})
	})

	// Verify that validate deps is properly passing through errors
	Convey("Validating Deps", t, func() {
		Convey("Should Fail if given invalid info", func() {
			req := &rpc.ValidateDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.InvalidMetric}),
				Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
			}
			reply, err := client.ValidateDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
		Convey("with valid metrics", func() {
			req := &rpc.ValidateDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
			}
			reply, err := client.ValidateDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
	})
	//Subscribe Deps: valid/invalid
	Convey("SubscribeDeps", t, func() {
		Convey("Should Error with invalid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.InvalidMetric}),
				Plugins: common.ToCorePluginsMsg([]core.Plugin{}),
				TaskId:  "my-snowflake-id",
			}
			reply, err := client.SubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			So(reply.Errors[0].ErrorString, ShouldResemble, "Metric not found: /this/is/invalid")
		})
		Convey("Should not error with valid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				Plugins: common.ToCorePluginsMsg([]core.Plugin{}),
				TaskId:  "my-snowflake-id",
			}
			reply, err := client.SubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
	// unsubscribedeps -- valid/invalid
	Convey("UnsubscribeDeps", t, func() {
		Convey("Should Error with invalid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.InvalidMetric}),
				Plugins: common.ToCorePluginsMsg([]core.Plugin{}),
				TaskId:  "my-snowflake-id",
			}
			reply, err := client.UnsubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			So(reply.Errors[0].ErrorString, ShouldResemble, "Metric not found: /this/is/invalid")
		})
		Convey("Should not error with valid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				Plugins: common.ToCorePluginsMsg([]core.Plugin{}),
				TaskId:  "my-snowflake-id",
			}
			reply, err := client.UnsubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
	//matchquerytonamespaces -- valid/invalid
	Convey("MatchingQueryToNamespaces", t, func() {
		Convey("Should error with invalid inputs", func() {
			req := &rpc.ExpandWildcardsRequest{
				Namespace: common.ToNamespace(fixtures.InvalidMetric.Namespace()),
			}
			reply, err := client.MatchQueryToNamespaces(context.Background(), req)
			// we don't expect rpc.errors
			So(err, ShouldBeNil)
			So(reply.Error, ShouldNotBeNil)
			So(reply.Error.ErrorString, ShouldResemble, "Metric not found: /this/is/invalid")
		})
		Convey("Should not error with invalid inputs", func() {
			req := &rpc.ExpandWildcardsRequest{
				Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()),
			}
			reply, err := client.MatchQueryToNamespaces(context.Background(), req)
			// we don't expect rpc.errors
			So(err, ShouldBeNil)
			So(reply.Error, ShouldBeNil)
		})
	})
	//expandwildcards -- valid/invalid
	Convey("ExpandWildcards", t, func() {
		Convey("Should error with invalid inputs", func() {
			req := &rpc.ExpandWildcardsRequest{
				Namespace: common.ToNamespace(fixtures.InvalidMetric.Namespace()),
			}
			reply, err := client.ExpandWildcards(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(reply.Error, ShouldNotBeNil)
			So(reply.Error.ErrorString, ShouldResemble, "Metric not found: /this/is/invalid")
		})
		Convey("Should not error with valid inputs", func() {
			req := &rpc.ExpandWildcardsRequest{
				Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()),
			}
			reply, err := client.ExpandWildcards(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(reply.Error, ShouldBeNil)
		})
	})
	// start plugin pools/provide task info so we can do collect/process/publishMetrics
	// errors here indicate problems outside the scope of this test.
	plugins := []string{"collector:mock:1", "processor:passthru:1", "publisher:file:3"}
	lps := make([]*loadedPlugin, len(plugins))
	pools := make([]strategy.Pool, len(plugins))
	for i, v := range plugins {
		lps[i], err = c.pluginManager.get(v)
		if err != nil {
			log.Fatal(err)
		}
		pools[i], err = c.pluginRunner.AvailablePlugins().getOrCreatePool(v)
		if err != nil {
			log.Fatal(err)
		}
		pools[i].Subscribe("my-snowflake-id", strategy.BoundSubscriptionType)
		err = c.pluginRunner.runPlugin(lps[i].Details)
		if err != nil {
			log.Fatal(err)
		}
	}
	//our returned metrics
	var mts []core.Metric
	//collect
	Convey("CollectMetrics", t, func() {
		Convey("Should error with invalid inputs", func() {
			req := &rpc.CollectMetricsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.InvalidMetric}),
				Deadline: &common.Time{
					Sec:  int64(time.Now().Unix()),
					Nsec: int64(time.Now().Nanosecond()),
				},
				TaskID: "my-snowflake-id",
			}
			reply, err := client.CollectMetrics(context.Background(), req)
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
		Convey("should not error with valid inputs", func() {
			req := &rpc.CollectMetricsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				Deadline: &common.Time{
					Sec:  int64(time.Now().Unix()),
					Nsec: int64(time.Now().Nanosecond()),
				},
				TaskID: "my-snowflake-id",
			}
			reply, err := client.CollectMetrics(context.Background(), req)
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
			So(reply.Metrics[0].Namespace, ShouldResemble, common.ToNamespace(fixtures.ValidMetric.Namespace()))
			// Used in a later test as metrics to be passed to processor
			mts = common.ToCoreMetrics(reply.Metrics)
		})
	})
	//our content to pass to publish
	var content []byte
	//process
	Convey("ProcessMetrics", t, func() {
		Convey("Should error with invalid inputs", func() {
			req := controlproxy.GetPubProcReq("snap.gob", []byte{}, "bad name", 1, map[string]ctypes.ConfigValue{}, "my-snowflake-id")
			reply, err := client.ProcessMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			So(reply.Errors[0], ShouldResemble, "bad key")
		})
		Convey("should not error with valid inputs", func() {
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			metrics := make([]plugin.MetricType, len(mts))
			for i, m := range mts {
				metrics[i] = m.(plugin.MetricType)
			}
			enc.Encode(metrics)
			req := controlproxy.GetPubProcReq("snap.gob", buf.Bytes(), "passthru", 1, map[string]ctypes.ConfigValue{}, "my-snowflake-id")
			reply, err := client.ProcessMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
			// content to pass to publisher
			content = reply.Content

		})
	})
	//publishmetrics
	Convey("PublishMetrics", t, func() {
		Convey("Should error with invalid inputs", func() {
			req := controlproxy.GetPubProcReq("snap.gob", []byte{}, "bad name", 1, map[string]ctypes.ConfigValue{}, "my-snowflake-id")
			reply, err := client.PublishMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)

			So(reply.Errors[0], ShouldResemble, "bad key")
		})
		// Publish only returns no errors on success
		Convey("should not error with valid inputs", func() {
			config := make(map[string]ctypes.ConfigValue)
			config["file"] = ctypes.ConfigValueStr{Value: "/tmp/grpcservertest.snap"}
			req := controlproxy.GetPubProcReq("snap.gob", content, "file", 3, config, "my-snowflake-id")
			reply, err := client.PublishMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
}