Skip to content

Commit

Permalink
feat: Make EKS collector handle tags and zone
Browse files Browse the repository at this point in the history
Signed-off-by: Ferenc Géczi <[email protected]>
  • Loading branch information
Ferenc- committed Feb 12, 2024
1 parent c5666f3 commit caceee6
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 29 deletions.
2 changes: 1 addition & 1 deletion instana/agent/aws_eks_fargate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import time
from instana.options import EKSFargateOptions
from instana.collector.aws_eks_fargate import EKSFargateCollector
from instana.collector.helpers.eks.pod import get_pod_name
from instana.collector.helpers.eks.process import get_pod_name
from instana.log import logger
from instana.util import to_json
from instana.agent.base import BaseAgent
Expand Down
19 changes: 5 additions & 14 deletions instana/collector/aws_eks_fargate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from time import time
from instana.log import logger
from instana.collector.base import BaseCollector
from instana.collector.helpers.eks.process import EKSFargateProcessHelper
from instana.collector.helpers.runtime import RuntimeHelper
from instana.util import DictionaryOfStan


Expand All @@ -20,23 +22,12 @@ def __init__(self, agent):
self.snapshot_data = DictionaryOfStan()
self.snapshot_data_sent = False
self.podname = agent.podname
self.helpers.append(EKSFargateProcessHelper(self))
self.helpers.append(RuntimeHelper(self))

def should_send_snapshot_data(self):
return int(time()) - self.snapshot_data_last_sent > self.snapshot_data_interval

def collect_snapshot(self, event, context):
self.context = context
self.event = event

try:
plugin_data = dict()
plugin_data["name"] = "com.instana.plugin.aws.eks"
plugin_data["entityId"] = self.self.podname
self.snapshot_data["plugins"] = [plugin_data]
except Exception:
logger.debug("collect_snapshot error", exc_info=True)
return self.snapshot_data

def prepare_payload(self):
payload = DictionaryOfStan()
payload["spans"] = []
Expand All @@ -57,6 +48,6 @@ def prepare_payload(self):
if with_snapshot is True:
self.snapshot_data_last_sent = int(time())
except Exception:
logger.debug("collect_snapshot error", exc_info=True)
logger.debug("prepare_payload error", exc_info=True)

return payload
14 changes: 0 additions & 14 deletions instana/collector/helpers/eks/pod.py

This file was deleted.

36 changes: 36 additions & 0 deletions instana/collector/helpers/eks/process.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# (c) Copyright IBM Corp. 2024

""" Module to handle the collection of containerized process metrics for EKS Pods on AWS Fargate """
import os
from instana.collector.helpers.process import ProcessHelper
from instana.log import logger


def get_pod_name():
podname = os.environ.get('HOSTNAME', '')

if not podname:
logger.warning("Failed to determine podname from EKS hostname.")
return podname


class EKSFargateProcessHelper(ProcessHelper):
""" Helper class to extend the generic process helper class with the corresponding fargate attributes """

def collect_metrics(self, **kwargs):
plugin_data = dict()
try:
plugin_data = super(EKSFargateProcessHelper, self).collect_metrics(**kwargs)
plugin_data["data"]["containerType"] = "docker"

if self.collector.agent.options.zone is not None:
plugin_data["data"]["instanaZone"] = self.collector.agent.options.zone

if self.collector.agent.options.tags is not None:
plugin_data["data"]["tags"] = self.collector.agent.options.tags

if kwargs.get("with_snapshot"):
plugin_data["data"]["com.instana.plugin.host.name"] = get_pod_name()
except Exception:
logger.debug("EKSFargateProcessHelper.collect_metrics: ", exc_info=True)
return [plugin_data]
115 changes: 115 additions & 0 deletions tests/platforms/test_eksfargate_collector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# (c) Copyright IBM Corp. 2024

import os
import json
import unittest

from instana.tracer import InstanaTracer
from instana.recorder import StanRecorder
from instana.agent.aws_eks_fargate import EKSFargateAgent
from instana.singletons import get_agent, set_agent, get_tracer, set_tracer


