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

[extension/solarwindsapmsettingsextension] Added remaining implementation of solarwindsapmsettingsextension #33315

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d53d9da
Added refresh logic
jerrytfleung May 30, 2024
f4258b1
Added changlog
jerrytfleung May 30, 2024
f24f425
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung May 30, 2024
f4c6d03
make gotidy
jerrytfleung May 30, 2024
4674c76
Update extension/solarwindsapmsettingsextension/extension.go
jerrytfleung Jun 3, 2024
d1cba82
Update extension/solarwindsapmsettingsextension/extension.go
jerrytfleung Jun 3, 2024
a0688c5
Updated log messages
jerrytfleung Jun 3, 2024
07212ee
Fixed export
jerrytfleung Jun 3, 2024
08dc77b
Removed gigantic else clause
jerrytfleung Jun 3, 2024
baa26f9
Added test case for refresh function
jerrytfleung Jun 18, 2024
0084eac
nits
jerrytfleung Jun 18, 2024
465c376
Fixed linter error
jerrytfleung Jun 18, 2024
0120d04
Simplified implementation
jerrytfleung Jun 18, 2024
172e950
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jun 18, 2024
8f65ad1
Updated otelcontribcol go modules
jerrytfleung Jun 18, 2024
85091f5
Updated
jerrytfleung Jun 18, 2024
0ef422b
Revert
jerrytfleung Jun 18, 2024
d75baae
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jun 19, 2024
d471abb
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jul 11, 2024
4c61613
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jul 15, 2024
ca529fb
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jul 16, 2024
005f428
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jul 16, 2024
ce61f50
Fixed go.mod after updating
jerrytfleung Jul 16, 2024
25be1fd
fixed go version
jerrytfleung Jul 16, 2024
7b92892
Reverted
jerrytfleung Jul 16, 2024
080daef
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jul 16, 2024
7119763
Update extension/solarwindsapmsettingsextension/extension.go
jerrytfleung Jul 17, 2024
1b59c85
Added to get system certificate pool for TLS config
jerrytfleung Jul 23, 2024
a2ee3fa
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Jul 23, 2024
da99852
Fixed go.mod
jerrytfleung Jul 23, 2024
2a17e91
Used os.TempDir()
jerrytfleung Aug 15, 2024
78f38c0
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Aug 15, 2024
59b1911
Updated dependencies
jerrytfleung Aug 15, 2024
5c78537
Applied configgrpc
jerrytfleung Aug 15, 2024
0b1330b
Applied ToClientConn function
jerrytfleung Aug 16, 2024
574d3f0
Fixed checkapi problem
jerrytfleung Aug 16, 2024
5bb4ddc
Fixed go.mod
jerrytfleung Aug 16, 2024
82ef634
nits
jerrytfleung Aug 16, 2024
3f31f51
Added more unit test cases & system pool
jerrytfleung Aug 16, 2024
cdeee9f
nits
jerrytfleung Aug 16, 2024
9475c30
nits
jerrytfleung Aug 16, 2024
398f3f4
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Aug 19, 2024
096ba0d
make gotidy
jerrytfleung Aug 19, 2024
45ce744
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Sep 3, 2024
630f1ce
Fixed go.mod
jerrytfleung Sep 3, 2024
a55f64e
Improved indentation
jerrytfleung Sep 3, 2024
a47f1c1
Merge branch 'main' into feature/solarwindsapmsettingsextension-impl-2
jerrytfleung Sep 3, 2024
33570e1
Fixed collector version from CI/CD error
jerrytfleung Sep 3, 2024
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
27 changes: 27 additions & 0 deletions .chloggen/feature_solarwindsapmsettingsetension-impl-2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: solarwindsapmsettingsextension

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Added logic for refresh function

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [27668]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
2 changes: 1 addition & 1 deletion extension/solarwindsapmsettingsextension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<!-- end autogenerated section -->

## Overview
The Solarwinds APM Settings extension gets Solarwinds APM specific settings from Solarwinds APM collector and `/tmp/solarwinds-apm-settings.json` & `/tmp/solarwinds-apm-settings-raw` periodically.
The Solarwinds APM Settings extension gets Solarwinds APM specific settings from Solarwinds APM collector and `/tmp/solarwinds-apm-settings.json` periodically.

