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/nsxreceiver] Add NSX-T Metrics Receiver #9738

Merged
merged 55 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
5a8bad1
wip
schmikei Apr 19, 2022
70c7222
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei Apr 27, 2022
0f06ef7
mostly working independent client
schmikei Apr 27, 2022
86259a0
wip
schmikei Apr 29, 2022
b7a1039
add logs and unit testing
schmikei May 3, 2022
54847e3
log error on failed start
schmikei May 3, 2022
23ea423
ensure client on scrape
schmikei May 3, 2022
900f710
remove router since no stats can be grabbed for it
schmikei May 3, 2022
84610fe
more unit tests
schmikei May 3, 2022
460cc98
addlicense to test files
schmikei May 3, 2022
49574f4
more tests
schmikei May 3, 2022
edcc705
more tests
schmikei May 3, 2022
5855ee3
add Readme
schmikei May 3, 2022
39be4c8
fix typo
schmikei May 3, 2022
e923ecd
update readme again
schmikei May 3, 2022
06e2594
rename file
schmikei May 4, 2022
14b7aec
finish rename
schmikei May 4, 2022
67b0b50
gotidy
schmikei May 4, 2022
4245ab9
remove logging component
schmikei May 4, 2022
9eea7f3
add more test coverage
schmikei May 4, 2022
f43a320
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei May 4, 2022
80804d4
update changelog
schmikei May 4, 2022
d57a98a
add to receivers_test
schmikei May 4, 2022
1f0c246
fix semconv replace (no longer needed)
schmikei May 4, 2022
4e7c5b3
add to codeowners and fix import check
schmikei May 4, 2022
509c430
make goporto
schmikei May 4, 2022
f656b45
use newer mdatagen
schmikei May 4, 2022
899aeef
fix ineffectual assignment
schmikei May 4, 2022
8738253
add to versions.yaml
schmikei May 4, 2022
63209b3
some minor README updates and factory test update
schmikei May 4, 2022
0113ced
another test fix
schmikei May 4, 2022
d02419c
move folder to nsxtreceiver
schmikei May 9, 2022
82293a8
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei May 9, 2022
f38f256
fix go.mod
schmikei May 9, 2022
49f4fc1
finish rename
schmikei May 9, 2022
b789e45
don't use requestOptions until necessary
schmikei May 9, 2022
13a0150
fix receiver type change: nsx -> nsxt
schmikei May 9, 2022
70d273c
update factory_test.go
schmikei May 9, 2022
091b363
remove disk attribute for node disk usage metrics
schmikei May 9, 2022
70c254c
remove unnecessary conversion
schmikei May 9, 2022
1d80dde
PR feedback
schmikei May 9, 2022
aa8230e
try to accomodate feedback on metric names
schmikei May 10, 2022
f43231d
fix collection of mem_cache
schmikei May 10, 2022
49bbbb9
remove underscore
schmikei May 10, 2022
b3436fa
remove comment and add nodeType and nodeID to network metrics
schmikei May 11, 2022
7f187a8
fix expected metrics with new resource attributes
schmikei May 11, 2022
a059ed6
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei May 11, 2022
f568e32
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei May 12, 2022
e496de9
fix alibaba version
schmikei May 12, 2022
8017881
fix alibaba version; again
schmikei May 12, 2022
2a24517
accomodate small changes to attribute name and simple error return ch…
schmikei May 12, 2022
2e6cc25
just return error instead of 1 error errors.Combine()
schmikei May 12, 2022
aade34f
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei May 12, 2022
38c88dd
use latest mdatagen
schmikei May 12, 2022
4984246
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
schmikei May 12, 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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ receiver/mongodbreceiver/ @open-telemetry/collector-c
receiver/mongodbatlasreceiver/ @open-telemetry/collector-contrib-approvers @zenmoto
receiver/mysqlreceiver/ @open-telemetry/collector-contrib-approvers @djaglowski
receiver/nginxreceiver/ @open-telemetry/collector-contrib-approvers @djaglowski
receiver/nsxtreceiver/ @open-telemetry/collector-contrib-approvers @dashpole @schmikei
receiver/postgresqlreceiver/ @open-telemetry/collector-contrib-approvers @djaglowski
receiver/prometheusexecreceiver/ @open-telemetry/collector-contrib-approvers @dmitryax
receiver/prometheusreceiver/ @open-telemetry/collector-contrib-approvers @Aneurysm9 @dashpole
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

- `schemaprocessor`: Starting the initial work to allow from translating from semantic convention to another (#8371)
- `saphanareceiver`: Added implementation of SAP HANA Metric Receiver (#8827)
- `nsxtreceiver`: Added implementation of NSX-T Metric Receiver (#9568)
- `logstransformprocessor`: Add implementation of Logs Transform Processor (#9335)

### 💡 Enhancements 💡
Expand Down
4 changes: 4 additions & 0 deletions cmd/configschema/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mongodbreceiver v0.51.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver v0.51.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver v0.51.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver v0.51.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver v0.51.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/podmanreceiver v0.51.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/postgresqlreceiver v0.51.0 // indirect
Expand Down Expand Up @@ -450,6 +451,7 @@ require (
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/vmware/go-vmware-nsxt v0.0.0-20220328155605-f49a14c1ef5f // indirect
github.com/wavefronthq/wavefront-sdk-go v0.9.11 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
Expand Down Expand Up @@ -784,6 +786,8 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysql

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver => ../../receiver/nginxreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver => ../../receiver/nsxtreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver => ../../receiver/opencensusreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/podmanreceiver => ../../receiver/podmanreceiver
Expand Down
2 changes: 2 additions & 0 deletions cmd/configschema/go.sum

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

4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mongodbreceiver v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/podmanreceiver v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/postgresqlreceiver v0.51.0
Expand Down Expand Up @@ -451,6 +452,7 @@ require (
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/vmware/go-vmware-nsxt v0.0.0-20220328155605-f49a14c1ef5f // indirect
github.com/wavefronthq/wavefront-sdk-go v0.9.11 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
Expand Down Expand Up @@ -789,6 +791,8 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysql

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver => ./receiver/nginxreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver => ./receiver/nsxtreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver => ./receiver/opencensusreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/podmanreceiver => ./receiver/podmanreceiver
Expand Down
2 changes: 2 additions & 0 deletions go.sum

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

2 changes: 2 additions & 0 deletions internal/components/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mongodbreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/podmanreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/postgresqlreceiver"
Expand Down Expand Up @@ -214,6 +215,7 @@ func Components() (component.Factories, error) {
mongodbatlasreceiver.NewFactory(),
mongodbreceiver.NewFactory(),
mysqlreceiver.NewFactory(),
nsxtreceiver.NewFactory(),
nginxreceiver.NewFactory(),
opencensusreceiver.NewFactory(),
otlpreceiver.NewFactory(),
Expand Down
3 changes: 3 additions & 0 deletions internal/components/receivers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ func TestDefaultReceivers(t *testing.T) {
{
receiver: "nginx",
},
{
receiver: "nsxt",
},
{
receiver: "opencensus",
skipLifecyle: true, // TODO: Usage of CMux doesn't allow proper shutdown.
Expand Down
1 change: 1 addition & 0 deletions receiver/nsxtreceiver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../../Makefile.Common
66 changes: 66 additions & 0 deletions receiver/nsxtreceiver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# NSX-T Receiver

This receiver fetches metrics important to run virtual networking using NSX-T. The receiver ingests metrics via the [NSX Rest API](https://docs.vmware.com/en/VMware-NSX-Data-Center-for-vSphere/6.4/nsx_64_api.pdf).

Supported pipeline types: `metrics`

> :construction: This receiver is in **ALPHA**. Configuration fields and metric data model are subject to change.

## Purpose

The purpose of this receiver is to allow users to monitor metrics from NSX-T environments.

## Prerequisites

Needs at least an “Auditor” user for NSX Manager Resources in the vSphere Client (can be created via Web UI or CLI)

The collector must be able to reach the NSX Manager with port 443 open.

This receiver supports NSX-T Datacenter versions:

- 3.2.0
- 3.1.2

## Configuration

- `endpoint`: Endpoint of the NSX Manager. Must be formatted as `{scheme}://{host}:{port}`. Schems supported are `http` and `https`

- `username`: Username of the `Auditor` user

- `password`: Password of the `Auditor` user

- `collection_interval`: (default = `1m`): This receiver collects metrics on an interval. This value must be a string readable by Golang's [time.ParseDuration](https://pkg.go.dev/time#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`.

- `timeout`: (default = `1m`) The timeout of running commands against the NSX REST API.

- `metrics` (default: see DefaultMetricsSettings [here])(./internal/metadata/generated_metrics_v2.go): Allows enabling and disabling specific metrics from being collected in this receiver.

### Example Configuration

```yaml
receivers:
nsxt:
endpoint: https://nsx-manager
username: admin
password: password
timeout: 60s
metrics:
nsxt.node.cpu.utilization:
enabled: false

exporters:
file:
path: "./content.json"

service:
pipelines:
metrics:
receivers: [nsxt]
exporters: [file]
```

The full list of settings exposed for this receiver are documented [here](./config.go) with detailed sample configurations [here](./testdata/config.yaml).

## Metrics

Details about the metrics produced by this receiver can be found in [metadata.yaml](./metadata.yaml)
218 changes: 218 additions & 0 deletions receiver/nsxtreceiver/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// 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 nsxtreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver"
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"

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

dm "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nsxtreceiver/internal/model"
)

var _ (Client) = &nsxClient{}

// Client is a way of interacting with the NSX REST API
type Client interface {
TransportNodes(ctx context.Context) ([]dm.TransportNode, error)
ClusterNodes(ctx context.Context) ([]dm.ClusterNode, error)
NodeStatus(ctx context.Context, nodeID string, class nodeClass) (*dm.NodeStatus, error)
Interfaces(ctx context.Context, nodeID string, class nodeClass) ([]dm.NetworkInterface, error)
InterfaceStatus(ctx context.Context, nodeID, interfaceID string, class nodeClass) (*dm.NetworkInterfaceStats, error)
}

type nsxClient struct {
config *Config
client *http.Client
endpoint *url.URL
logger *zap.Logger
}

var (
errUnauthorized = errors.New("STATUS 403, unauthorized")
)

func newClient(c *Config, settings component.TelemetrySettings, host component.Host, logger *zap.Logger) (*nsxClient, error) {
client, err := c.HTTPClientSettings.ToClient(host.GetExtensions(), settings)
if err != nil {
return nil, err
}

endpoint, err := url.Parse(c.Endpoint)
if err != nil {
return nil, err
}

return &nsxClient{
config: c,
client: client,
endpoint: endpoint,
logger: logger,
}, nil
}

func (c *nsxClient) TransportNodes(ctx context.Context) ([]dm.TransportNode, error) {
body, err := c.doRequest(
ctx,
"/api/v1/transport-nodes",
)
if err != nil {
return nil, err
}
var nodes dm.TransportNodeList
err = json.Unmarshal(body, &nodes)
return nodes.Results, err
}

func (c *nsxClient) ClusterNodes(ctx context.Context) ([]dm.ClusterNode, error) {
body, err := c.doRequest(
ctx,
"/api/v1/cluster/nodes",
)
if err != nil {
return nil, fmt.Errorf("unable to get cluster nodes: %w", err)
}
var nodes dm.ClusterNodeList
err = json.Unmarshal(body, &nodes)

return nodes.Results, err
}

func (c *nsxClient) NodeStatus(ctx context.Context, nodeID string, class nodeClass) (*dm.NodeStatus, error) {
body, err := c.doRequest(
ctx,
c.nodeStatusEndpoint(class, nodeID),
)
if err != nil {
return nil, fmt.Errorf("unable to get a node's status from the REST API: %w", err)
}

switch class {
case transportClass:
var nodeStatus dm.TransportNodeStatus
err = json.Unmarshal(body, &nodeStatus)
return &nodeStatus.NodeStatus, err
default:
var nodeStatus dm.NodeStatus
err = json.Unmarshal(body, &nodeStatus)
return &nodeStatus, err
}

}

func (c *nsxClient) Interfaces(
ctx context.Context,
nodeID string,
class nodeClass,
) ([]dm.NetworkInterface, error) {
body, err := c.doRequest(
ctx,
c.interfacesEndpoint(class, nodeID),
)
if err != nil {
return nil, err
}
var interfaces dm.NodeNetworkInterfacePropertiesListResult
err = json.Unmarshal(body, &interfaces)

return interfaces.Results, err
}

func (c *nsxClient) InterfaceStatus(
ctx context.Context,
nodeID, interfaceID string,
class nodeClass,
) (*dm.NetworkInterfaceStats, error) {
body, err := c.doRequest(
ctx,
c.interfaceStatusEndpoint(class, nodeID, interfaceID),
)

if err != nil {
return nil, fmt.Errorf("unable to get interface stats: %w", err)
}
var interfaceStats dm.NetworkInterfaceStats
err = json.Unmarshal(body, &interfaceStats)
return &interfaceStats, err
}

func (c *nsxClient) doRequest(ctx context.Context, path string) ([]byte, error) {
endpoint, err := c.endpoint.Parse(path)
if err != nil {
return nil, err
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(c.config.Username, c.config.Password)
h := req.Header
h.Add("User-Agent", "opentelemetry-collector")
h.Add("Accept", "application/json")
h.Add("Connection", "keep-alive")

resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
return io.ReadAll(resp.Body)
}

body, _ := io.ReadAll(resp.Body)
switch resp.StatusCode {
case 403:
return nil, errUnauthorized
default:
c.logger.Info(fmt.Sprintf("%v", req))
return nil, fmt.Errorf("got non 200 status code %d: %w, %s", resp.StatusCode, err, string(body))
}
}

func (c *nsxClient) nodeStatusEndpoint(class nodeClass, nodeID string) string {
switch class {
case transportClass:
return fmt.Sprintf("/api/v1/transport-nodes/%s/status", nodeID)
default:
return fmt.Sprintf("/api/v1/cluster/nodes/%s/status", nodeID)
}
}

func (c *nsxClient) interfacesEndpoint(class nodeClass, nodeID string) string {
switch class {
case transportClass:
return fmt.Sprintf("/api/v1/transport-nodes/%s/network/interfaces", nodeID)
default:
return fmt.Sprintf("/api/v1/cluster/nodes/%s/network/interfaces", nodeID)
}
}

func (c *nsxClient) interfaceStatusEndpoint(class nodeClass, nodeID, interfaceID string) string {
switch class {
case transportClass:
return fmt.Sprintf("/api/v1/transport-nodes/%s/network/interfaces/%s/stats", nodeID, interfaceID)
default:
return fmt.Sprintf("/api/v1/cluster/nodes/%s/network/interfaces/%s/stats", nodeID, interfaceID)
}
}
Loading