/
server_side_diagnostics.go
113 lines (102 loc) · 4.34 KB
/
server_side_diagnostics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package ldclient
import (
"time"
"gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents"
"gopkg.in/launchdarkly/go-sdk-common.v2/ldvalue"
ldevents "gopkg.in/launchdarkly/go-sdk-events.v1"
"gopkg.in/launchdarkly/go-server-sdk.v5/interfaces"
)
func createDiagnosticsManager(
context interfaces.ClientContext,
sdkKey string,
config Config,
waitFor time.Duration,
) *ldevents.DiagnosticsManager {
id := ldevents.NewDiagnosticID(sdkKey)
return ldevents.NewDiagnosticsManager(
id,
makeDiagnosticConfigData(context, config, waitFor),
makeDiagnosticSDKData(),
time.Now(),
nil,
)
}
func makeDiagnosticConfigData(context interfaces.ClientContext, config Config, waitFor time.Duration) ldvalue.Value {
builder := ldvalue.ObjectBuild().
Set("startWaitMillis", durationToMillis(waitFor))
// Allow each pluggable component to describe its own relevant properties.
mergeComponentProperties(builder, context, config.HTTP, ldcomponents.HTTPConfiguration(), "")
mergeComponentProperties(builder, context, config.DataSource, ldcomponents.StreamingDataSource(), "")
mergeComponentProperties(builder, context, config.DataStore, ldcomponents.InMemoryDataStore(), "dataStoreType")
mergeComponentProperties(builder, context, config.Events, ldcomponents.SendEvents(), "")
return builder.Build()
}
var allowedDiagnosticComponentProperties = map[string]ldvalue.ValueType{ //nolint:gochecknoglobals
"allAttributesPrivate": ldvalue.BoolType,
"connectTimeoutMillis": ldvalue.NumberType,
"customBaseURI": ldvalue.BoolType,
"customEventsURI": ldvalue.BoolType,
"customStreamURI": ldvalue.BoolType,
"diagnosticRecordingIntervalMillis": ldvalue.NumberType,
"eventsCapacity": ldvalue.NumberType,
"eventsFlushIntervalMillis": ldvalue.NumberType,
"inlineUsersInEvents": ldvalue.BoolType,
"pollingIntervalMillis": ldvalue.NumberType,
"reconnectTimeMillis": ldvalue.NumberType,
"socketTimeoutMillis": ldvalue.NumberType,
"streamingDisabled": ldvalue.BoolType,
"userKeysCapacity": ldvalue.NumberType,
"userKeysFlushIntervalMillis": ldvalue.NumberType,
"usingProxy": ldvalue.BoolType,
"usingRelayDaemon": ldvalue.BoolType,
}
// Attempts to add relevant configuration properties, if any, from a customizable component:
// - If the component does not implement DiagnosticDescription, set the defaultPropertyName property to
// "custom".
// - If it does implement DiagnosticDescription or DiagnosticDescriptionExt, call the corresponding
// interface method to get a value.
// - If the value is a string, then set the defaultPropertyName property to that value.
// - If the value is an object, then copy all of its properties as long as they are ones we recognize
// and have the expected type.
func mergeComponentProperties(
builder ldvalue.ObjectBuilder,
context interfaces.ClientContext,
component interface{},
defaultComponent interface{},
defaultPropertyName string,
) {
if component == nil {
component = defaultComponent
}
var componentDesc ldvalue.Value
if dd, ok := component.(interfaces.DiagnosticDescriptionContext); ok {
componentDesc = dd.DescribeConfigurationContext(context)
} else if dd, ok := component.(interfaces.DiagnosticDescription); ok { //nolint:staticcheck // deprecated
componentDesc = dd.DescribeConfiguration() //nolint:staticcheck
}
if !componentDesc.IsNull() {
if componentDesc.Type() == ldvalue.StringType && defaultPropertyName != "" {
builder.Set(defaultPropertyName, componentDesc)
} else if componentDesc.Type() == ldvalue.ObjectType {
componentDesc.Enumerate(func(i int, name string, value ldvalue.Value) bool {
if allowedType, ok := allowedDiagnosticComponentProperties[name]; ok {
if value.IsNull() || value.Type() == allowedType {
builder.Set(name, value)
}
}
return true
})
}
} else if defaultPropertyName != "" {
builder.Set(defaultPropertyName, ldvalue.String("custom"))
}
}
func makeDiagnosticSDKData() ldvalue.Value {
return ldvalue.ObjectBuild().
Set("name", ldvalue.String("go-server-sdk")).
Set("version", ldvalue.String(Version)).
Build()
}
func durationToMillis(d time.Duration) ldvalue.Value {
return ldvalue.Float64(float64(uint64(d / time.Millisecond)))
}