## Configuration

Expand Down
140 changes: 138 additions & 2 deletions extension/solarwindsapmsettingsextension/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ package solarwindsapmsettingsextension // import "github.com/open-telemetry/open
import (
"context"
"crypto/tls"
"encoding/binary"
"encoding/json"
"math"
"os"
"strconv"
"time"

"github.com/solarwindscloud/apm-proto/go/collectorpb"
Expand All @@ -14,6 +19,12 @@ import (
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/protobuf/encoding/protojson"
)

const (
JSONOutputFile = "/tmp/solarwinds-apm-settings.json"
Copy link
Contributor

Choose a reason for hiding this comment

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

do those need to be exported?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. I fixed it.

GrpcContextDeadline = time.Duration(1) * time.Second
jerrytfleung marked this conversation as resolved.
Show resolved Hide resolved
)

type solarwindsapmSettingsExtension struct {
Expand Down Expand Up @@ -76,6 +87,131 @@ func (extension *solarwindsapmSettingsExtension) Shutdown(_ context.Context) err
}

func refresh(extension *solarwindsapmSettingsExtension) {
// Concrete implementation will be available in later PR
extension.logger.Info("refresh task")
extension.logger.Info("Time to refresh from " + extension.config.Endpoint)
if hostname, err := os.Hostname(); err != nil {
extension.logger.Error("Unable to call os.Hostname() " + err.Error())
} else {
ctx, cancel := context.WithTimeout(context.Background(), GrpcContextDeadline)
defer cancel()

request := &collectorpb.SettingsRequest{
ApiKey: extension.config.Key,
Identity: &collectorpb.HostID{
Hostname: hostname,
},
ClientVersion: "2",
Copy link
Contributor

Choose a reason for hiding this comment

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

In extension.Settings there is a build.Version that you could use if you wanted to identify what collector version was built.

I wonder if this should be set as part of the package coming in or use the provided collector version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The ClientVersion is fixed and we plan to migrate to OTLP. It is probably the last version.

}
if response, err := extension.client.GetSettings(ctx, request); err != nil {
extension.logger.Error("Unable to getSettings from " + extension.config.Endpoint + " " + err.Error())
jerrytfleung marked this conversation as resolved.
Show resolved Hide resolved
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

consider an early exit here to avoid this gigantic else clause

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. Done.

switch result := response.GetResult(); result {
case collectorpb.ResultCode_OK:
if len(response.GetWarning()) > 0 {
extension.logger.Warn(response.GetWarning())
}
var settings []map[string]any
for _, item := range response.GetSettings() {
marshalOptions := protojson.MarshalOptions{
UseEnumNumbers: true,
EmitUnpopulated: true,
}
if settingBytes, err := marshalOptions.Marshal(item); err != nil {
extension.logger.Warn("Error to marshal setting JSON[] byte from response.GetSettings() " + err.Error())
} else {
setting := make(map[string]any)
if err := json.Unmarshal(settingBytes, &setting); err != nil {
extension.logger.Warn("Error to unmarshal setting JSON object from setting JSON[]byte " + err.Error())
} else {
if value, ok := setting["value"].(string); ok {
if num, err := strconv.ParseInt(value, 10, 0); err != nil {
extension.logger.Warn("Unable to parse value " + value + " as number " + err.Error())
} else {
setting["value"] = num
}
}
if timestamp, ok := setting["timestamp"].(string); ok {
if num, err := strconv.ParseInt(timestamp, 10, 0); err != nil {
extension.logger.Warn("Unable to parse timestamp " + timestamp + " as number " + err.Error())
} else {
setting["timestamp"] = num
}
}
if ttl, ok := setting["ttl"].(string); ok {
if num, err := strconv.ParseInt(ttl, 10, 0); err != nil {
extension.logger.Warn("Unable to parse ttl " + ttl + " as number " + err.Error())
} else {
setting["ttl"] = num
}
}
if _, ok := setting["flags"]; ok {
setting["flags"] = string(item.Flags)
}
if arguments, ok := setting["arguments"].(map[string]any); ok {
if value, ok := item.Arguments["BucketCapacity"]; ok {
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 add code coverage for all this new 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.

Sure. Done

arguments["BucketCapacity"] = math.Float64frombits(binary.LittleEndian.Uint64(value))
}
if value, ok := item.Arguments["BucketRate"]; ok {
arguments["BucketRate"] = math.Float64frombits(binary.LittleEndian.Uint64(value))
}
if value, ok := item.Arguments["TriggerRelaxedBucketCapacity"]; ok {
arguments["TriggerRelaxedBucketCapacity"] = math.Float64frombits(binary.LittleEndian.Uint64(value))
}
if value, ok := item.Arguments["TriggerRelaxedBucketRate"]; ok {
arguments["TriggerRelaxedBucketRate"] = math.Float64frombits(binary.LittleEndian.Uint64(value))
}
if value, ok := item.Arguments["TriggerStrictBucketCapacity"]; ok {
arguments["TriggerStrictBucketCapacity"] = math.Float64frombits(binary.LittleEndian.Uint64(value))
}
if value, ok := item.Arguments["TriggerStrictBucketRate"]; ok {
arguments["TriggerStrictBucketRate"] = math.Float64frombits(binary.LittleEndian.Uint64(value))
}
if value, ok := item.Arguments["MetricsFlushInterval"]; ok {
arguments["MetricsFlushInterval"] = int32(binary.LittleEndian.Uint32(value))
}
if value, ok := item.Arguments["MaxTransactions"]; ok {
arguments["MaxTransactions"] = int32(binary.LittleEndian.Uint32(value))
}
if value, ok := item.Arguments["MaxCustomMetrics"]; ok {
arguments["MaxCustomMetrics"] = int32(binary.LittleEndian.Uint32(value))
}
if value, ok := item.Arguments["EventsFlushInterval"]; ok {
arguments["EventsFlushInterval"] = int32(binary.LittleEndian.Uint32(value))
}
if value, ok := item.Arguments["ProfilingInterval"]; ok {
arguments["ProfilingInterval"] = int32(binary.LittleEndian.Uint32(value))
}
// Remove SignatureKey from collector response
delete(arguments, "SignatureKey")
}
settings = append(settings, setting)
}
}
}
if content, err := json.Marshal(settings); err != nil {
extension.logger.Warn("Error to marshal setting JSON[] byte from settings " + err.Error())
} else {
if err := os.WriteFile(JSONOutputFile, content, 0600); err != nil {
extension.logger.Error("Unable to write " + JSONOutputFile + " " + err.Error())
} else {
if len(response.GetWarning()) > 0 {
extension.logger.Warn(JSONOutputFile + " is refreshed (soft disabled)")
} else {
extension.logger.Info(JSONOutputFile + " is refreshed")
}
extension.logger.Info(string(content))
}
}
case collectorpb.ResultCode_TRY_LATER:
extension.logger.Warn("GetSettings returned TRY_LATER " + response.GetWarning())
case collectorpb.ResultCode_INVALID_API_KEY:
extension.logger.Warn("GetSettings returned INVALID_API_KEY " + response.GetWarning())
case collectorpb.ResultCode_LIMIT_EXCEEDED:
extension.logger.Warn("GetSettings returned LIMIT_EXCEEDED " + response.GetWarning())
case collectorpb.ResultCode_REDIRECT:
extension.logger.Warn("GetSettings returned REDIRECT " + response.GetWarning())
default:
extension.logger.Warn("Unknown ResultCode from GetSettings " + response.GetWarning())
}
}
}
}
2 changes: 1 addition & 1 deletion extension/solarwindsapmsettingsextension/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
go.uber.org/goleak v1.3.0
go.uber.org/zap v1.27.0
google.golang.org/grpc v1.64.0
google.golang.org/protobuf v1.34.1
)

require (
Expand Down Expand Up @@ -45,6 +46,5 @@ require (
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)