Skip to content

Commit

Permalink
[FABG-686] add Tally performance support to SDK
Browse files Browse the repository at this point in the history
	In this patch, performance counts are added the
	Channel Client's Execute and Query function calls.
	ref: pkg/client/channel/chclient.go for counts additions

	Similar counts can be added elsewhere in the SDK if needed

Change-Id: I797a140f9d4d8540b7b8d8c6d3642889637bf16a
Signed-off-by: Baha Shaaban <baha.shaaban@securekey.com>
  • Loading branch information
Baha Shaaban committed Jul 23, 2018
1 parent 817c62d commit 2fd5e4f
Show file tree
Hide file tree
Showing 13 changed files with 735 additions and 22 deletions.
72 changes: 71 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Gopkg.toml
Expand Up @@ -55,3 +55,9 @@
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.0"

# tally is used only if performance is enabled
# using the pprof build tag (normal sdk build does not use this library)
[[constraint]]
name = "github.com/uber-go/tally"
version = "=3.3.2"
12 changes: 4 additions & 8 deletions pkg/client/channel/chclient.go
Expand Up @@ -40,6 +40,7 @@ type Client struct {
membership fab.ChannelMembership
eventService fab.EventService
greylist *greylist.Filter
clientTally // nolint
}

// ClientOption describes a functional parameter for the New constructor
Expand Down Expand Up @@ -69,12 +70,7 @@ func New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client
return nil, errors.WithMessage(err, "membership creation failed")
}

channelClient := Client{
membership: membership,
eventService: eventService,
greylist: greylistProvider,
context: channelContext,
}
channelClient := newClient(channelContext, membership, eventService, greylistProvider)

for _, param := range opts {
err := param(&channelClient)
Expand All @@ -98,7 +94,7 @@ func (cc *Client) Query(request Request, options ...RequestOption) (Response, er
options = append(options, addDefaultTimeout(fab.Query))
options = append(options, addDefaultTargetFilter(cc.context, filter.ChaincodeQuery))

return cc.InvokeHandler(invoke.NewQueryHandler(), request, options...)
return callQuery(cc, request, options...)
}

// Execute prepares and executes transaction using request and optional request options
Expand All @@ -112,7 +108,7 @@ func (cc *Client) Execute(request Request, options ...RequestOption) (Response,
options = append(options, addDefaultTimeout(fab.Execute))
options = append(options, addDefaultTargetFilter(cc.context, filter.EndorsingPeer))

return cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...)
return callExecute(cc, request, options...)
}

// addDefaultTargetFilter adds default target filter if target filter is not specified
Expand Down
36 changes: 36 additions & 0 deletions pkg/client/channel/chclientrun.go
@@ -0,0 +1,36 @@
// +build !pprof

/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package channel

import (
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke"
"github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/greylist"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
)

type clientTally interface{} // nolint

func newClient(channelContext context.Channel, membership fab.ChannelMembership, eventService fab.EventService, greylistProvider *greylist.Filter) Client {
channelClient := Client{
membership: membership,
eventService: eventService,
greylist: greylistProvider,
context: channelContext,
}
return channelClient
}

func callQuery(cc *Client, request Request, options ...RequestOption) (Response, error) {
return cc.InvokeHandler(invoke.NewQueryHandler(), request, options...)
}

func callExecute(cc *Client, request Request, options ...RequestOption) (Response, error) {
return cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...)
}
82 changes: 82 additions & 0 deletions pkg/client/channel/clientrun_perf.go
@@ -0,0 +1,82 @@
// +build pprof

/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package channel

import (
// TODO update metrics package with Fabric's copy, once officially released
// TODO and pinned into Go SDK with the below commented out import statement
//"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke"
"github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/greylist"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"

// TODO remove below metrics declaration once Fabric's copy is ready to be used
"github.com/hyperledger/fabric-sdk-go/test/performance/metrics"
"github.com/uber-go/tally"
)

type clientTally struct {
queryCount tally.Counter
queryFailCount tally.Counter
queryTimer tally.Timer

executeCount tally.Counter
executeFailCount tally.Counter
executeTimer tally.Timer
}

func newClientTally(channelContext context.Channel) clientTally {
return clientTally{
queryCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_query_calls"),
queryFailCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_query_errors"),
queryTimer: metrics.RootScope.SubScope(channelContext.ChannelID()).Timer("ch_client_query_processing_time_seconds"),

executeCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_execute_calls"),
executeFailCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_execute_errors"),
executeTimer: metrics.RootScope.SubScope(channelContext.ChannelID()).Timer("ch_client_execute_processing_time_seconds"),
}
}

func newClient(channelContext context.Channel, membership fab.ChannelMembership, eventService fab.EventService, greylistProvider *greylist.Filter) Client {
ct := newClientTally(channelContext)

channelClient := Client{
membership: membership,
eventService: eventService,
greylist: greylistProvider,
context: channelContext,
clientTally: ct,
}
return channelClient
}

func callQuery(cc *Client, request Request, options ...RequestOption) (Response, error) {
cc.executeCount.Inc(1)
stopWatch := cc.queryTimer.Start()
defer stopWatch.Stop()

r, err := cc.InvokeHandler(invoke.NewQueryHandler(), request, options...)
if err != nil {
cc.queryFailCount.Inc(1)
}
return r, err
}

func callExecute(cc *Client, request Request, options ...RequestOption) (Response, error) {
cc.executeCount.Inc(1)
stopWatch := cc.executeTimer.Start()
defer stopWatch.Stop()

r, err := cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...)
if err != nil {
cc.executeFailCount.Inc(1)
}
return r, err
}
38 changes: 37 additions & 1 deletion pkg/core/config/testdata/config_test.yaml
Expand Up @@ -331,4 +331,40 @@ certificateAuthorities:
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: ca.org2.example.com
#first one
#first one

###############################################################################
#
# Metrics section
#
# Similar to what's introduced in Fabric 1.3, this section can now
# be used in the SDK (see test/performance for an example showing how this is used)
# Note: In order to use performance metrics, the SDK must be built with 'pprof' build tag
###############################################################################
metrics:
# enable or disable metrics server
enabled: true

# when enable metrics server, must specify metrics reporter type
# currently supported type: "statsd","prom"
reporter: prom

# determines frequency of report metrics(unit: second)
interval: 1s

statsdReporter:

# statsd server address to connect
address: peer0.org1.example.com:8125

# determines frequency of push metrics to statsd server(unit: second)
flushInterval: 2s

# max size bytes for each push metrics request
# intranet recommend 1432 and internet recommend 512
flushBytes: 1432

promReporter:

# prometheus http server listen address for pull metrics
listenAddress: peer0.org1.example.com:8080
9 changes: 8 additions & 1 deletion scripts/third_party_pins/fabric/apply_fabric_client_utils.sh
Expand Up @@ -33,6 +33,8 @@ declare -a PKGS=(
"common/channelconfig"
"common/attrmgr"
"common/ledger"
# TODO add metrics once it's officially released
# "common/metrics"

"sdkpatch/logbridge"
"sdkpatch/cryptosuitebridge"
Expand Down Expand Up @@ -109,7 +111,12 @@ declare -a FILES=(
"common/channelconfig/organization.go"

"common/ledger/ledger_interface.go"


# TODO add metrics once it's officially released
# "common/metrics/server.go"
# "common/metrics/tally_provider.go"
# "common/metrics/types.go"

"sdkpatch/logbridge/logbridge.go"
"sdkpatch/cryptosuitebridge/cryptosuitebridge.go"
"sdkpatch/cachebridge/cache.go"
Expand Down

0 comments on commit 2fd5e4f

Please sign in to comment.