Repository: openshift/linuxptp-daemon
Pull request #435: [release-4.16] OCPBUGS-55281: update event to fix T-GM regression failure
Author: login: aneeshkp
Labels: name: approved
description: Indicates a PR has been approved by an approver from all required OWNERS files.
name: lgtm
description: Indicates that a PR is ready to be merged.
name: cherry-pick-approved
description: Indicates a cherry-pick PR into a release branch has been approved by the release branch manager.
name: backport-risk-assessed
description: Indicates a PR to a release branch has been evaluated and considered safe to accept.
name: jira/valid-bug
description: Indicates that a referenced Jira bug is valid for the branch this PR is targeting.
name: jira/severity-important
description: Referenced Jira bug's severity is important for the branch this PR is targeting.
name: jira/valid-reference
description: Indicates that this PR references a valid Jira ticket of any type.
Created: 2025-04-30T18:21:02Z | Merged: 2025-05-02T01:02:21Z


This PR restores a critical logic block that was incorrectly removed in a previous commit. The removed code was responsible for:

    missing  logDataValues from dataDetails.logData for log output
    if event.WriteToLog && logDataValues != "" {
	logOut = append(logOut, logDataValues)
}


Diff:
diff --git a/pkg/event/event.go b/pkg/event/event.go
index 1614ad9ce..227c9600c 100644
--- a/pkg/event/event.go
+++ b/pkg/event/event.go
@@ -635,9 +635,6 @@ connect:
 			// Update the in MemData
 			dataDetails := e.addEvent(event)
 
-			if event.WriteToLog && logDataValues != "" {
-				logOut = append(logOut, logDataValues)
-			}
 			// Computes GM state
 			gmState := e.updateGMState(event.CfgName)
 			// right now if GPS offset || mode is bad then consider source lost
@@ -646,9 +643,8 @@ connect:
 			}
 
 			logDataValues = dataDetails.logData
-
-			if gmState.gmLog != "" && gmState.gmIFace != GM_INTERFACE_UNKNOWN {
-				logOut = append(logOut, gmState.gmLog)
+			if event.WriteToLog && logDataValues != "" {
+				logOut = append(logOut, logDataValues)
 			}
 
 			// only if config has this special name
@@ -665,6 +661,11 @@ connect:
 				debug.UpdateTs2phcState(string(d.State), 0, debug.OverallTs2phcKey)
 			}
 			debug.UpdateGMState(string(gmState.state))
