@@ -9,6 +9,7 @@ package vxray
99
1010import (
1111 "fmt"
12+ "os"
1213
1314 "github.com/aws/aws-xray-sdk-go/awsplugins/beanstalk"
1415 "github.com/aws/aws-xray-sdk-go/awsplugins/ec2"
@@ -18,15 +19,18 @@ import (
1819 "v.io/v23/context"
1920 "v.io/v23/logging"
2021 "v.io/v23/vtrace"
22+ "v.io/x/ref/lib/aws/vxray/internal"
2123 "v.io/x/ref/lib/flags"
2224 libvtrace "v.io/x/ref/lib/vtrace"
2325)
2426
2527type options struct {
26- mergeLogging bool
27- mapToHTTP bool
28- newStore bool
29- newStoreFlags flags.VtraceFlags
28+ mergeLogging bool
29+ mapToHTTP bool
30+ newStore bool
31+ newStoreFlags flags.VtraceFlags
32+ configMap , configMapKey string
33+ containerized bool
3034}
3135
3236// Option represents an option to InitXRay.
@@ -53,6 +57,43 @@ func BeanstalkPlugin() Option {
5357 }
5458}
5559
60+ // KubernetesCluster configures obtaining information about the process'
61+ // current environment when running under Kubernetes (k8s), whether managed by
62+ // AWS EKS or any other control plane implementation. It requires that the
63+ // K8S configuration creates a configmap that contains the cluster name.
64+ // The configMap argument names that configmap and configMapKey
65+ // is the key in that configmap for the cluster name. For example, when using
66+ // the AWS cloudwatch/insights/xray-daemon daemonset the values for those
67+ // would be:
68+ // /api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info
69+ // cluster.name
70+ //
71+ // When configured, xray segments will contain a 'cluster_name' annotation.
72+ func KubernetesCluster (configMap , configMapKey string ) Option {
73+ return func (o * options ) {
74+ o .configMap , o .configMapKey = configMap , configMapKey
75+ }
76+ }
77+
78+ // EKSCluster calls KubernetesCluster with the values commonly used
79+ // with EKS clusters.
80+ func EKSCluster () Option {
81+ return KubernetesCluster ("/api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info" , "cluster.name" )
82+ }
83+
84+ // ContainerIDAndHost requests that container id and host information be
85+ // obtained and added to traces. The container id is obtained by parsing
86+ // the /proc/self/cgroup file, and the host by call the operating system's
87+ // hostname function. When running under kubernetes for example, the
88+ //
89+ // When configured, xray segments will contain 'container_id' and 'container_host'
90+ // annotations.
91+ func ContainerIDAndHost () Option {
92+ return func (o * options ) {
93+ o .containerized = true
94+ }
95+ }
96+
5697// MergeLogging arrays for xray logging messages to be merged with vanadium
5798// log messages.
5899func MergeLogging (v bool ) Option {
@@ -105,44 +146,73 @@ func (xl *xraylogger) Log(level xraylog.LogLevel, msg fmt.Stringer) {
105146 }
106147}
107148
108- func initXRay (ctx * context.T , config xray.Config , opts []Option ) (* context.T , * options , error ) {
109- o := & options {mapToHTTP : true }
110- for _ , fn := range opts {
111- fn (o )
112- }
149+ func (m * manager ) initXRay (ctx * context.T , config xray.Config ) (* context.T , error ) {
113150 if err := xray .Configure (config ); err != nil {
114151 ctx .Errorf ("failed to configure xray context: %v" , err )
115- return ctx , nil , err
152+ return ctx , err
116153 }
117- if o .mergeLogging {
154+ if m . options .mergeLogging {
118155 xray .SetLogger (& xraylogger {context .LoggerFromContext (ctx )})
119156 }
120157 ctx , err := WithConfig (ctx , config )
121- return ctx , o , err
158+ return ctx , err
122159}
123160
124161// InitXRay configures the AWS xray service and returns a context containing
125162// the xray configuration. This should only be called once. The vflags argument
126163// is used solely to check if xray tracing is enabled and not to create a
127- // new vtrace.Store, if a new store is required, the
164+ // new vtrace.Store, if a new/alternate store is required, the WithNewStore option
165+ // should be used to specify the store to be used.
128166func InitXRay (ctx * context.T , vflags flags.VtraceFlags , config xray.Config , opts ... Option ) (* context.T , error ) {
129167 if ! vflags .EnableAWSXRay {
130168 return ctx , nil
131169 }
132170 octx := ctx
133- ctx , options , err := initXRay (ctx , config , opts )
171+ mgr := & manager {}
172+ mgr .options .mapToHTTP = true
173+ for _ , fn := range opts {
174+ fn (& mgr .options )
175+ }
176+ ctx , err := mgr .initXRay (ctx , config )
134177 if err != nil {
135178 return octx , err
136179 }
137-
138- if options .newStore {
139- store , err := libvtrace .NewStore (options .newStoreFlags )
180+ if mgr .options .newStore {
181+ store , err := libvtrace .NewStore (mgr .options .newStoreFlags )
140182 if err != nil {
141183 return octx , err
142184 }
143185 ctx = vtrace .WithStore (ctx , store )
144186 }
145- mgr := & manager {mapToHTTP : options .mapToHTTP }
187+ if mgr .options .containerized {
188+ if hostNameErr == nil {
189+ mgr .containerHost = hostName
190+ } else {
191+ ctx .Infof ("failed to obtain host name from: %v" , hostNameErr )
192+ }
193+ cgroupFile := "/proc/self/cgroup"
194+ if cid , err := internal .GetContainerID (cgroupFile ); err == nil {
195+ mgr .containerID = cid
196+ } else {
197+ ctx .Infof ("failed to obtain container id" , err )
198+ }
199+ }
200+ if cm := mgr .options .configMap ; len (cm ) > 0 {
201+ if clusterName , err := internal .GetEKSClusterName (ctx , cm , mgr .options .configMapKey ); err == nil {
202+ mgr .clusterName = clusterName
203+ } else {
204+ ctx .Infof ("failed to obtain cluster name from %v.%v: %v" , cm , mgr .options .configMapKey , err )
205+ }
206+ }
146207 ctx = vtrace .WithManager (ctx , mgr )
147208 return ctx , nil
148209}
210+
211+ var (
212+ hostName string
213+ hostNameErr error
214+ )
215+
216+ func init () {
217+ hostName , hostNameErr = os .Hostname ()
218+ }
0 commit comments