Skip to content

Allow configuration of analytics pixel URL#3718

Merged
MDrakos merged 8 commits intomasterfrom
miked/PIF-1051
Aug 28, 2025
Merged

Allow configuration of analytics pixel URL#3718
MDrakos merged 8 commits intomasterfrom
miked/PIF-1051

Conversation

@MDrakos
Copy link
Member

@MDrakos MDrakos commented Aug 26, 2025

No description provided.

Comment on lines 21 to 27

// Attempt to get the value for the pixel URL from the environment. Fall back to default if that fails
if pixelUrl = os.Getenv(constants.AnalyticsPixelOverrideEnv); pixelUrl == "" {
// If a host is provided, use it. Otherwise, use the environment variable.
// Fall back to default if that fails.
if url != "" {
pixelUrl = url
} else if pixelUrl = os.Getenv(constants.AnalyticsPixelOverrideEnv); pixelUrl != "" {
pixelUrl = constants.DefaultAnalyticsPixel
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you make this a switch case? It's a bit frustrating to grok as is.

Copy link
Member Author

Choose a reason for hiding this comment

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

No longer needed with the new approach.

Comment on lines +657 to +661
// Stop the service so that the next command will pick up the new config values.
// We need to do this because the analytics reporting instance will have values set that will
// be used until a new instance is created.
cp = ts.SpawnCmd(ts.SvcExe, "stop")
cp.ExpectExitCode(0)
Copy link
Contributor

Choose a reason for hiding this comment

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

The ACs call for the svc to pick up the change, so this should not be part of the test.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I've found a better pattern for this and the service is not picking up these changes. May apply this to the other PR.

@MDrakos MDrakos requested a review from Naatan August 27, 2025 16:59
}

func RegisterConfigListener(cfg *config.Instance) error {
configMediator.AddListener(constants.AnalyticsPixelOverrideConfig, func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Far as I can tell this does not speak with the state-svc. So a listener placed on the svc will not fire if the config was changed on the state tool side.

I like this pattern though, and it seems to me we ought to support this across state tool and the svc. It also means the code as is is completely self sufficient aside from the state-svc AC, but if we address that separately this code will automatically get the benefit.

I've filed this as a followup: https://activestatef.atlassian.net/browse/CP-1083, and we'll drop the AC from the current set of stories regarding the svc picking up the change. I don't think it's critical for the milestone we're targeting.

Good thinking on taking this approach!

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm fairly certain that the service will pick up this change. When we set a config value the runner makes a request to the service which in turn notifies the listeners in the service.

Copy link
Member Author

Choose a reason for hiding this comment

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

The changes to the integration test should prove that the service will pick up the config changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ohh nice! I wasn't grokking that yesterday. Thanks for digging! 🙏

Comment on lines +74 to +78
if err := analytics.RegisterConfigListener(cfg); err != nil {
multilog.Critical("Could not register config listener: %v", errs.JoinMessage(err))
exitCode = 1
return
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Analytics is already using a single instance that is propagated everywhere, so there should be no need for globals. You can do the config listener registration in analytics.New().

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't find a confirmation of this. There is no analytics.New(). We have multiple analytics clients and while the async client is created once and passed around throughout the state tool the sync client has multiple instantiations in the state service.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, it's not analytics.New() it's sync|async.New(). eg. #3718 (comment)

I only see a single invocation of New() in any of our cmd's? Far as I can tell my point still stands.

Copy link
Member Author

Choose a reason for hiding this comment

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

In the state service we have two invocations of sync.New() one for the service itself and another for the resolver because I believe the latter is running in a goroutine. See here and here also it looks like we're only using the pixel reporter in the sync client...

Close()
}

var AnalyticsURL string
Copy link
Contributor

Choose a reason for hiding this comment

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

This should still be recorded on the PixelReporter. Unlike with the API host the use of analytics is not pervasive, it's all a single instance.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've moved this to the pixel reporter but as stated above I can't confirm that there will be a single instance

@MDrakos MDrakos requested a review from Naatan August 28, 2025 17:32
Copy link
Contributor

@Naatan Naatan left a comment

Choose a reason for hiding this comment

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

I'm still maintaining there is no need for globals for this PR:

#3718 (comment)

@MDrakos
Copy link
Member Author

MDrakos commented Aug 28, 2025

I'm still maintaining there is no need for globals for this PR:

#3718 (comment)

Pointed out the multiple sync clients here #3718 (comment)

@MDrakos MDrakos requested a review from Naatan August 28, 2025 18:19
Copy link
Contributor

@Naatan Naatan left a comment

Choose a reason for hiding this comment

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

Thanks for digging up the other reference, though this still doesn't change that we don't need globals here. Both instances are receiving the cfg and are able to record the stored host to their instance. There should be no need for a global.

@MDrakos MDrakos requested a review from Naatan August 28, 2025 21:11
Comment on lines +15 to +18
url string
cfg *config.Instance
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 we can still keep the url here, no? It's static, it only changes when the config listener fires, at which point we can update the value here. The config listener is set at construction time, so we can just loose the config after the listener is placed.

Comment on lines +34 to +50
var (
pixelUrl string

envUrl = os.Getenv(constants.AnalyticsPixelOverrideEnv)
cfgUrl = r.cfg.GetString(constants.AnalyticsPixelOverrideConfig)
)

switch {
case envUrl != "":
pixelUrl = envUrl
case cfgUrl != "":
pixelUrl = cfgUrl
default:
pixelUrl = constants.DefaultAnalyticsPixel
}

pixelURL, err := url.Parse(pixelUrl)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest making this its own function that gets invoked both in the constructor and when the config value changes. You could make that a private method on PixelReporter which then also updates the url.

@MDrakos MDrakos requested a review from Naatan August 28, 2025 22:21
Copy link
Contributor

@Naatan Naatan left a comment

Choose a reason for hiding this comment

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

Beautiful!

@MDrakos MDrakos merged commit 7483c85 into master Aug 28, 2025
3 of 8 checks passed
@MDrakos MDrakos deleted the miked/PIF-1051 branch August 28, 2025 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants