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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: opamp implementation for nodejs agent #1287

Open
wants to merge 45 commits into
base: main
Choose a base branch
from

Conversation

blumamir
Copy link
Collaborator

No description provided.

@edeNFed
Copy link
Contributor

edeNFed commented Jun 23, 2024

nit: maybe we should put the files in /agents/nodejs instead of /agent-nodejs?
We will probably have a similar OpAMP implementation for Java, NodeJS, Python, so having nested directories will be prettier.

"compile": "tsc -p ."
},
"dependencies": {
"@bufbuild/protobuf": "^1.10.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

Update path in dependabot.yaml

@@ -3,10 +3,15 @@ WORKDIR /python-instrumentation
ADD odiglet/agents/python/requirements.txt .
RUN mkdir workspace && pip install --target workspace -r requirements.txt

FROM node:16 AS nodejs-builder
FROM node:18 AS nodejs-builder
ARG ODIGOS_VERSION
Copy link
Contributor

Choose a reason for hiding this comment

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

Not directly connected to this PR, but can we use a similar approach for the go code to inject the version? would that make it easier compared to what we do today?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Currently. I think we should do it for all agents 馃憤


func StartOpAmpServer(ctx context.Context, logger logr.Logger, mgr ctrl.Manager, kubeClient *kubernetes.Clientset, nodeName string) error {

listenEndpoint := "0.0.0.0:4320"
Copy link
Contributor

Choose a reason for hiding this comment

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

Use opamp port const


http.HandleFunc("/v1/opamp", func(w http.ResponseWriter, req *http.Request) {
// Check for the correct method, e.g., GET
if req.Method != "POST" {
Copy link
Contributor

Choose a reason for hiding this comment

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

since go 1.22 this is not required, you can do
http.HandleFunc("POST /v1/opamp"...

return "", false
}

overwrittenName, exists := annotations["odigos.io/reported-name"]
Copy link
Contributor

Choose a reason for hiding this comment

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

consts.OdigosReportedNameAnnotation

}
}

func (k *K8sPodInfoResolver) getServiceNameFromAnnotation(ctx context.Context, name string, kind string, namespace string) (string, bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think these functions should idealy be under k8sutils and not opampserver

Copy link
Contributor

Choose a reason for hiding this comment

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

Are these generated with protoc, if so maybe worth adding in the README how to generate them,
Are we using the proto defined in opAmp, or are we having some custom types?

for {
select {
case <-ctx.Done():
logger.Info("Shutting down live connections timeout monitor")
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any cleanup we need to do here in exit?

// unfortunately, I did not find a way to get just one device id from the kubelet, we need
// to list and iterate over all the devices to get a current snapshot of allocations on this node
// and then look for the ones we are interested in.
func (c *KubeletClient) DeviceIdsToContainerDetails() (map[string]*ContainerDetails, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This also does not look like it relates specifically to opamp server, maybe worth moving to k8sutils

private resourcePromiseResolver?: (resourceAttributes: Attributes) => void;

constructor(config: OpAMPClientHttpConfig) {
this.config = config;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we put a timeout on the HTTP requests?

baseURL: `http://${this.config.opAMPServerHost}`,
headers: {
"Content-Type": " application/x-protobuf",
Authorization: `DeviceId ${config.instrumentationDeviceId}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think calling the header Authorization is a little misleading.
This gives a sense of secure connection but obviously, it is very easy to manipulate. Maybe something like X-Odigos-DeviceId

});
}

private async sendHeartBeatToServer() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need the heartbeat to keep the connection alive or is it part of OpAMP spec? Maybe we can drop it if we are not doing anything on the heartbeat

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants