Skip to content

Commit

Permalink
Use new runtime detector for logging process events (#1645)
Browse files Browse the repository at this point in the history
  • Loading branch information
RonFed authored Oct 31, 2024
1 parent 509afdc commit 2f478f0
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 22 deletions.
9 changes: 9 additions & 0 deletions common/envOverwrite/overwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ var EnvValuesMap = map[string]envValues{
},
}

func GetRelevantEnvVarsKeys() []string {
keys := make([]string, 0, len(EnvValuesMap))
for key := range EnvValuesMap {
keys = append(keys, key)
}
return keys
}


// returns the current value that should be populated in a specific environment variable.
// if we should not patch the value, returns nil.
// the are 2 parts to the environment value: odigos part and user part.
Expand Down
13 changes: 4 additions & 9 deletions instrumentor/controllers/instrumentationdevice/pods_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,13 @@ import (
"strings"

common "github.com/odigos-io/odigos/common"
"github.com/odigos-io/odigos/k8sutils/pkg/consts"
"sigs.k8s.io/controller-runtime/pkg/webhook"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)

const (
EnvVarNamespace = "ODIGOS_WORKLOAD_NAMESPACE"
EnvVarContainerName = "ODIGOS_CONTAINER_NAME"
EnvVarPodName = "ODIGOS_POD_NAME"
)

type PodsWebhook struct{}

var _ webhook.CustomDefaulter = &PodsWebhook{}
Expand All @@ -43,15 +38,15 @@ func injectOdigosEnvVars(pod *corev1.Pod) {
// Common environment variables that do not change across containers
commonEnvVars := []corev1.EnvVar{
{
Name: EnvVarNamespace,
Name: consts.OdigosEnvVarNamespace,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
},
},
},
{
Name: EnvVarPodName,
Name: consts.OdigosEnvVarPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
Expand All @@ -74,7 +69,7 @@ func injectOdigosEnvVars(pod *corev1.Pod) {
}

container.Env = append(container.Env, append(commonEnvVars, corev1.EnvVar{
Name: EnvVarContainerName,
Name: consts.OdigosEnvVarContainerName,
Value: container.Name,
})...)
}
Expand Down
14 changes: 14 additions & 0 deletions k8sutils/pkg/consts/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ const (

OdigosNodeCollectorConfigMapKey = "conf" // this key is different than the cluster collector value. not sure why
)

const (
OdigosEnvVarNamespace = "ODIGOS_WORKLOAD_NAMESPACE"
OdigosEnvVarContainerName = "ODIGOS_CONTAINER_NAME"
OdigosEnvVarPodName = "ODIGOS_POD_NAME"
)

func OdigosInjectedEnvVars() []string {
return []string{
OdigosEnvVarNamespace,
OdigosEnvVarContainerName,
OdigosEnvVarPodName,
}
}
19 changes: 9 additions & 10 deletions odiglet/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.PHONY: build-odiglet generate

LIBRARIES := go.opentelemetry.io/auto \
github.com/odigos-io/runtime-detector

build-odiglet: generate
CGO_ENABLED=0 go build -o odiglet cmd/main.go

Expand All @@ -8,15 +11,11 @@ debug-build-odiglet: generate

generate:
go mod download
GO_AUTO_PATH=$$(go list -m -f '{{.Dir}}' "go.opentelemetry.io/auto") && \
cd $$GO_AUTO_PATH && \
chmod -R +w $$GO_AUTO_PATH && \
make generate
@for lib in $(LIBRARIES); do \
LIB_PATH=$$(go list -m -f '{{.Dir}}' $${lib%@*}) && \
chmod -R +w $$LIB_PATH && \
make -C "$$LIB_PATH" generate; \
done

test:
go mod download
GO_AUTO_PATH=$$(go list -m -f '{{.Dir}}' "go.opentelemetry.io/auto") && \
sudo chmod -R +w $$GO_AUTO_PATH && \
cd $$GO_AUTO_PATH && \
make generate
test: generate
go test -v ./...
14 changes: 14 additions & 0 deletions odiglet/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/odigos-io/odigos/odiglet/pkg/ebpf/sdks"
"github.com/odigos-io/odigos/odiglet/pkg/instrumentation/fs"
detector "github.com/odigos-io/odigos/odiglet/pkg/detector"

"github.com/kubevirt/device-plugin-manager/pkg/dpm"
"github.com/odigos-io/odigos/common"
Expand Down Expand Up @@ -71,6 +72,13 @@ func main() {

go startDeviceManager(clientset)

procEvents := make(chan detector.ProcessEvent)
runtimeDetector, err := detector.StartRuntimeDetector(ctx, log.Logger, procEvents)
if err != nil {
log.Logger.Error(err, "Failed to start runtime detector")
os.Exit(-1)
}

mgr, err := kube.CreateManager()
if err != nil {
log.Logger.Error(err, "Failed to create controller-runtime manager")
Expand Down Expand Up @@ -105,6 +113,12 @@ func main() {
for _, director := range ebpfDirectors {
director.Shutdown()
}
err = runtimeDetector.Stop()
if err != nil {
log.Logger.Error(err, "Failed to stop runtime detector")
os.Exit(-1)
}
log.Logger.V(0).Info("odiglet exiting")
}

func startDeviceManager(clientset *kubernetes.Clientset) {
Expand Down
1 change: 1 addition & 0 deletions odiglet/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/odigos-io/odigos/opampserver v0.0.0
github.com/odigos-io/odigos/procdiscovery v0.0.0
github.com/odigos-io/opentelemetry-zap-bridge v0.0.5
github.com/odigos-io/runtime-detector v0.0.2
github.com/stretchr/testify v1.9.0
go.opentelemetry.io/auto v0.15.0-alpha
go.opentelemetry.io/otel v1.30.0
Expand Down
2 changes: 2 additions & 0 deletions odiglet/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/odigos-io/opentelemetry-zap-bridge v0.0.5 h1:UDEKtgab42nGVSvA/F3lLKUYFPETtpl7kpxM9BKBlWk=
github.com/odigos-io/opentelemetry-zap-bridge v0.0.5/go.mod h1:K98wHhktQ6vCTqeFztcpBDtPTe88vxVgZFlbeGobt24=
github.com/odigos-io/runtime-detector v0.0.2 h1:8G6KOBxlmP0vu+/62lHbvjSDARP+DML0gk5ypcdZOpg=
github.com/odigos-io/runtime-detector v0.0.2/go.mod h1:m8GfdG6pET0K/8aoZwnX+MkYz8oVroKs8HzRnkuJWt4=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down
107 changes: 107 additions & 0 deletions odiglet/pkg/detector/detector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package detector

import (
"context"
"errors"
"fmt"
"log/slog"
"sync"

"github.com/go-logr/logr"
"github.com/odigos-io/odigos/common/envOverwrite"
"github.com/odigos-io/odigos/k8sutils/pkg/consts"
"github.com/odigos-io/odigos/procdiscovery/pkg/process"
"github.com/odigos-io/runtime-detector"
)

type ProcessEvent = detector.ProcessEvent

type Detector struct {
detector *detector.Detector
wg sync.WaitGroup
runError error
}

func StartRuntimeDetector(ctx context.Context, logger logr.Logger, events chan ProcessEvent) (*Detector, error) {
detector, err := newDetector(ctx, logger, events)
if err != nil {
return nil, fmt.Errorf("failed to create runtime detector: %w", err)
}

d := &Detector{detector: detector}

d.wg.Add(1)
go func() {
defer d.wg.Done()
readProcEventsLoop(logger, events)
}()

d.wg.Add(1)
go func() {
defer d.wg.Done()
d.runError = detector.Run(ctx)
}()

return d, nil
}

func (d *Detector) Stop() error {
err := d.detector.Stop()
d.wg.Wait()
return errors.Join(d.runError, err)
}

func newDetector(ctx context.Context, logger logr.Logger, events chan ProcessEvent) (*detector.Detector, error) {
sLogger := slog.New(logr.ToSlogHandler(logger))

opts := []detector.DetectorOption{
detector.WithLogger(sLogger),
detector.WithEnvironments(relevantEnvVars()...),
}
detector, err := detector.NewDetector(ctx, events, opts...)

if err != nil {
return nil, err
}

return detector, nil
}

func readProcEventsLoop(l logr.Logger, events chan ProcessEvent) {
l = l.WithName("process detector")
for e := range events {
switch e.EventType {
case detector.ProcessExecEvent:
l.Info("detected new process",
"pid", e.PID,
"cmd", e.ExecDetails.CmdLine,
"exeName", e.ExecDetails.ExeName,
"exeLink", e.ExecDetails.ExeLink,
"envs", e.ExecDetails.Environments,
"container PID", e.ExecDetails.ContainerProcessID,
)
case detector.ProcessExitEvent:
l.Info("detected process exit",
"pid", e.PID,
)
}
}
}

func relevantEnvVars() []string {
// env vars related to language versions
versionEnvs := process.LangsVersionEnvs

envs := make([]string, 0, len(versionEnvs))
for env := range versionEnvs {
envs = append(envs, env)
}

// env vars that Odigos is using for adding dependencies
envs = append(envs, envOverwrite.GetRelevantEnvVarsKeys()...)

// env vars that Odigos is injecting to the relevant containers
envs = append(envs, consts.OdigosInjectedEnvVars()...)

return envs
}
6 changes: 3 additions & 3 deletions procdiscovery/pkg/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const NodeVersionConst = "NODE_VERSION"
const PythonVersionConst = "PYTHON_VERSION"
const JavaVersionConst = "JAVA_VERSION"

// envDetailsMap is a map of environment variables and their separators
var envDetailsMap = map[string]struct{}{NodeVersionConst: {}, PythonVersionConst: {}, JavaVersionConst: {}}
// LangsVersionEnvs is a map of environment variables used for detecting the versions of different languages
var LangsVersionEnvs = map[string]struct{}{NodeVersionConst: {}, PythonVersionConst: {}, JavaVersionConst: {}}

type Details struct {
ProcessID int
Expand Down Expand Up @@ -158,7 +158,7 @@ func getRelevantEnvVars(pid int) ProcessEnvs {
overWriteEnvsResult[envParts[0]] = envParts[1]
}

if _, ok := envDetailsMap[envParts[0]]; ok {
if _, ok := LangsVersionEnvs[envParts[0]]; ok {
detailedEnvsResult[envParts[0]] = envParts[1]
}

Expand Down

0 comments on commit 2f478f0

Please sign in to comment.