Skip to content

chore: test to prod#204

Merged
blue4209211 merged 5 commits into
prodfrom
test
Feb 23, 2026
Merged

chore: test to prod#204
blue4209211 merged 5 commits into
prodfrom
test

Conversation

@mayankpande88

Copy link
Copy Markdown
Contributor

No description provided.

mayankpande88 and others added 5 commits February 16, 2026 09:15
…200)

* fix: resolve external IPs to FQDNs in metric labels using DNS cache

DestinationKey is set at TCP connection time, but DNS may not be cached
yet due to per-CPU perf buffer race conditions. This causes all metric
labels (destination, destination_workload_name) to show raw IPs instead
of FQDNs for external services.

Add enrichDestinationKey() that checks the DNS cache at metric emission
time and substitutes the FQDN when available. Applied to all TCP metrics
(bytes, connections, retransmits) and all L7 protocol metrics (HTTP,
Postgres, Redis, etc).

* fix: aggregate connection stats by enriched key to prevent duplicate metrics

Multiple IPs resolving to the same FQDN (e.g., Google's shared IPs for
monitoring.googleapis.com) caused duplicate metric errors when enriched
to the same label set. Aggregate stats by enriched DestinationKey before
emitting TCP metrics.

* fix: migrate connection DestinationKey when DNS becomes available

Root cause fix for duplicate metric errors. When a TCP connection opens
before DNS is cached (per-CPU perf buffer race), the DestinationKey
stores the raw IP. Later connections get an FQDN-based key. Both enrich
to the same FQDN at emit time, causing "collected before with same label
values" errors.

migrateConnectionKeyIfNeeded updates conn.DestinationKey in-place and
migrates connectionStats from the old IP-based key to the FQDN-based
key. Called from updateConnectionTrafficStats and onL7RequestWithResult.
Collect() aggregation kept as safety net for stale entries.

* fix: use minimal structs and O(1) pod lookup in ip_resolver

Replace full K8s API objects with minimal structs (MinimalOwnerInfo,
MinimalService, MinimalNode) to reduce memory ~10x per resource.
Add PodNameIndex for O(1) ResolvePodOwner instead of O(pods) scan.
Deduplicate service resolution into resolveServiceWorkload().
Simplify getControllerOfOwner from 7 switch cases to unified lookup.

* fix: eliminate duplicate HTTP parsing and remove dead code

Remove 3 unused functions (ParseHTTPResponse, ParseHttpResponse,
ParseHostFromHttpRequest). Fix parseRequest() to call ParseHTTPRequest
once instead of both ParseHttp + ParseHTTPRequest. Pass pre-parsed
method/path to observe() instead of re-parsing payload a third time.
Fix pre-existing RawPath bug in ParseHTTPRequest URL construction.

* fix: race conditions, missing informer, stale IP cleanup, and eBPF bounds checks

- Fix concurrent map access in getMounts/getListens/ping (copy c.processes under lock)
- Fix conn.Closed written outside lock in onConnectionClose
- Add missing CronJob informer handler for owner chain resolution
- Fix InstanceMeta missing Instance field in initial snapshot
- Fix storeWorkloadsIP check-then-act race with mutex
- Clean stale ClusterIPs on Service update and old pod IPs on Pod update
- Add bounds checks in memcached/redis eBPF parsers to prevent OOB reads
- Remove misleading defer req.Body.Close() in ParseHTTPRequest

* fix: correct ssl_st struct offsets for OpenSSL 3.x TLS capture

In OpenSSL 3.x, the SSL struct was split into ssl_st (base) and
ssl_connection_st (connection data). rbio/wbio moved from offset
16/24 to 80/88. The eBPF code was reading garbage pointers for the
BIO, causing FD extraction to fail (CONN_NOT_FOUND with invalid FDs
like 2868022864). HTTP payload was captured correctly since it comes
from function parameters, but the connection couldn't be matched.

Adds GET_FD_V3 macro that reads rbio/wbio at the correct offsets
for OpenSSL 3.x (verified against OpenSSL 3.5.4 with a test program).

* fix: prefer system libssl over psycopg2 bundled lib for TLS uprobes

Processes like the notification server load both psycopg2's bundled
libssl-*.so and the system /usr/lib/libssl.so.3. The agent was picking
the first match from /proc/pid/maps (psycopg2's), but Python's ssl
module uses the system lib for HTTPS. This caused SSL uprobes to fire
on the wrong library, missing Slack/Teams API calls.

* fix: reduce log noise by raising debug log levels

Per-event hot-path logs (L7_EVENT_REGISTRY, CONTAINER_FOUND,
TIMESTAMP_MISMATCH) were at V(2), producing ~15K lines/min with
KLOG_V=2. Raised to V(5). Per-request logs (HTTP2_COMPLETED, LLM_TRACK)
raised to V(4). Occasional logs raised to V(3). TLS per-process debug
logs moved from unconditional Infof to V(2)/V(3).

* fix: align L7 metric labels with TCP and remove dead connection fields

- Rename L7 labels to match TCP: destination_region → destination_workload_region,
  destination_az → destination_workload_az, destination_instance → actual_destination_instance
- Add missing actual_destination_region and actual_destination_az labels to L7 metrics
- Fix L7 destination_workload_region/az to use destinationWorkload (was using actualDestWorkload)
- Remove dead fields from ConnectionKey (srcWorkload, dstWorkload, actualDestWorkload — never set)
- Remove dead fields from ActiveConnection (dstWorkload, actualDestWorkload — set but never read)
- Remove redundant DNS re-enrichment in trace creation (migrateConnectionKeyIfNeeded already handles it)

* style: fix gofmt formatting in container.go and http.go
#203)

* fix: add missing patternsPerLevelLimit param to logparser.NewParser calls

* fix: update logparser dep, sanitize log paths, replace test credential

* fix: update logparser dep to fix sensitive pattern loading

The previous version had a corrupted sensitive_patterns.json that caused
"cannot unmarshal object into Go value of type []SensitivePattern" errors,
breaking sensitive data detection in log parsing.
@blue4209211 blue4209211 merged commit 883beea into prod Feb 23, 2026
1 check passed
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @mayankpande88, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors and enhances the agent's ability to collect and process metrics and traces, particularly focusing on Kubernetes and systemd environments, network connection enrichment, and improved eBPF uprobe attachment. It introduces new data structures for more efficient Kubernetes resource handling, refines systemd service detection, and improves the robustness of L7 tracing by addressing race conditions in DNS resolution and connection tracking. Additionally, it updates the build process, adds new configuration flags, and includes a new utility for ELF symbol parsing.

Highlights

  • Improved Kubernetes Resource Handling: Introduced minimal data structures for Kubernetes objects (e.g., MinimalOwnerInfo, MinimalService, MinimalNode) to reduce memory footprint and optimize snapshotting, along with a PodNameIndex for faster lookups.
  • Enhanced Systemd Service Detection and Filtering: Refactored systemd property retrieval using a new DbusClient with caching, expanded cgroup regex to include 'kube.slice' and 'azure.slice', and added a flag to skip well-known systemd system services.
  • Robust L7 Tracing and Connection Management: Addressed race conditions in DNS resolution for network connections by introducing FQDN enrichment and connection key migration, ensuring consistent metric aggregation and improved connection tracking.
  • Dynamic eBPF Uprobe Attachment: Introduced a new 'ebpftracer/elf.go' utility for parsing ELF files and dynamically attaching uprobes/uretprobes based on symbol lookup, improving compatibility with different library versions (e.g., OpenSSL 3.x, Node.js, Python).
  • Build Process and Configuration Updates: Switched the Dockerfile base image to Debian Bullseye for better glibc compatibility, added new flags for GPU monitoring and log pattern limits, and updated Go module dependencies.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • Dockerfile
    • Updated base image to Debian Bullseye and manually installed Go.
  • cgroup/cgroup.go
    • Expanded systemd cgroup regex to include 'kube' and 'azure' slices.
    • Refined standalone process detection for systemd cgroups.
  • cgroup/cgroup_test.go
    • Added new test cases for 'kube.slice', 'azure.slice', and various systemd scope paths.
  • common/ip_resolver.go
    • Removed 'k8s.io/api/batch/v1beta1' import.
    • Introduced 'MinimalOwnerInfo', 'MinimalService', 'MinimalNode' structs for efficient data storage.
    • Updated 'clusterSnapshot' to use minimal structs and added 'PodNameIndex'.
    • Added 'ipsMapMu' mutex for thread-safe IP map access.
    • Integrated 'cronJobInformer' and 'addCronJobHandlers'.
    • Modified resource handlers to store minimal Kubernetes object information.
    • Refactored service and pod event handlers for improved IP mapping and lookup efficiency.
    • Introduced helper functions 'resolveServiceWorkload', 'labelsMatch', and 'getControllerOwnerRef'.
  • common/log_parser_test.go
    • Updated 'NewParser' instantiation with a new parameter and a generic AWS key example.
  • common/net.go
    • Removed debug logging from 'NewDestinationKey'.
    • Added 'WithResolvedDomain' method to 'DestinationKey' for FQDN enrichment.
  • containers/container.go
    • Added 'path/filepath' import.
    • Replaced 'systemdTriggeredBy' with a 'SystemdProperties' struct in 'ContainerMetadata'.
    • Removed 'LLMStats' struct and related fields/logic.
    • Simplified 'ConnectionKey' and 'ActiveConnection' structs.
    • Modified 'Collect' to use new systemd properties and aggregate connection stats by enriched key.
    • Reduced verbosity of LLM-related klog messages.
    • Introduced 'enrichDestinationKey' and 'migrateConnectionKeyIfNeeded' for FQDN resolution and key migration.
    • Updated 'onL7RequestWithResult' to use connection key migration and pass more L7 details to 'l7Stats.observe'.
    • Improved thread safety for accessing 'c.processes' in 'getMounts', 'getListens', and 'ping'.
    • Modified 'runLogParser' to use new log pattern flag and systemd unit for journald subscriptions.
    • Improved 'resolveFd' logic for log path detection.
  • containers/containerd.go
    • Updated protobuf field accessors from '.Value' to '.GetValue()'.
  • containers/http_processor.go
    • Improved HTTP request parsing to use 'l7.ParseHTTPRequest' for method, path, and headers, with fallback for malformed URIs.
  • containers/journald.go
    • Removed 'cgroup' import.
    • Modified 'JournaldSubscribe' and 'JournaldUnsubscribe' to use systemd unit names.
  • containers/l7.go
    • Added 'mu' (mutex) to 'L7Stats' for thread-safe access.
    • Modified 'observe' method to accept 'method' and 'path' parameters, and to use 'destWorkload' for region/zone labels.
    • Implemented thread-safe initialization and collection for L7 stats.
  • containers/llm_stream.go
    • Reduced logging verbosity for LLM stream events.
  • containers/metrics.go
    • Removed LLM-related Prometheus metrics.
    • Updated 'ContainerInfo' metric to include 'systemd_type' label.
  • containers/process.go
    • Improved Python instrumentation to handle empty command fields gracefully.
    • Modified 'Close' method to close uprobes in a separate goroutine to prevent blocking.
  • containers/registry.go
    • Reduced logging verbosity for TCP connection errors and L7 events.
    • Added handling for deleted cgroups and implemented skipping of well-known systemd system services.
    • Modified 'getContainerMetadata' to use 'getSystemdProperties'.
  • containers/systemd.go
    • Introduced 'DbusClient' for systemd property lookup with caching and retry logic.
    • Defined 'SystemdProperties' struct with 'IsEmpty' and 'IsSystemService' methods.
    • Replaced 'SystemdTriggeredBy' with 'getSystemdProperties' for comprehensive systemd property retrieval.
  • ebpftracer/ebpf/l7/memcached.c
    • Added buffer size check for memcached response parsing to prevent out-of-bounds access.
  • ebpftracer/ebpf/l7/openssl.c
    • Added OpenSSL 3.x specific offsets and logic for file descriptor extraction.
    • Modified SSL_write/read enter probes to use new OpenSSL 3.x FD extraction.
  • ebpftracer/ebpf/l7/redis.c
    • Added buffer size check for redis response parsing to prevent out-of-bounds access.
  • ebpftracer/elf.go
    • Added new file implementing ELF file parsing, symbol lookup, and dynamic uprobe/uretprobe attachment based on instruction analysis.
  • ebpftracer/l7/http.go
    • Modified 'ParseHTTPRequest' to include 'RawPath' and use 'req.Method'/'req.URL.RequestURI()' for parsing.
    • Removed deprecated 'ParseHostFromHttpRequest' and 'ParseHTTPResponse' functions.
  • ebpftracer/nodejs.go
    • Refactored Node.js uprobe attachment to leverage the new ELF symbol parsing utilities for 'uv__io_poll' and callbacks.
  • ebpftracer/python.go
    • Updated 'muslRegexp' for better matching of musl-based libraries.
    • Refactored Python uprobe attachment to use the new ELF symbol parsing utilities for 'pthread_cond_timedwait'.
  • ebpftracer/tls.go
    • Removed unused imports and 'getReturnOffsets' (now in 'elf.go').
    • Refactored TLS uprobe attachment for OpenSSL and Go, utilizing the new ELF symbol parsing for dynamic and robust probe placement.
    • Improved SSL library detection to differentiate and prioritize system vs. bundled libraries.
  • flags/flags.go
    • Added new command-line flags: 'DisableGPUMonitoring', 'SkipSystemdSystemServices', and 'LogPatternsPerContainer'.
  • gpu/gpu.go
    • Integrated new 'DisableGPUMonitoring' flag to conditionally enable/disable GPU monitoring.
    • Added nil check before NVML shutdown in 'Close' method.
  • install.sh
    • Updated environment variable list to include 'DISABLE_GPU_MONITORING'.
  • logs/journald_reader.go
    • Added 'journaldPollTimeout' constant and improved journald reader robustness with better error logging and poll timeout handling.
    • Modified journald subscription to use 'SD_JOURNAL_FIELD_SYSTEMD_UNIT' instead of cgroup ID.
  • node/metadata/gcp.go
    • Refactored GCP metadata fetching to use a custom HTTP client with network namespace execution for improved isolation and reliability.
  • node/net.go
    • Expanded network device filter regex to include bridge and virtual bridge interfaces ('br', 'vmbr').
    • Made network device filter case-insensitive.
  • node/net_test.go
    • Updated network device filter tests to reflect the new regex and case-insensitivity.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant number of improvements and refactorings across the agent. Key changes include a major optimization of the Kubernetes IP resolver to reduce memory usage, fixes for several race conditions, and a solution for a metric duplication issue related to DNS resolution. The TLS uprobe attachment logic has been nicely refactored into a reusable ELF utility, and support for OpenSSL 3.x has been added. I've found one area for improvement in the Dockerfile to reduce the final image size. Overall, these are excellent changes that enhance the agent's performance, stability, and maintainability.

Comment thread containers/l7.go
@@ -114,7 +115,7 @@ func NewL7Stats() L7Stats {
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Changing the receiver for observe and other L7Stats methods from a value receiver (s L7Stats) to a pointer receiver (s *L7Stats) is a critical fix. With a value receiver, each call would operate on a copy of the struct, meaning the internal maps and mutex would not be shared, and state changes would be lost. This change ensures that all operations correctly modify the single shared L7Stats instance.

Comment thread ebpftracer/l7/http.go
Comment on lines 150 to 154
}
if len(body) > 0 || body != nil {
p := body
req.Body = io.NopCloser(bytes.NewReader(p))
defer req.Body.Close()
if len(body) > 0 {
req.Body = io.NopCloser(bytes.NewReader(body))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The removal of defer req.Body.Close() is a good fix. In the previous implementation, the body was closed immediately after being set, which would cause issues for any code attempting to read it later. The new implementation correctly leaves the responsibility of closing the body to the consumer of the http.Request object.

Comment thread common/ip_resolver.go
Comment on lines 924 to 930
func (resolver *K8sIPResolver) ResolvePodOwner(podName string, podNamespace string) Workload {
// This function is now more complex because we don't have the full pod object.
// We need to find the pod in our minimal cache.
var targetPod *MinimalPod
resolver.snapshot.Pods.Range(func(key, value any) bool {
pod, ok := value.(MinimalPod)
if !ok {
return true // continue
}
if pod.Name == podName && pod.Namespace == podNamespace {
targetPod = &pod
return false // stop
if uidVal, ok := resolver.snapshot.PodNameIndex.Load(podNamespace + "/" + podName); ok {
if podVal, ok := resolver.snapshot.Pods.Load(uidVal.(types.UID)); ok {
pod := podVal.(MinimalPod)
return resolver.resolvePodDescriptor(&pod)
}
return true
})

if targetPod != nil {
return resolver.resolvePodDescriptor(targetPod)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using a PodNameIndex map for a direct lookup of pods by namespace/name is an excellent performance optimization. This avoids iterating over the entire list of pods, which could be a significant bottleneck in large clusters.

Comment thread Dockerfile
Comment on lines +5 to +6
RUN apt-get update && apt-get install -y \
curl git build-essential pkg-config libsystemd-dev

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

To reduce the Docker image size, it's a good practice to clean up the apt cache after installing packages. You can do this by adding && rm -rf /var/lib/apt/lists/* to the end of this RUN command.

RUN apt-get update && apt-get install -y \
    curl git build-essential pkg-config libsystemd-dev && \
    rm -rf /var/lib/apt/lists/*

Comment thread containers/process.go
Comment on lines +179 to 187
if len(p.uprobes) > 0 {
uprobes := p.uprobes
p.uprobes = nil
go func() {
for _, u := range uprobes {
_ = u.Close()
}
}()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Detaching the uprobes in a separate goroutine is a great improvement for robustness. This prevents the Close() method from blocking if closing an uprobe takes a long time, and setting p.uprobes to nil immediately helps prevent race conditions if Close() were to be called concurrently.

Comment thread containers/container.go
Comment on lines 855 to +871
c.lock.Lock()
conn := c.connectionsByPidFd[PidFd{Pid: e.Pid, Fd: e.Fd}]
c.lock.Unlock()
if conn != nil {
if conn.Timestamp != 0 && conn.Timestamp != e.Timestamp {
return
}
if conn.Closed.IsZero() {
if e.TrafficStats != nil {
c.lock.Lock()
c.updateConnectionTrafficStats(conn, e.TrafficStats.BytesSent, e.TrafficStats.BytesReceived)
c.lock.Unlock()
}
conn.Closed = time.Now()
if conn == nil {
c.lock.Unlock()
return
}
if conn.Timestamp != 0 && conn.Timestamp != e.Timestamp {
c.lock.Unlock()
return
}
if conn.Closed.IsZero() {
if e.TrafficStats != nil {
c.updateConnectionTrafficStats(conn, e.TrafficStats.BytesSent, e.TrafficStats.BytesReceived)
}
conn.Closed = time.Now()
}
c.lock.Unlock()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Refactoring the onConnectionClose logic to use a single lock at the beginning of the function and early returns is a good improvement. It makes the code cleaner and safer by avoiding nested locks and ensuring the lock is held for the entire duration of the critical section.

Comment thread proc/fd.go
Comment on lines +37 to 39
if !os.IsNotExist(err) {
klog.Warningf("failed to read link '%s': %s", entry.Name(), err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The change from if os.IsNotExist(err) to if !os.IsNotExist(err) is a good bug fix. The previous logic would log a warning if the file did not exist, which is a normal condition for a process that has exited. The new logic correctly logs warnings only for unexpected errors, reducing log noise.

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.

3 participants