+
+			if gmState.gmLog != "" && gmState.gmIFace != GM_INTERFACE_UNKNOWN {
+				logOut = append(logOut, gmState.gmLog)
+			}
+
 			// Update the metrics
 			if !e.stdoutToSocket { // if events not enabled
 				eventIface := event.IFace
diff --git a/pkg/event/event_test.go b/pkg/event/event_test.go
index c355e97cc..44067b914 100644
--- a/pkg/event/event_test.go
+++ b/pkg/event/event_test.go
@@ -73,10 +73,10 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			outOfSpec:        false,
 			iface:            "ens1f0",
 			values:           map[event.ValueType]interface{}{event.OFFSET: 0, event.PHASE_STATUS: 3, event.FREQUENCY_STATUS: 3, event.PPS_STATUS: 1},
-			wantGMState:      "GM[0]:[ts2phc.0.config] unknown T-GM-STATUS s0",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 248",
+			wantGMState:      "",
+			wantClockState:   "",
 			wantProcessState: "dpll[0]:[ts2phc.0.config] ens1f0 frequency_status 3 offset 0 phase_status 3 pps_status 1 s2",
-			desc:             "Initial state, gnss is not set, so expect GM to be FREERUN",
+			desc:             "Initial state, gnss is not set, gm won't have intrerface so no  t-gm or clock class ",
 		},
 		{
 			processName:      event.GNSS,
@@ -130,7 +130,7 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			outOfSpec:        false,
 			values:           map[event.ValueType]interface{}{event.OFFSET: 0, event.GPS_STATUS: 0},
 			wantGMState:      "GM[0]:[ts2phc.0.config] ens1f0 T-GM-STATUS s2",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 6",
+			wantClockState:   "", // clock class didn;t change
 			wantProcessState: "gnss[0]:[ts2phc.0.config] ens1f0 gnss_status 0 offset 0 s0",
 			sourceLost:       true,
 			desc:             "GPS is free run ,source is lost when everything else is locked(Do nothing and wait  for DPLL to switch to HOLDOVER)",
@@ -166,8 +166,8 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			iface:            "ens1f0",
 			outOfSpec:        false,
 			values:           map[event.ValueType]interface{}{event.OFFSET: 0, event.GPS_STATUS: 3},
-			wantGMState:      "GM[0]:[ts2phc.0.config] ens1f0 T-GM-STATUS s0",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 140",
+			wantGMState:      "", // TM state did not change
+			wantClockState:   "", // CLOCKCLASS did not change
 			wantProcessState: "gnss[0]:[ts2phc.0.config] ens1f0 gnss_status 3 offset 0 s2",
 			sourceLost:       false,
 			desc:             "GPS is locked but dpll is in FREERUN and out of spec, yet to switch over in that case GM should stay with last state",
@@ -240,7 +240,7 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			iface:            "ens1f0",
 			values:           map[event.ValueType]interface{}{event.OFFSET: 0, event.GPS_STATUS: 0},
 			wantGMState:      "GM[0]:[ts2phc.0.config] ens1f0 T-GM-STATUS s2",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 6",
+			wantClockState:   "", // clock class didn not change
 			wantProcessState: "gnss[0]:[ts2phc.0.config] ens1f0 gnss_status 0 offset 0 s0",
 			sourceLost:       true,
 			desc:             "Case 2: GPS is free run ,source is lost when everything else is locked(Do nothing and wait  for DPLL to switch to HOLDOVER)",
@@ -265,7 +265,7 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			iface:            "ens2f0",
 			values:           map[event.ValueType]interface{}{event.OFFSET: 0, event.PHASE_STATUS: 4, event.FREQUENCY_STATUS: 4, event.PPS_STATUS: 0},
 			wantGMState:      "GM[0]:[ts2phc.0.config] ens1f0 T-GM-STATUS s1",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 7",
+			wantClockState:   "", // clock class did not change
 			wantProcessState: "dpll[0]:[ts2phc.0.config] ens2f0 frequency_status 4 offset 0 phase_status 4 pps_status 0 s1",
 			desc:             "dpll 2 is on Holdover, where source is lost, moving to holdover state",
 		},
@@ -277,7 +277,7 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			iface:            "ens2f0",
 			values:           map[event.ValueType]interface{}{event.OFFSET: 5000, event.PPS_STATUS: 0},
 			wantGMState:      "GM[0]:[ts2phc.0.config] ens1f0 T-GM-STATUS s1",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 7",
+			wantClockState:   "", // clock class did not change ,
 			wantProcessState: "ts2phc[0]:[ts2phc.0.config] ens2f0 offset 5000 pps_status 0 s0",
 			desc:             "2nd card ts2phc offset spiked when in holdover",
 		},
@@ -293,6 +293,12 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 	defer close(leap.LeapMgr.Close)
 	time.Sleep(1 * time.Second)
 	for _, test := range tests {
+		test := test
+		expectedLogs := map[string]bool{
+			test.wantProcessState: false,
+			test.wantGMState:      false,
+			test.wantClockState:   false,
+		}
 		select {
 		case eChannel <- sendEvents(test.cfgName, test.iface, test.processName, test.clockState, test.values, test.outOfSpec, test.sourceLost):
 			log.Println("sent data to channel")
@@ -307,23 +313,28 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			case c := <-logOut:
 				s1 := strings.Index(c, "[")
 				s2 := strings.Index(c, "]")
-				rs := strings.Replace(c, c[s1+1:s2], "0", -1)
 
-				if strings.HasPrefix(c, string(test.processName)) {
-					assert.Equal(t, test.wantProcessState, rs, test.desc)
-				}
-				if strings.HasPrefix(c, "GM[") {
-					assert.Equal(t, test.wantGMState, rs, test.desc)
+				if s1 != -1 && s2 > s1 {
+					c = c[:s1+1] + "0" + c[s2:]
 				}
-				if strings.HasPrefix(c, "ptp4l[") {
-					assert.Equal(t, test.wantClockState, rs, test.desc)
+				// Mark expected log as seen
+				for want := range expectedLogs {
+					if want == "" || c == want {
+						expectedLogs[want] = true
+					}
 				}
 			default:
+				time.Sleep(100 * time.Millisecond)
 			}
-			if len(logOut) > 0 {
-				goto retry
-			}
-			time.Sleep(100 * time.Millisecond)
+		}
+		time.Sleep(100 * time.Millisecond)
+		if len(logOut) > 0 {
+			goto retry
+		}
+		time.Sleep(100 * time.Millisecond)
+		// Final check: ensure all expected logs were received
+		for logStr, seen := range expectedLogs {
+			assert.True(t, seen, "Missing expected log for test '%s': %s", test.desc, logStr)
 		}
 	}
 


Reviews:
user: login: lack
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-01T22:30:51Z
user: login: lack
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-01T22:32:45Z
user: login: nocturnalastro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T12:14:21Z

Review comments:
diff_hunk: @@ -307,23 +313,28 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			case c := <-logOut:
 				s1 := strings.Index(c, "[")
 				s2 := strings.Index(c, "]")
-				rs := strings.Replace(c, c[s1+1:s2], "0", -1)
 
-				if strings.HasPrefix(c, string(test.processName)) {
-					assert.Equal(t, test.wantProcessState, rs, test.desc)
-				}
-				if strings.HasPrefix(c, "GM[") {
-					assert.Equal(t, test.wantGMState, rs, test.desc)
+				if s1 != -1 && s2 > s1 {
+					c = c[:s1+1] + "0" + c[s2:]
 				}
-				if strings.HasPrefix(c, "ptp4l[") {
-					assert.Equal(t, test.wantClockState, rs, test.desc)
+				// Mark expected log as seen
+				for want := range expectedLogs {
+					if want == "" || c == want {
+						expectedLogs[want] = true
+					}
 				}
 			default:
+				time.Sleep(100 * time.Millisecond)
path: pkg/event/event_test.go
user: login: lack
body: I don't want to derail the PR, but I'd love to learn more about why we're sleeping here.

Every time I see a sleep I see a red flag; trauma from past jobs I've held.
created_at: 2025-05-01T22:30:51Z
author_association: MEMBER
diff_hunk: @@ -73,10 +73,10 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			outOfSpec:        false,
 			iface:            "ens1f0",
 			values:           map[event.ValueType]interface{}{event.OFFSET: 0, event.PHASE_STATUS: 3, event.FREQUENCY_STATUS: 3, event.PPS_STATUS: 1},
-			wantGMState:      "GM[0]:[ts2phc.0.config] unknown T-GM-STATUS s0",
-			wantClockState:   "ptp4l[0]:[ts2phc.0.config] CLOCK_CLASS_CHANGE 248",
+			wantGMState:      "",
+			wantClockState:   "",
 			wantProcessState: "dpll[0]:[ts2phc.0.config] ens1f0 frequency_status 3 offset 0 phase_status 3 pps_status 1 s2",
-			desc:             "Initial state, gnss is not set, so expect GM to be FREERUN",
+			desc:             "Initial state, gnss is not set, gm won't have intrerface so no  t-gm or clock class ",
path: pkg/event/event_test.go
user: login: lack
body: nit:
```suggestion
			desc:             "Initial state, gnss is not set, gm won't have interface so no t-gm or clock class ",
```
created_at: 2025-05-01T22:32:45Z
author_association: MEMBER
diff_hunk: @@ -307,23 +313,28 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
 			case c := <-logOut:
 				s1 := strings.Index(c, "[")
 				s2 := strings.Index(c, "]")
-				rs := strings.Replace(c, c[s1+1:s2], "0", -1)
 
-				if strings.HasPrefix(c, string(test.processName)) {
-					assert.Equal(t, test.wantProcessState, rs, test.desc)
-				}
-				if strings.HasPrefix(c, "GM[") {
-					assert.Equal(t, test.wantGMState, rs, test.desc)
+				if s1 != -1 && s2 > s1 {
+					c = c[:s1+1] + "0" + c[s2:]
 				}
-				if strings.HasPrefix(c, "ptp4l[") {
-					assert.Equal(t, test.wantClockState, rs, test.desc)
+				// Mark expected log as seen
+				for want := range expectedLogs {
+					if want == "" || c == want {
+						expectedLogs[want] = true
+					}
 				}
 			default:
+				time.Sleep(100 * time.Millisecond)
path: pkg/event/event_test.go
user: login: nocturnalastro
body: Sleeping allows a context switch for other go-routines to run which is especially important for the tests at they may run in environments for where the thread/process count is low :) 
created_at: 2025-05-02T12:14:21Z
author_association: CONTRIBUTOR

PR comments:
user: login: openshift-ci-robot
created_at: 2025-04-30T18:21:38Z
body: @aneeshkp: This pull request references [Jira Issue OCPBUGS-55281](https://issues.redhat.com//browse/OCPBUGS-55281), which is invalid:
 - expected the bug to target the "4.16.z" version, but no target version was set
 - release note text must be set and not match the template OR release note type must be set to "Release Note Not Required".  For more information you can reference the [OpenShift Bug Process](https://source.redhat.com/groups/public/openshift/openshift_wiki/openshift_bugzilla_process#doc-text-for-bugs).
 - expected [Jira Issue OCPBUGS-55281](https://issues.redhat.com//browse/OCPBUGS-55281) to depend on a bug targeting a version in 4.17.0, 4.17.z and in one of the following states: VERIFIED, RELEASE PENDING, CLOSED (ERRATA), CLOSED (CURRENT RELEASE), CLOSED (DONE), CLOSED (DONE-ERRATA), but no dependents were found

Comment <code>/jira refresh</code> to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

<details>

In response to [this](https://github.com/openshift/linuxptp-daemon/pull/435):

>
>This PR restores a critical logic block that was incorrectly removed in a previous commit. The removed code was responsible for:
>
>    missing  logDataValues from dataDetails.logData for log output
>    if event.WriteToLog && logDataValues != "" {
>	logOut = append(logOut, logDataValues)
>}


Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=openshift%2Flinuxptp-daemon).  If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository.
</details>
author_association: CONTRIBUTOR
user: login: Bonnie-Block
created_at: 2025-04-30T20:47:06Z
body: /label cherry-pick-approved
author_association: NONE
user: login: aneeshkp
created_at: 2025-04-30T20:55:19Z
body: /jira  refresh 
author_association: CONTRIBUTOR
user: login: aneeshkp
created_at: 2025-04-30T20:56:26Z
body: /jira refresh
author_association: CONTRIBUTOR
user: login: openshift-ci-robot
created_at: 2025-04-30T20:56:31Z
body: @aneeshkp: This pull request references [Jira Issue OCPBUGS-55281](https://issues.redhat.com//browse/OCPBUGS-55281), which is invalid:
 - expected dependent [Jira Issue OCPBUGS-55612](https://issues.redhat.com//browse/OCPBUGS-55612) to target a version in 4.17.0, 4.17.z, but it targets "4.19.0" instead

Comment <code>/jira refresh</code> to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

<details>

In response to [this](https://github.com/openshift/linuxptp-daemon/pull/435#issuecomment-2843261425):

>/jira refresh


Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=openshift%2Flinuxptp-daemon).  If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository.
</details>
author_association: CONTRIBUTOR
user: login: aneeshkp
created_at: 2025-04-30T20:58:26Z
body: /jira refresh 
author_association: CONTRIBUTOR
user: login: openshift-ci-robot
created_at: 2025-04-30T20:58:34Z
body: @aneeshkp: This pull request references [Jira Issue OCPBUGS-55281](https://issues.redhat.com//browse/OCPBUGS-55281), which is valid. The bug has been moved to the POST state.

<details><summary>7 validation(s) were run on this bug</summary>

* bug is open, matching expected state (open)
* bug target version (4.16.z) matches configured target version for branch (4.16.z)
* bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)
* release note type set to "Release Note Not Required"
* dependent bug [Jira Issue OCPBUGS-55610](https://issues.redhat.com//browse/OCPBUGS-55610) is in the state Closed (Done), which is one of the valid states (VERIFIED, RELEASE PENDING, CLOSED (ERRATA), CLOSED (CURRENT RELEASE), CLOSED (DONE), CLOSED (DONE-ERRATA))
* dependent [Jira Issue OCPBUGS-55610](https://issues.redhat.com//browse/OCPBUGS-55610) targets the "4.17.z" version, which is one of the valid target versions: 4.17.0, 4.17.z
* bug has dependents</details>

No GitHub users were found matching the public email listed for the QA contact in Jira (hhassid@redhat.com), skipping review request.

<details>

In response to [this](https://github.com/openshift/linuxptp-daemon/pull/435#issuecomment-2843265482):

>/jira refresh 


Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=openshift%2Flinuxptp-daemon).  If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository.
</details>
author_association: CONTRIBUTOR
user: login: openshift-ci[bot]
created_at: 2025-05-01T20:19:04Z
body: @aneeshkp: all tests **passed!**


[Full PR test history](https://prow.ci.openshift.org/pr-history?org=openshift&repo=linuxptp-daemon&pr=435). [Your PR dashboard](https://prow.ci.openshift.org/pr?query=is:pr+state:open+author:aneeshkp).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
author_association: CONTRIBUTOR
user: login: lack
created_at: 2025-05-01T22:36:06Z
body: As someone new to the codebase, it would be useful to have a bit more in the commit log message - How does it address the T-GM regression failure?
author_association: MEMBER
user: login: lack
created_at: 2025-05-01T22:36:18Z
body: /lgtm
author_association: MEMBER
user: login: openshift-ci[bot]
created_at: 2025-05-01T22:36:38Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/openshift/linuxptp-daemon/pull/435#" title="Author self-approved">aneeshkp</a>*, *<a href="https://github.com/openshift/linuxptp-daemon/pull/435#issuecomment-2845924056" title="LGTM">lack</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=openshift%2Flinuxptp-daemon).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/openshift/linuxptp-daemon/blob/release-4.16/OWNERS)~~ [aneeshkp]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR
user: login: lack
created_at: 2025-05-02T00:46:13Z
body: /label backport-risk-assessed
author_association: MEMBER
user: login: openshift-ci[bot]
created_at: 2025-05-02T00:46:16Z
body: @lack: Can not set label backport-risk-assessed: Must be member in one of these teams: []

<details>

In response to [this](https://github.com/openshift/linuxptp-daemon/pull/435#issuecomment-2846073688):

>/label backport-risk-assessed


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
author_association: CONTRIBUTOR
user: login: jzding
created_at: 2025-05-02T00:59:22Z
body: /label backport-risk-assessed
author_association: CONTRIBUTOR
user: login: openshift-ci-robot
created_at: 2025-05-02T01:02:25Z
body: @aneeshkp: [Jira Issue OCPBUGS-55281](https://issues.redhat.com//browse/OCPBUGS-55281): All pull requests linked via external trackers have merged:
 * [openshift/linuxptp-daemon#435](https://github.com/openshift/linuxptp-daemon/pull/435)

[Jira Issue OCPBUGS-55281](https://issues.redhat.com//browse/OCPBUGS-55281) has been moved to the MODIFIED state.

<details>

In response to [this](https://github.com/openshift/linuxptp-daemon/pull/435):

>
>This PR restores a critical logic block that was incorrectly removed in a previous commit. The removed code was responsible for:
>
>    missing  logDataValues from dataDetails.logData for log output
>    if event.WriteToLog && logDataValues != "" {
>	logOut = append(logOut, logDataValues)
>}


Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=openshift%2Flinuxptp-daemon).  If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository.
</details>
author_association: CONTRIBUTOR
user: login: openshift-bot
created_at: 2025-05-02T02:23:15Z
body: **[ART PR BUILD NOTIFIER]**

Distgit: linuxptp-daemon
This PR has been included in build [ose-linuxptp-daemon-container-v4.16.0-202505020146.p0.g5015b5d.assembly.stream.el9](https://brewweb.engineering.redhat.com/brew/buildinfo?buildID=3630163).
All builds following this will include this PR.
author_association: CONTRIBUTOR