class TestFargateCollector(unittest.TestCase):
def __init__(self, methodName='runTest'):
super(TestFargateCollector, self).__init__(methodName)
self.agent = None
self.span_recorder = None
self.tracer = None
self.pwd = os.path.dirname(os.path.realpath(__file__))

self.original_agent = get_agent()
self.original_tracer = get_tracer()

def setUp(self):
os.environ["INSTANA_TRACER_ENVIRONMENT"] = "AWS_EKS_FARGATE"
os.environ["INSTANA_ENDPOINT_URL"] = "https://localhost/notreal"
os.environ["INSTANA_AGENT_KEY"] = "Fake_Key"

def tearDown(self):
""" Reset all environment variables of consequence """
variable_names = (
"INSTANA_TRACER_ENVIRONMENT",
"AWS_EXECUTION_ENV", "INSTANA_EXTRA_HTTP_HEADERS",
"INSTANA_ENDPOINT_URL", "INSTANA_ENDPOINT_PROXY",
"INSTANA_AGENT_KEY", "INSTANA_ZONE", "INSTANA_TAGS"
)

for variable_name in variable_names:
if variable_name in os.environ:
os.environ.pop(variable_name)

set_agent(self.original_agent)
set_tracer(self.original_tracer)

def create_agent_and_setup_tracer(self):
self.agent = EKSFargateAgent()
self.span_recorder = StanRecorder(self.agent)
self.tracer = InstanaTracer(recorder=self.span_recorder)
set_agent(self.agent)
set_tracer(self.tracer)

def test_prepare_payload_basics(self):
self.create_agent_and_setup_tracer()

payload = self.agent.collector.prepare_payload()
self.assertTrue(payload)

self.assertEqual(2, len(payload.keys()))
self.assertIn('spans',payload)
self.assertIsInstance(payload['spans'], list)
self.assertEqual(0, len(payload['spans']))
self.assertIn('metrics', payload)
self.assertEqual(1, len(payload['metrics'].keys()))
self.assertIn('plugins', payload['metrics'])
self.assertIsInstance(payload['metrics']['plugins'], list)
self.assertEqual(2, len(payload['metrics']['plugins']))


process_plugin = payload['metrics']['plugins'][0]
#self.assertIn('data', process_plugin)

runtime_plugin = payload['metrics']['plugins'][1]
self.assertIn('name', runtime_plugin)
self.assertIn('entityId', runtime_plugin)
self.assertIn('data', runtime_plugin)

def test_no_instana_zone(self):
self.create_agent_and_setup_tracer()
self.assertIsNone(self.agent.options.zone)

def test_instana_zone(self):
os.environ["INSTANA_ZONE"] = "YellowDog"
self.create_agent_and_setup_tracer()

self.assertEqual(self.agent.options.zone, "YellowDog")

payload = self.agent.collector.prepare_payload()
self.assertTrue(payload)

plugins = payload['metrics']['plugins']
self.assertIsInstance(plugins, list)

process_plugin = payload['metrics']['plugins'][0]
self.assertTrue(process_plugin)
self.assertIn("data", process_plugin)
self.assertIn("instanaZone", process_plugin["data"])
self.assertEqual(process_plugin["data"]["instanaZone"], "YellowDog")

def test_custom_tags(self):
os.environ["INSTANA_TAGS"] = "love,war=1,games"
self.create_agent_and_setup_tracer()
self.assertTrue(hasattr(self.agent.options, 'tags'))
self.assertDictEqual(self.agent.options.tags, {"love": None, "war": "1", "games": None})

payload = self.agent.collector.prepare_payload()

self.assertTrue(payload)
task_plugin = None
process_plugin = payload['metrics']['plugins'][0]
self.assertTrue(process_plugin)
self.assertIn("tags", process_plugin["data"])
tags = process_plugin["data"]["tags"]
self.assertEqual(tags["war"], "1")
self.assertIsNone(tags["love"])
self.assertIsNone(tags["games"])

0 comments on commit caceee6

Please sign in to comment.