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

[receiver/couchdb] Implement client #6880

Merged
merged 28 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
785be6b
establish couchdb codebase
JonathanWamsley Dec 9, 2021
bfb21e7
add in pr feedback
JonathanWamsley Dec 13, 2021
a220e16
add couchdb client
JonathanWamsley Dec 14, 2021
ab5994c
clean up names/format
JonathanWamsley Dec 15, 2021
6bce5da
fix linting ci
JonathanWamsley Dec 15, 2021
4ab7b7d
add couchdbreceiver to verisons
JonathanWamsley Dec 15, 2021
b0ad8dc
Merge branch 'couchdbreceiver-establish-codebase' into couchdbreceive…
JonathanWamsley Dec 15, 2021
139b16f
update with pr feedback
JonathanWamsley Dec 16, 2021
01fa266
establish couchdb codebase
JonathanWamsley Dec 9, 2021
9a6c8e2
add in pr feedback
JonathanWamsley Dec 13, 2021
f69ae48
clean up names/format
JonathanWamsley Dec 15, 2021
d38362c
fix linting ci
JonathanWamsley Dec 15, 2021
8d526a3
add couchdbreceiver to verisons
JonathanWamsley Dec 15, 2021
214f293
remove host validation
JonathanWamsley Dec 16, 2021
2fe8bbf
fix nit
JonathanWamsley Dec 16, 2021
255e154
Update receiver/couchdbreceiver/README.md
JonathanWamsley Dec 16, 2021
0f1d67e
add check for default endpoint on CreateDefaultConfig
JonathanWamsley Dec 16, 2021
c016372
add missing receivers in versions
JonathanWamsley Dec 16, 2021
edd11ed
change Nodes struct to nodes
JonathanWamsley Dec 16, 2021
d472012
merge from couchdb pr 1
JonathanWamsley Dec 16, 2021
86410ad
merge from couchdb pr1
JonathanWamsley Dec 16, 2021
8342062
update client pr feedback
JonathanWamsley Dec 16, 2021
caf6d09
merge with main
JonathanWamsley Jan 3, 2022
bcc1d88
Merge branch 'main' into couchdbreceiver-client
JonathanWamsley Jan 4, 2022
36e1f5f
update changelog
JonathanWamsley Jan 4, 2022
ce05339
Merge branch 'main' into couchdbreceiver-client
JonathanWamsley Jan 4, 2022
e35bfd2
Merge branch 'main' into couchdbreceiver-client
JonathanWamsley Jan 4, 2022
c3a13cc
update client tests w/ default config
JonathanWamsley Jan 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions receiver/couchdbreceiver/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package couchdbreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/couchdbreceiver"

import (
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"

"go.opentelemetry.io/collector/component"
"go.uber.org/zap"
)

const nodeNamesPath = "/_membership"

// CouchDBClient defines the basic HTTP client interface.
type CouchDBClient interface {
djaglowski marked this conversation as resolved.
Show resolved Hide resolved
Get(path string) ([]byte, error)
GetNodeNames() ([]string, error)
GetStats(nodeName string) (map[string]interface{}, error)
}

var _ CouchDBClient = (*couchDBClient)(nil)

type couchDBClient struct {
client *http.Client
cfg *Config
logger *zap.Logger
}

// NewCouchDBClient creates a new client to make requests for the CouchDB receiver.
func NewCouchDBClient(cfg *Config, host component.Host, logger *zap.Logger) (CouchDBClient, error) {
djaglowski marked this conversation as resolved.
Show resolved Hide resolved
client, err := cfg.ToClient(host.GetExtensions())
if err != nil {
return nil, fmt.Errorf("failed to create HTTP Client: %w", err)
}

return &couchDBClient{
client: client,
cfg: cfg,
logger: logger,
}, nil
}

// Get issues an authorized Get requests to the specified url.
func (cc *couchDBClient) Get(path string) ([]byte, error) {
req, err := cc.buildReq(path)
if err != nil {
return nil, err
}

resp, err := cc.client.Do(req)
if err != nil {
return nil, err
}

defer func() {
if err = resp.Body.Close(); err != nil {
cc.logger.Warn("failed to close response body", zap.Error(err))
}
}()

if resp.StatusCode != http.StatusOK {
if resp.StatusCode >= 400 {
cc.logger.Error("couchdb", zap.Error(err), zap.String("status_code", strconv.Itoa(resp.StatusCode)))
}
return nil, fmt.Errorf("request GET %s failed - %q", req.URL.String(), resp.Status)
}

body, err := io.ReadAll(resp.Body)
jpkrohling marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, fmt.Errorf("failed to read response body %w", err)
}

return body, nil
}

// nodes contains a list of all known connected node names.
type nodes struct {
AllNodes []string `json:"all_nodes"`
}

// GetNodeNames gets all known connected nodes names.
func (cc *couchDBClient) GetNodeNames() ([]string, error) {
djaglowski marked this conversation as resolved.
Show resolved Hide resolved
body, err := cc.Get(nodeNamesPath)
if err != nil {
return nil, err
}

var nodeNames nodes
err = json.Unmarshal(body, &nodeNames)
if err != nil {
return nil, err
}

return nodeNames.AllNodes, nil
}

// GetStats gets couchdb stats at a specific node name endpoint.
func (cc *couchDBClient) GetStats(nodeName string) (map[string]interface{}, error) {
path := fmt.Sprintf("/_node/%s/_stats/couchdb", nodeName)
body, err := cc.Get(path)
if err != nil {
return nil, err
}

var stats map[string]interface{}
err = json.Unmarshal(body, &stats)
if err != nil {
return nil, err
}

return stats, nil
}

func (cc *couchDBClient) buildReq(path string) (*http.Request, error) {
url := cc.cfg.Endpoint + path
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(cc.cfg.Username, cc.cfg.Password)
return req, nil
}
Loading