Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clientv3: added test for client metrics #6748

Merged
merged 1 commit into from
Nov 2, 2016
Merged

clientv3: added test for client metrics #6748

merged 1 commit into from
Nov 2, 2016

Conversation

sinsharat
Copy link
Contributor

@sinsharat sinsharat commented Oct 28, 2016

@sinsharat
Copy link
Contributor Author

sinsharat commented Oct 28, 2016

@xiang90, @heyitsanthony ,@gyuho : I am facing an issue with this test case. The test cases are failing for a leak in go-routine due to the http.ListenAndServe i am starting as it won't close until the entire test case execution completes.
I tried doing the custom way by creating my own customized call to handle the server. The below is the code for this:

// listen for all prometheus metrics
    go func() {
        http.Handle("/metrics", prometheus.Handler())
        srv := &http.Server{Addr: ":27989", Handler: nil}
        addr := srv.Addr
        if addr == "" {
            addr = ":http"
        }
        ln, err = net.Listen("tcp", addr)
        if err != nil {
            log.Fatalf("Error : %v occured while listening on addr : %v", err, addr)
        }
        log.Fatal(srv.Serve(ln.(*net.TCPListener)))
    }()

And before exiting i was doing:

if ln != nil {
        ln.Close()
    }

But now the issue is once the listener is closing the entire test case ends and before the next test case execution it exits :-(

Logs below:

=== RUN   TestRWMutexMultiNode
--- PASS: TestRWMutexMultiNode (1.41s)
=== RUN   TestV3MaintenanceHashInflight
--- PASS: TestV3MaintenanceHashInflight (0.35s)
=== RUN   TestV3ClientMetrics
--- PASS: TestV3ClientMetrics (0.81s)
=== RUN   TestQueueOneReaderOneWriter
exit status 1
FAIL    github.com/coreos/etcd/integration  177.484s

Will be glad if you could help on this.
Thank you!

@sinsharat
Copy link
Contributor Author

@xiang90 I don't know why the semaphore build is failing for integration, in my local machine i have tested it almost 50 times now and its passing all the time :-(.
Proof attached:

sharat@sharat-ubuntu:~/Go-Projects/src/github.com/coreos/etcd/integration$ go test -v
=== RUN   TestClusterOf1
--- PASS: TestClusterOf1 (0.38s)
=== RUN   TestClusterOf3
--- PASS: TestClusterOf3 (0.87s)
=== RUN   TestTLSClusterOf3
--- PASS: TestTLSClusterOf3 (0.80s)
=== RUN   TestClusterOf1UsingDiscovery
--- PASS: TestClusterOf1UsingDiscovery (0.71s)
=== RUN   TestClusterOf3UsingDiscovery
--- PASS: TestClusterOf3UsingDiscovery (1.15s)
=== RUN   TestTLSClusterOf3UsingDiscovery
--- PASS: TestTLSClusterOf3UsingDiscovery (1.15s)
=== RUN   TestDoubleClusterSizeOf1
--- PASS: TestDoubleClusterSizeOf1 (0.87s)
=== RUN   TestDoubleClusterSizeOf3
--- PASS: TestDoubleClusterSizeOf3 (2.84s)
=== RUN   TestDoubleTLSClusterSizeOf3
--- PASS: TestDoubleTLSClusterSizeOf3 (3.15s)
=== RUN   TestDecreaseClusterSizeOf3
--- PASS: TestDecreaseClusterSizeOf3 (1.40s)
=== RUN   TestDecreaseClusterSizeOf5
--- PASS: TestDecreaseClusterSizeOf5 (1.86s)
=== RUN   TestForceNewCluster
--- PASS: TestForceNewCluster (1.03s)
=== RUN   TestAddMemberAfterClusterFullRotation
--- PASS: TestAddMemberAfterClusterFullRotation (3.33s)
=== RUN   TestIssue2681
--- PASS: TestIssue2681 (2.04s)
=== RUN   TestIssue2746
--- PASS: TestIssue2746 (3.51s)
=== RUN   TestIssue2746WithThree
--- PASS: TestIssue2746WithThree (3.05s)
=== RUN   TestIssue2904
--- PASS: TestIssue2904 (6.69s)
=== RUN   TestIssue3699
--- PASS: TestIssue3699 (4.73s)
=== RUN   TestRejectUnhealthyAdd
--- PASS: TestRejectUnhealthyAdd (11.06s)
=== RUN   TestRejectUnhealthyRemove
--- PASS: TestRejectUnhealthyRemove (9.11s)
=== RUN   TestTransferLeader
--- PASS: TestTransferLeader (0.70s)
=== RUN   TestEmbedEtcd
--- PASS: TestEmbedEtcd (1.43s)
=== RUN   TestPauseMember
--- PASS: TestPauseMember (2.29s)
=== RUN   TestRestartMember
--- PASS: TestRestartMember (1.77s)
=== RUN   TestLaunchDuplicateMemberShouldFail
--- PASS: TestLaunchDuplicateMemberShouldFail (1.21s)
=== RUN   TestSnapshotAndRestartMember
--- PASS: TestSnapshotAndRestartMember (2.12s)
=== RUN   TestNetworkPartition5MembersLeaderInMinority
--- PASS: TestNetworkPartition5MembersLeaderInMinority (1.64s)
=== RUN   TestNetworkPartition5MembersLeaderInMajority
--- PASS: TestNetworkPartition5MembersLeaderInMajority (1.59s)
=== RUN   TestNetworkPartition4Members
--- PASS: TestNetworkPartition4Members (2.27s)
=== RUN   TestV2Set
--- PASS: TestV2Set (0.42s)
=== RUN   TestV2CreateUpdate
--- PASS: TestV2CreateUpdate (0.47s)
=== RUN   TestV2CAS
--- PASS: TestV2CAS (0.43s)
=== RUN   TestV2Delete
--- PASS: TestV2Delete (0.39s)
=== RUN   TestV2CAD
--- PASS: TestV2CAD (0.37s)
=== RUN   TestV2Unique
--- PASS: TestV2Unique (0.35s)
=== RUN   TestV2Get
--- PASS: TestV2Get (0.29s)
=== RUN   TestV2QuorumGet
--- PASS: TestV2QuorumGet (0.33s)
=== RUN   TestV2Watch
--- PASS: TestV2Watch (0.36s)
=== RUN   TestV2WatchWithIndex
--- PASS: TestV2WatchWithIndex (0.31s)
=== RUN   TestV2WatchKeyInDir
--- PASS: TestV2WatchKeyInDir (1.75s)
=== RUN   TestV2Head
--- PASS: TestV2Head (0.33s)
=== RUN   TestBarrierSingleNode
--- PASS: TestBarrierSingleNode (0.39s)
=== RUN   TestBarrierMultiNode
--- PASS: TestBarrierMultiNode (0.99s)
=== RUN   TestDoubleBarrier
--- PASS: TestDoubleBarrier (1.95s)
=== RUN   TestDoubleBarrierFailover
--- PASS: TestDoubleBarrierFailover (1.79s)
=== RUN   TestElectionWait
--- PASS: TestElectionWait (1.85s)
=== RUN   TestElectionFailover
--- PASS: TestElectionFailover (1.24s)
=== RUN   TestElectionSessionRecampaign
--- PASS: TestElectionSessionRecampaign (0.54s)
=== RUN   TestElectionOnPrefixOfExistingKey
--- PASS: TestElectionOnPrefixOfExistingKey (0.28s)
=== RUN   TestV3PutOverwrite
--- PASS: TestV3PutOverwrite (0.84s)
=== RUN   TestV3PutRestart
--- PASS: TestV3PutRestart (1.10s)
=== RUN   TestV3CompactCurrentRev
--- PASS: TestV3CompactCurrentRev (0.34s)
=== RUN   TestV3TxnTooManyOps
--- PASS: TestV3TxnTooManyOps (0.92s)
=== RUN   TestV3TxnDuplicateKeys
--- PASS: TestV3TxnDuplicateKeys (0.83s)
=== RUN   TestV3TxnRevision
--- PASS: TestV3TxnRevision (0.42s)
=== RUN   TestV3PutMissingLease
--- PASS: TestV3PutMissingLease (1.18s)
=== RUN   TestV3DeleteRange
--- PASS: TestV3DeleteRange (6.41s)
=== RUN   TestV3TxnInvalidRange
--- PASS: TestV3TxnInvalidRange (1.00s)
=== RUN   TestV3TooLargeRequest
--- PASS: TestV3TooLargeRequest (1.03s)
=== RUN   TestV3Hash
--- PASS: TestV3Hash (0.98s)
=== RUN   TestV3StorageQuotaAPI
--- PASS: TestV3StorageQuotaAPI (1.79s)
=== RUN   TestV3StorageQuotaApply
--- PASS: TestV3StorageQuotaApply (2.52s)
=== RUN   TestV3AlarmDeactivate
--- PASS: TestV3AlarmDeactivate (1.39s)
=== RUN   TestV3RangeRequest
--- PASS: TestV3RangeRequest (7.06s)
=== RUN   TestTLSGRPCRejectInsecureClient
--- PASS: TestTLSGRPCRejectInsecureClient (0.79s)
=== RUN   TestTLSGRPCRejectSecureClient
--- PASS: TestTLSGRPCRejectSecureClient (5.86s)
=== RUN   TestTLSGRPCAcceptSecureAll
--- PASS: TestTLSGRPCAcceptSecureAll (0.98s)
=== RUN   TestGRPCRequireLeader
--- PASS: TestGRPCRequireLeader (1.08s)
=== RUN   TestGRPCStreamRequireLeader
--- PASS: TestGRPCStreamRequireLeader (1.80s)
=== RUN   TestV3LeasePrmote
--- PASS: TestV3LeasePrmote (11.23s)
=== RUN   TestV3LeaseRevoke
--- PASS: TestV3LeaseRevoke (0.83s)
=== RUN   TestV3LeaseGrantByID
--- PASS: TestV3LeaseGrantByID (1.06s)
=== RUN   TestV3LeaseExpire
--- PASS: TestV3LeaseExpire (1.98s)
=== RUN   TestV3LeaseKeepAlive
--- PASS: TestV3LeaseKeepAlive (1.01s)
=== RUN   TestV3LeaseExists
--- PASS: TestV3LeaseExists (0.96s)
=== RUN   TestV3PutOnNonExistLease
--- PASS: TestV3PutOnNonExistLease (0.35s)
=== RUN   TestV3GetNonExistLease
--- PASS: TestV3GetNonExistLease (1.40s)
=== RUN   TestV3LeaseSwitch
--- PASS: TestV3LeaseSwitch (1.90s)
=== RUN   TestV3LeaseFailover
--- PASS: TestV3LeaseFailover (7.23s)
=== RUN   TestV3LeaseRecoverAndRevoke
--- PASS: TestV3LeaseRecoverAndRevoke (0.72s)
=== RUN   TestV3LeaseRevokeAndRecover
--- PASS: TestV3LeaseRevokeAndRecover (0.78s)
=== RUN   TestV3LeaseRecoverKeyWithDetachedLease
--- PASS: TestV3LeaseRecoverKeyWithDetachedLease (0.71s)
=== RUN   TestV3LeaseRecoverKeyWithMutipleLease
--- PASS: TestV3LeaseRecoverKeyWithMutipleLease (0.84s)
=== RUN   TestMutexSingleNode
--- PASS: TestMutexSingleNode (1.15s)
=== RUN   TestMutexMultiNode
--- PASS: TestMutexMultiNode (1.93s)
=== RUN   TestMutexSessionRelock
--- PASS: TestMutexSessionRelock (0.85s)
=== RUN   TestRWMutexSingleNode
--- PASS: TestRWMutexSingleNode (1.55s)
=== RUN   TestRWMutexMultiNode
--- PASS: TestRWMutexMultiNode (1.15s)
=== RUN   TestV3MaintenanceHashInflight
--- PASS: TestV3MaintenanceHashInflight (0.43s)
=== RUN   TestV3ClientMetrics
--- PASS: TestV3ClientMetrics (1.05s)
=== RUN   TestQueueOneReaderOneWriter
--- PASS: TestQueueOneReaderOneWriter (0.46s)
=== RUN   TestQueueManyReaderOneWriter
--- PASS: TestQueueManyReaderOneWriter (1.10s)
=== RUN   TestQueueOneReaderManyWriter
--- PASS: TestQueueOneReaderManyWriter (1.81s)
=== RUN   TestQueueManyReaderManyWriter
--- PASS: TestQueueManyReaderManyWriter (1.63s)
=== RUN   TestPrQueueOneReaderOneWriter
--- PASS: TestPrQueueOneReaderOneWriter (0.45s)
=== RUN   TestPrQueueManyReaderManyWriter
--- PASS: TestPrQueueManyReaderManyWriter (2.17s)
=== RUN   TestSTMConflict
--- PASS: TestSTMConflict (1.10s)
=== RUN   TestSTMPutNewKey
--- PASS: TestSTMPutNewKey (0.33s)
=== RUN   TestSTMAbort
--- PASS: TestSTMAbort (0.33s)
=== RUN   TestSTMSerialize
--- PASS: TestSTMSerialize (1.06s)
=== RUN   TestV3WatchFromCurrentRevision
--- PASS: TestV3WatchFromCurrentRevision (13.44s)
=== RUN   TestV3WatchFutureRevision
--- PASS: TestV3WatchFutureRevision (0.36s)
=== RUN   TestV3WatchCancelSynced
--- PASS: TestV3WatchCancelSynced (1.86s)
=== RUN   TestV3WatchCancelUnsynced
--- PASS: TestV3WatchCancelUnsynced (1.67s)
=== RUN   TestV3WatchCurrentPutOverlap
--- PASS: TestV3WatchCurrentPutOverlap (1.92s)
=== RUN   TestV3WatchEmptyKey
--- PASS: TestV3WatchEmptyKey (0.33s)
=== RUN   TestV3WatchMultipleWatchersSynced
--- PASS: TestV3WatchMultipleWatchersSynced (1.65s)
=== RUN   TestV3WatchMultipleWatchersUnsynced
--- PASS: TestV3WatchMultipleWatchersUnsynced (1.80s)
=== RUN   TestV3WatchMultipleEventsTxnSynced
--- PASS: TestV3WatchMultipleEventsTxnSynced (1.79s)
=== RUN   TestV3WatchMultipleEventsTxnUnsynced
--- PASS: TestV3WatchMultipleEventsTxnUnsynced (1.79s)
=== RUN   TestV3WatchMultipleEventsPutUnsynced
--- PASS: TestV3WatchMultipleEventsPutUnsynced (1.99s)
=== RUN   TestV3WatchMultipleStreamsSynced
--- PASS: TestV3WatchMultipleStreamsSynced (1.72s)
=== RUN   TestV3WatchMultipleStreamsUnsynced
--- PASS: TestV3WatchMultipleStreamsUnsynced (1.72s)
=== RUN   TestWatchWithProgressNotify
--- PASS: TestWatchWithProgressNotify (4.68s)
=== RUN   TestV3WatchClose
--- PASS: TestV3WatchClose (0.36s)
=== RUN   TestV3WatchWithFilter
--- PASS: TestV3WatchWithFilter (0.43s)
=== RUN   TestV3WatchWithPrevKV
--- PASS: TestV3WatchWithPrevKV (0.34s)
PASS
ok      github.com/coreos/etcd/integration  215.335s
sharat@sharat-ubuntu:~/Go-Projects/src/github.com/coreos/etcd/integration$ 

What do i do for this?

@sinsharat
Copy link
Contributor Author

sinsharat commented Oct 31, 2016

@gyuho @xiang90 As i mentioned i am not able to figure out why this is failing in semaphore as it not giving any inoformation for its failure and in my system its passing all the time. What am i supposed to do with this? If its not useful enough shall i close it?

@xiang90
Copy link
Contributor

xiang90 commented Oct 31, 2016

We will take a look today

@sinsharat
Copy link
Contributor Author

@xiang90 Thank you!

@@ -113,6 +113,7 @@ func interestingGoroutines() (gs []string) {
strings.Contains(stack, "github.com/coreos/etcd/pkg/testutil.interestingGoroutines") ||
strings.Contains(stack, "github.com/coreos/etcd/pkg/logutil.(*MergeLogger).outputLoop") ||
strings.Contains(stack, "github.com/golang/glog.(*loggingT).flushDaemon") ||
strings.Contains(stack, "github.com/coreos/etcd/integration.TestV3ClientMetrics") ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't mask goroutine leaks for specific test cases; leak checking is incredibly useful for debugging and there's usually a way to write the test so it won't leak

Copy link
Contributor Author

@sinsharat sinsharat Oct 31, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyitsanthony i undertand your concern, i had initially mentioned a double check for this for net/http induced go routine as well as the current check, later i had modified this only to check if semaphore passes. But to no avail. As i had mentioned earlier as well i had written a custom code by passing listener to this, but on closing the listener the entire test was failing. Also i didn't find an alternative to close the go-routine i was setting up, But to no avail. Had asked for help from you as well for this but i guess you we busy with other work.As a last resort i had to dig deep and found an alternative this way. Would be grateful to you if you could help me out on closing the go routine which i am creating as i haven't been able to figure out an alternative to close this.
Thanks a lot for looking into this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert this. see my comment on the http server setup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

// listen for all prometheus metrics
go func() {
http.Handle("/metrics", prometheus.Handler())
http.ListenAndServe(":27989", nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to shutdown this http server after this test. or there will be go routine leak. you can create a listener first and close that listener after test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 if you see my sample code above i had already tried it. But closing the listener is also terminating the entire test case. Hence i had to come up with the current solution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i do not quite understand. why does it terminate the entire test case? also when we decide to close the listener, we should expect the test to finish, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 yes i expected the same but i have already tried and saw it terminating here. Please take a look at the code i had posted earlier. Let me know if i am doing anything wrong there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sinsharat

    log.Fatal(srv.Serve(ln.(*net.TCPListener)))

do not fatal here. get the error, if the error is closing ... then gracefully exit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will do that and will try it out. Thank you!

http.ListenAndServe(":27989", nil)
}()

clus := NewClusterV3(t, &ClusterConfig{Size: 3})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just use size 1? we do not really need a multi-member etcd cluster for this test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok Will change it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 For clientv3/integration it crating one client per member hence will require cluster of size 3 now. Or shall i move away from this behavior and write my custom code for this?

defer clus.Terminate(t)

ctxb := context.Background()
ctx, cancel := context.WithCancel(ctxb)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctx, cancel := context.WithCancel(context.Background())

and remove line42

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will do that.

@@ -0,0 +1,142 @@
// Copyright 2016 The etcd Authors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please move this test to clientv3/integration?

/integration is for server side testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will do it.

ctx, cancel := context.WithCancel(ctxb)
defer cancel()

wAPI := toGRPC(clus.RandClient()).Watch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use clientv3's API not raw gRPC API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}
}

func sumCountersForMetricAndLabels(metricName string, matchingLabelValues ...string) int {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we already have this somewhere? can we reuse that code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually i had checked it specific search at this depth is not available for members code it was available to one high level

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to reconstruct the code to avoid this kind of code duplication.

can you point to me where is the code that you copied this from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 its a reference from promtheus test case written on similar terms.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not from etcd code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. let's put aside this for now. i will try to give this a closer look if we make other stuff work well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 sure will do all the changes and test it. Will let you know once all the changes are done.


func getAllMetrics() []string {

url := "http://localhost:27989/metrics"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use hard coded value. pass the url into this func.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will change it.

// make an http request to fetch all prometheus metrics
resp, err := http.Get(url)
if err != nil {
log.Fatalf("fetch: %v\n", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use t.fatal in tests, not log.fatal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will modify it.

if err == io.EOF {
break
} else {
log.Fatalf("error reading stuff and the err is : %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use t.fatal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will change it

@xiang90
Copy link
Contributor

xiang90 commented Oct 31, 2016

Let's clean this up. ping me when it is ready for the next round of review. sorry for the delay.

@sinsharat
Copy link
Contributor Author

@xiang90 I have done the changes. PTAL.
Thank you!

)

var (
host string = "localhost"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this into the func as a local var?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also probably just addr := "localhost:27989"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

err error
)

// listen for all prometheus metrics
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the comments please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 only this comment or all the comments?

if addr == "" {
addr = ":http"
}
ln, err = net.Listen("tcp", addr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}()
}()

clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change size to 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 currently the integration framework is designed to have one client per member. Hence i had to make it 3.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we just use one client? why do we need multiple clients?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we need to have separate clients do to watch and put? client is thread-safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok you were right one client is sufficient. Will change it.

w := clientv3.NewWatcher(wclient)
defer w.Close()

// select a different client from wclient so puts succeed if
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? i do not quite understand this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiang90 on one client its watching. so not getting the same one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does not matter. it wont affect anything. one client can do multiple concurrent requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will test it out.


wc := w.Watch(ctxc, "foo1")

watchResponseBefore := sumCountersForMetricAndLabels(t, "grpc_client_msg_received_total", "Watch", "bidi_stream")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wbefore (try to use short variable name for local var)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will chnge it


watchResponseBefore := sumCountersForMetricAndLabels(t, "grpc_client_msg_received_total", "Watch", "bidi_stream")

putTotalBefore := sumCountersForMetricAndLabels(t, "grpc_client_started_total", "Put", "unary")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pbefore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will change it

watchResponseBefore := sumCountersForMetricAndLabels(t, "grpc_client_msg_received_total", "Watch", "bidi_stream")

putTotalBefore := sumCountersForMetricAndLabels(t, "grpc_client_started_total", "Put", "unary")
kv.Put(ctxc, "foo1", "bar")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will do that.


putTotalBefore := sumCountersForMetricAndLabels(t, "grpc_client_started_total", "Put", "unary")
kv.Put(ctxc, "foo1", "bar")
putTotalAfter := sumCountersForMetricAndLabels(t, "grpc_client_started_total", "Put", "unary")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pafter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will modify it.

putTotalAfter := sumCountersForMetricAndLabels(t, "grpc_client_started_total", "Put", "unary")

if putTotalBefore+1 != putTotalAfter {
t.Errorf("grpc_client_started_total should be incremented but recieved : %v\n", putTotalAfter-putTotalBefore)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.Errorf ("after = %d, want %d")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will chng it

}

// consume watch response
<-wc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

select {
    case <-wc:
    case <-time.After(10 * time.Second):
    ....

}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will chng it.

t.Errorf("grpc_client_msg_received_total should be incremented but recieved %v\n", watchResponseAfter-watchResponseBefore)
}

if ln != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove nil checking.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@sinsharat
Copy link
Contributor Author

@xiang90 Do you mean using round trip?

@xiang90
Copy link
Contributor

xiang90 commented Nov 2, 2016

@sinsharat Yes. Use that directly.

@sinsharat
Copy link
Contributor Author

@xiang90 ok will try it out and check. Thanks for the suggestion!

if err != nil {
t.Fatalf("Error : %v occured while listening on addr : %v", err, addr)
}
err = srv.Serve(ln)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

srv.SetKeepAlivesEnabled(false)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should go before the Serve; it will fix the leak.

mux := http.NewServeMux()
mux.Handle("/metrics", prometheus.Handler())

srv := &http.Server{Handler: mux}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mux isn't needed since only one handler:
srv := &http.Server{Handler: promehteus.Handler()}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyitsanthony @xiang90 had asked to not use nil and use custom handler instead. Hence had changed it to mux.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sinsharat we should do what @heyitsanthony suggested. we cannot put it as nil. but since this is the only handler, we do not really need a mux. We can put the handler itself here as the mux today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh? where's the nil here? I believe he was commenting about http.Handler + http.Server{Handler: nil}; http.Handler is bad because it's overriding defaults. This doesn't do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will do that.

)

// listen for all prometheus metrics
go func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test should probably wait until this goroutine completes,

donec := make(chan struct{})
go func() {
    defer close(donec)
    ...

t.Errorf("grpc_client_msg_received_total expected : %d, got %d", 1, wAfter-wBefore)
}
ln.Close()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<-donec

@sinsharat
Copy link
Contributor Author

@heyitsanthony I have done the changes as per your suggestion, but as i had judged earlier without channels as well the server was closing, and the problem of leak still persists. Will try doing what @xiang90 had suggested on top of your suggested changes.
Thank you!

@xiang90
Copy link
Contributor

xiang90 commented Nov 2, 2016

@sinsharat Can you push your recent changes to github?

@sinsharat
Copy link
Contributor Author

@xiang90 sure will do it.

@sinsharat
Copy link
Contributor Author

@xiang90 @heyitsanthony I have pushed the changes. PTAL.
Thank you!

t.Fatalf("Error : %v occured while listening on addr : %v", err, addr)
}
err = srv.Serve(ln)
srv.SetKeepAlivesEnabled(false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this line before serve?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will do it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyitsanthony @xiang90 You were right. it did fix the leak.
Thanks you so much for your help!

func getHTTPBodyAsLines(t *testing.T, url string) []string {
cfgtls := transport.TLSInfo{}
tr, err := transport.NewTransport(cfgtls, time.Second)
tr.DisableKeepAlives = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also set MaxIdleConns to -1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure will set it.

@sinsharat
Copy link
Contributor Author

@xiang90 @heyitsanthony PTAL.
Thank you!

lines = append(lines, line)
}
resp.Body.Close()
tr.CloseIdleConnections()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this? i think this is unnecessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will remove it.

// listen for all prometheus metrics
donec := make(chan struct{})
go func() {
// defer close(donec)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still use defer close(donec)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes right. i missed it.

if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
t.Fatalf("Err serving http requests: %v", err)
}
donec <- struct{}{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


ln, err = transport.NewUnixListener(addr)

if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

always put the error checking right after the operation? no empty lines between them. thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok sure will keep in mind from next time.

@xiang90
Copy link
Contributor

xiang90 commented Nov 2, 2016

LGTM. defer to @heyitsanthony and @gyuho

}

wAfter := sumCountersForMetricAndLabels(t, url, "grpc_client_msg_received_total", "Watch", "bidi_stream")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this empty line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

lines := []string{}
for {
line, err := reader.ReadString('\n')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this empty line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if err != nil {
if err == io.EOF {
break
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need this else right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gyuho We need this else for terminating if some un-expected error occurs.

lines = append(lines, line)
}
resp.Body.Close()
cli = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? It will be garbage collected anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gyuho had put that when i was looking for connection leak. Will remove it. Thanks!

@gyuho
Copy link
Contributor

gyuho commented Nov 2, 2016

lgtm. Defer to @heyitsanthony

Thanks @sinsharat !

@sinsharat
Copy link
Contributor Author

@xiang90 @heyitsanthony @gyuho Thank you so much for your support!

@heyitsanthony heyitsanthony merged commit fe755b6 into etcd-io:master Nov 2, 2016
@xiang90
Copy link
Contributor

xiang90 commented Nov 2, 2016

@sinsharat Thanks for getting it done!

@sinsharat
Copy link
Contributor Author

@xiang90 To be honest i am thankful to you and @heyitsanthony for helping me out on this.
Thanks again!

@sinsharat sinsharat deleted the client_metric_add_tests branch November 2, 2016 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants