Skip to content

Commit

Permalink
Merge pull request #365 from bmc-toolbox/tracing
Browse files Browse the repository at this point in the history
Adds tracing for client methods
  • Loading branch information
joelrebel authored Nov 17, 2023
2 parents 4666b85 + 2f99df1 commit b0ef181
Show file tree
Hide file tree
Showing 11 changed files with 259 additions and 19 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ The following one-time filters are available:
- `cl.For("gofish").GetPowerState(ctx)` - This removes any provider from the registry that is not the `gofish` provider.
- `cl.PreferProtocol("redfish").GetPowerState(ctx)` - This moves any provider that implements the `redfish` protocol to the beginning of the registry.

### Tracing

To collect trace telemetry, set the `WithTraceProvider()` option on the client
which results in trace spans being collected for each client method.

```go
cl := bmclib.NewClient(
host,
user,
pass,
bmclib.WithLogger(log),
bmclib.WithTracerProvider(otel.GetTracerProvider()),
)
```

## Versions

The current bmclib version is `v2` and is being developed on the `main` branch.
Expand Down
37 changes: 37 additions & 0 deletions bmc/bmc.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package bmc

import (
"strings"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

// Metadata represents details about a bmc method
type Metadata struct {
// SuccessfulProvider is the name of the provider that successfully executed
Expand All @@ -13,3 +20,33 @@ type Metadata struct {
// FailedProviderDetail holds the failed providers error messages for called methods
FailedProviderDetail map[string]string
}

func newMetadata() Metadata {
return Metadata{
FailedProviderDetail: make(map[string]string),
}
}

func (m *Metadata) RegisterSpanAttributes(host string, span trace.Span) {
span.SetAttributes(attribute.String("host", host))

span.SetAttributes(attribute.String("successful-provider", m.SuccessfulProvider))

span.SetAttributes(
attribute.String("successful-open-conns", strings.Join(m.SuccessfulOpenConns, ",")),
)

span.SetAttributes(
attribute.String("successful-close-conns", strings.Join(m.SuccessfulCloseConns, ",")),
)

span.SetAttributes(
attribute.String("attempted-providers", strings.Join(m.ProvidersAttempted, ",")),
)

for p, e := range m.FailedProviderDetail {
span.SetAttributes(
attribute.String("provider-errs-"+p, e),
)
}
}
12 changes: 5 additions & 7 deletions bmc/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ type connectionProviders struct {
// The reason failed ones need to be removed is so that when other methods are called (like powerstate)
// implementations that have connections wont nil pointer error when their connection fails.
func OpenConnectionFromInterfaces(ctx context.Context, timeout time.Duration, providers []interface{}) (opened []interface{}, metadata Metadata, err error) {
metadata = Metadata{
FailedProviderDetail: make(map[string]string),
}
metadata = newMetadata()

// Return immediately if the context is done.
select {
Expand Down Expand Up @@ -110,10 +108,8 @@ func OpenConnectionFromInterfaces(ctx context.Context, timeout time.Duration, pr
}

// closeConnection closes a connection to a BMC, trying all interface implementations passed in
func closeConnection(ctx context.Context, c []connectionProviders) (_ Metadata, err error) {
var metadata = Metadata{
FailedProviderDetail: make(map[string]string),
}
func closeConnection(ctx context.Context, c []connectionProviders) (metadata Metadata, err error) {
metadata = newMetadata()
var connClosed bool

for _, elem := range c {
Expand All @@ -138,6 +134,8 @@ func closeConnection(ctx context.Context, c []connectionProviders) (_ Metadata,

// CloseConnectionFromInterfaces identifies implementations of the Closer() interface and and passes the found implementations to the closeConnection() wrapper
func CloseConnectionFromInterfaces(ctx context.Context, generic []interface{}) (metadata Metadata, err error) {
metadata = newMetadata()

closers := make([]connectionProviders, 0)
for _, elem := range generic {
temp := connectionProviders{name: getProviderName(elem)}
Expand Down
12 changes: 12 additions & 0 deletions bmc/firmware.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func firmwareInstall(ctx context.Context, component, operationApplyTime string,

// FirmwareInstallFromInterfaces identifies implementations of the FirmwareInstaller interface and passes the found implementations to the firmwareInstall() wrapper
func FirmwareInstallFromInterfaces(ctx context.Context, component, operationApplyTime string, forceInstall bool, reader io.Reader, generic []interface{}) (taskID string, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]firmwareInstallerProvider, 0)
for _, elem := range generic {
temp := firmwareInstallerProvider{name: getProviderName(elem)}
Expand Down Expand Up @@ -146,6 +148,8 @@ func firmwareInstallStatus(ctx context.Context, installVersion, component, taskI

// FirmwareInstallStatusFromInterfaces identifies implementations of the FirmwareInstallVerifier interface and passes the found implementations to the firmwareInstallStatus() wrapper.
func FirmwareInstallStatusFromInterfaces(ctx context.Context, installVersion, component, taskID string, generic []interface{}) (status string, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]firmwareInstallVerifierProvider, 0)
for _, elem := range generic {
temp := firmwareInstallVerifierProvider{name: getProviderName(elem)}
Expand Down Expand Up @@ -223,6 +227,8 @@ func firmwareInstallUploaded(ctx context.Context, component, uploadTaskID string

// FirmwareInstallerUploadedFromInterfaces identifies implementations of the FirmwareInstallUploaded interface and passes the found implementations to the firmwareInstallUploaded() wrapper
func FirmwareInstallerUploadedFromInterfaces(ctx context.Context, component, uploadTaskID string, generic []interface{}) (installTaskID string, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]firmwareInstallerWithOptionsProvider, 0)
for _, elem := range generic {
temp := firmwareInstallerWithOptionsProvider{name: getProviderName(elem)}
Expand Down Expand Up @@ -260,6 +266,8 @@ type firmwareInstallStepsGetterProvider struct {

// FirmwareInstallStepsFromInterfaces identifies implementations of the FirmwareInstallStepsGetter interface and passes the found implementations to the firmwareInstallSteps() wrapper.
func FirmwareInstallStepsFromInterfaces(ctx context.Context, component string, generic []interface{}) (steps []constants.FirmwareInstallStep, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]firmwareInstallStepsGetterProvider, 0)
for _, elem := range generic {
temp := firmwareInstallStepsGetterProvider{name: getProviderName(elem)}
Expand Down Expand Up @@ -326,6 +334,8 @@ type firmwareUploaderProvider struct {

// FirmwareUploaderFromInterfaces identifies implementations of the FirmwareUploader interface and passes the found implementations to the firmwareUpload() wrapper.
func FirmwareUploadFromInterfaces(ctx context.Context, component string, file *os.File, generic []interface{}) (taskID string, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]firmwareUploaderProvider, 0)
for _, elem := range generic {
temp := firmwareUploaderProvider{name: getProviderName(elem)}
Expand Down Expand Up @@ -437,6 +447,8 @@ func firmwareTaskStatus(ctx context.Context, kind bconsts.FirmwareInstallStep, c

// FirmwareTaskStatusFromInterfaces identifies implementations of the FirmwareTaskVerifier interface and passes the found implementations to the firmwareTaskStatus() wrapper.
func FirmwareTaskStatusFromInterfaces(ctx context.Context, kind bconsts.FirmwareInstallStep, component, taskID, installVersion string, generic []interface{}) (state, status string, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]firmwareTaskVerifierProvider, 0)
for _, elem := range generic {
temp := firmwareTaskVerifierProvider{name: getProviderName(elem)}
Expand Down
2 changes: 2 additions & 0 deletions bmc/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ func inventory(ctx context.Context, generic []inventoryGetterProvider) (device *

// GetInventoryFromInterfaces identifies implementations of the InventoryGetter interface and passes the found implementations to the inventory() wrapper method
func GetInventoryFromInterfaces(ctx context.Context, generic []interface{}) (device *common.Device, metadata Metadata, err error) {
metadata = newMetadata()

implementations := make([]inventoryGetterProvider, 0)
for _, elem := range generic {
temp := inventoryGetterProvider{name: getProviderName(elem)}
Expand Down
4 changes: 4 additions & 0 deletions bmc/power.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func setPowerState(ctx context.Context, timeout time.Duration, state string, p [

// SetPowerStateFromInterfaces identifies implementations of the PostStateSetter interface and passes the found implementations to the setPowerState() wrapper.
func SetPowerStateFromInterfaces(ctx context.Context, timeout time.Duration, state string, generic []interface{}) (ok bool, metadata Metadata, err error) {
metadata = newMetadata()

powerSetter := make([]powerProviders, 0)
for _, elem := range generic {
temp := powerProviders{name: getProviderName(elem)}
Expand Down Expand Up @@ -126,6 +128,8 @@ func getPowerState(ctx context.Context, timeout time.Duration, p []powerProvider

// GetPowerStateFromInterfaces identifies implementations of the PostStateGetter interface and passes the found implementations to the getPowerState() wrapper.
func GetPowerStateFromInterfaces(ctx context.Context, timeout time.Duration, generic []interface{}) (state string, metadata Metadata, err error) {
metadata = newMetadata()

powerStateGetter := make([]powerProviders, 0)
for _, elem := range generic {
temp := powerProviders{name: getProviderName(elem)}
Expand Down
2 changes: 2 additions & 0 deletions bmc/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ func resetBMC(ctx context.Context, timeout time.Duration, resetType string, b []

// ResetBMCFromInterfaces identifies implementations of the BMCResetter interface and passes them to the resetBMC() wrapper method.
func ResetBMCFromInterfaces(ctx context.Context, timeout time.Duration, resetType string, generic []interface{}) (ok bool, metadata Metadata, err error) {
metadata = newMetadata()

bmcSetters := make([]bmcProviders, 0)
for _, elem := range generic {
temp := bmcProviders{name: getProviderName(elem)}
Expand Down
Loading

0 comments on commit b0ef181

Please sign in to comment.