rpc: add new client, use it everywhere
The new client implementation supports concurrent requests, subscriptions and replaces the various ad hoc RPC clients throughout go-ethereum.
This commit is contained in:
@ -19,9 +19,12 @@ package main
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/console"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
@ -99,7 +102,7 @@ func localConsole(ctx *cli.Context) error {
|
||||
// console to it.
|
||||
func remoteConsole(ctx *cli.Context) error {
|
||||
// Attach to a remotely running geth instance and start the JavaScript console
|
||||
client, err := utils.NewRemoteRPCClient(ctx)
|
||||
client, err := dialRPC(ctx.Args().First())
|
||||
if err != nil {
|
||||
utils.Fatalf("Unable to attach to remote geth: %v", err)
|
||||
}
|
||||
@ -127,6 +130,20 @@ func remoteConsole(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// dialRPC returns a RPC client which connects to the given endpoint.
|
||||
// The check for empty endpoint implements the defaulting logic
|
||||
// for "geth attach" and "geth monitor" with no argument.
|
||||
func dialRPC(endpoint string) (*rpc.Client, error) {
|
||||
if endpoint == "" {
|
||||
endpoint = node.DefaultIPCEndpoint()
|
||||
} else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
|
||||
// Backwards compatibility with geth < 1.5 which required
|
||||
// these prefixes.
|
||||
endpoint = endpoint[4:]
|
||||
}
|
||||
return rpc.Dial(endpoint)
|
||||
}
|
||||
|
||||
// ephemeralConsole starts a new geth node, attaches an ephemeral JavaScript
|
||||
// console to it, and each of the files specified as arguments and tears the
|
||||
// everything down.
|
||||
|
@ -21,11 +21,10 @@ import (
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"sort"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
@ -36,7 +35,7 @@ import (
|
||||
var (
|
||||
monitorCommandAttachFlag = cli.StringFlag{
|
||||
Name: "attach",
|
||||
Value: "ipc:" + node.DefaultIPCEndpoint(),
|
||||
Value: node.DefaultIPCEndpoint(),
|
||||
Usage: "API endpoint to attach to",
|
||||
}
|
||||
monitorCommandRowsFlag = cli.IntFlag{
|
||||
@ -69,12 +68,12 @@ to display multiple metrics simultaneously.
|
||||
// monitor starts a terminal UI based monitoring tool for the requested metrics.
|
||||
func monitor(ctx *cli.Context) error {
|
||||
var (
|
||||
client rpc.Client
|
||||
client *rpc.Client
|
||||
err error
|
||||
)
|
||||
// Attach to an Ethereum node over IPC or RPC
|
||||
endpoint := ctx.String(monitorCommandAttachFlag.Name)
|
||||
if client, err = utils.NewRemoteRPCClientFromString(endpoint); err != nil {
|
||||
if client, err = dialRPC(endpoint); err != nil {
|
||||
utils.Fatalf("Unable to attach to geth node: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
@ -159,30 +158,10 @@ func monitor(ctx *cli.Context) error {
|
||||
|
||||
// retrieveMetrics contacts the attached geth node and retrieves the entire set
|
||||
// of collected system metrics.
|
||||
func retrieveMetrics(client rpc.Client) (map[string]interface{}, error) {
|
||||
req := map[string]interface{}{
|
||||
"id": new(int64),
|
||||
"method": "debug_metrics",
|
||||
"jsonrpc": "2.0",
|
||||
"params": []interface{}{true},
|
||||
}
|
||||
|
||||
if err := client.Send(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res rpc.JSONSuccessResponse
|
||||
if err := client.Recv(&res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.Result != nil {
|
||||
if mets, ok := res.Result.(map[string]interface{}); ok {
|
||||
return mets, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unable to retrieve metrics")
|
||||
func retrieveMetrics(client *rpc.Client) (map[string]interface{}, error) {
|
||||
var metrics map[string]interface{}
|
||||
err := client.Call(&metrics, "debug_metrics", true)
|
||||
return metrics, err
|
||||
}
|
||||
|
||||
// resolveMetrics takes a list of input metric patterns, and resolves each to one
|
||||
@ -270,7 +249,7 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 {
|
||||
|
||||
// refreshCharts retrieves a next batch of metrics, and inserts all the new
|
||||
// values into the active datasets and charts
|
||||
func refreshCharts(client rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
|
||||
func refreshCharts(client *rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
|
||||
values, err := retrieveMetrics(client)
|
||||
for i, metric := range metrics {
|
||||
if len(data) < 512 {
|
||||
|
@ -1,55 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
// NewRemoteRPCClient returns a RPC client which connects to a running geth instance.
|
||||
// Depending on the given context this can either be a IPC or a HTTP client.
|
||||
func NewRemoteRPCClient(ctx *cli.Context) (rpc.Client, error) {
|
||||
if ctx.Args().Present() {
|
||||
endpoint := ctx.Args().First()
|
||||
return NewRemoteRPCClientFromString(endpoint)
|
||||
}
|
||||
// use IPC by default
|
||||
return rpc.NewIPCClient(node.DefaultIPCEndpoint())
|
||||
}
|
||||
|
||||
// NewRemoteRPCClientFromString returns a RPC client which connects to the given
|
||||
// endpoint. It must start with either `ipc:` or `rpc:` (HTTP).
|
||||
func NewRemoteRPCClientFromString(endpoint string) (rpc.Client, error) {
|
||||
if strings.HasPrefix(endpoint, "ipc:") {
|
||||
return rpc.NewIPCClient(endpoint[4:])
|
||||
}
|
||||
if strings.HasPrefix(endpoint, "rpc:") {
|
||||
return rpc.NewHTTPClient(endpoint[4:])
|
||||
}
|
||||
if strings.HasPrefix(endpoint, "http://") {
|
||||
return rpc.NewHTTPClient(endpoint)
|
||||
}
|
||||
if strings.HasPrefix(endpoint, "ws:") {
|
||||
return rpc.NewWSClient(endpoint)
|
||||
}
|
||||
return nil, fmt.Errorf("invalid endpoint")
|
||||
}
|
Reference in New Issue
Block a user