-
Notifications
You must be signed in to change notification settings - Fork 321
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Refactor][1/n] Replace logrus with logr to keep logging consistent #1835
Conversation
@@ -87,7 +86,7 @@ func BuildIngressForHeadService(cluster rayv1.RayCluster) (*networkingv1.Ingress | |||
// Get ingress class name from rayCluster annotations. this is a required field to use ingress. | |||
ingressClassName, ok := cluster.Annotations[IngressClassAnnotationKey] | |||
if !ok { | |||
logrus.Warn(fmt.Sprintf("ingress class annotation is not set for cluster %s/%s", cluster.Namespace, cluster.Name)) | |||
log.Info(fmt.Sprintf("ingress class annotation is not set for cluster %s/%s", cluster.Namespace, cluster.Name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This log
variable is initialized at
var log = logf.Log.WithName("controllers").WithName("RayCluster") |
@@ -34,7 +34,7 @@ const ( | |||
EnableInitContainerInjectionEnvKey = "ENABLE_INIT_CONTAINER_INJECTION" | |||
) | |||
|
|||
var log = logf.Log.WithName("RayCluster-Controller") | |||
var log = logf.Log.WithName("controllers").WithName("RayCluster") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make it consistent with
log := ctrl.Log.WithName("controllers").WithName("RayCluster") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I like this refactor PR. cc @astefanutti would you mind reviewing this PR? Thanks!
@@ -32,6 +31,8 @@ const ( | |||
DefaultDomainName = "cluster.local" | |||
) | |||
|
|||
var log = logf.Log.WithName("controllers").WithName("RayCluster") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be possible for RayJob/RayService controllers to call utility functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be better to use log := ctrl.LoggerFrom(ctx)
mentioned by @astefanutti.
@@ -87,7 +86,7 @@ func BuildIngressForHeadService(cluster rayv1.RayCluster) (*networkingv1.Ingress | |||
// Get ingress class name from rayCluster annotations. this is a required field to use ingress. | |||
ingressClassName, ok := cluster.Annotations[IngressClassAnnotationKey] | |||
if !ok { | |||
logrus.Warn(fmt.Sprintf("ingress class annotation is not set for cluster %s/%s", cluster.Namespace, cluster.Name)) | |||
log.Info(fmt.Sprintf("ingress class annotation is not set for cluster %s/%s", cluster.Namespace, cluster.Name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be preferable to avoid string formatting and use the structured form, e.g.:
log.Info("ingress class annotation is not set for cluster", cluster.Namespace, cluster.Name)
Maybe you're already planning to do it in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I am planning to add the namespace to the structured form, but I am not sure whether should we move all the logging parameters to the structured form. IMHO, the structured fields are subject to special purposes only such as filtering. Moving all parameters out from the message may reduce readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, having both the formatted message and the structured info sounds reasonable too.
@@ -32,6 +31,8 @@ const ( | |||
DefaultDomainName = "cluster.local" | |||
) | |||
|
|||
var log = logf.Log.WithName("controllers").WithName("RayCluster") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the case where utility functions are called by multiple controllers, it may be preferable to use the logger propagated in the context instead, e.g.:
log := ctrl.LoggerFrom(ctx)
@@ -87,7 +86,7 @@ func BuildIngressForHeadService(cluster rayv1.RayCluster) (*networkingv1.Ingress | |||
// Get ingress class name from rayCluster annotations. this is a required field to use ingress. | |||
ingressClassName, ok := cluster.Annotations[IngressClassAnnotationKey] | |||
if !ok { | |||
logrus.Warn(fmt.Sprintf("ingress class annotation is not set for cluster %s/%s", cluster.Namespace, cluster.Name)) | |||
log.Info(fmt.Sprintf("ingress class annotation is not set for cluster %s/%s", cluster.Namespace, cluster.Name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, there is the logger provided by controller-runtime that can be retrieved from the context, e.g.:
log := ctrl.LoggerFrom(ctx)
This contains the reconciliation request id, and can be customised with common key / value pairs (e.g. namespace and name) with the LogConstructor
option of the controller builder.
But a global variable can be a good approximation at the moment.
ea122a1
to
4bbbc3a
Compare
I have changed to use |
Would you mind rebasing with the master branch? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
@@ -164,6 +164,7 @@ type RayClusterReconcilerOptions struct { | |||
// Reconcile used to bridge the desired state with the current state | |||
func (r *RayClusterReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) { | |||
var err error | |||
ctx = ctrl.LoggerInto(ctx, r.Log) // TODO: add reqeust namespace here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "reqeust" -> "request"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have several questions:
- All RayCluster, RayJob, and RayService reconcilers seem to be running in a single process.
- (Not sure) Because the default value of
config.ReconcileConcurrency
is 1, it seems to be only 1 thread for all reconcilers. - What would happen if
config.ReconcileConcurrency
were set to more than 1? If the RayCluster and RayService reconcilers were to run concurrently and both callctx = ctrl.LoggerInto(ctx, r.Log)
, could that lead to a race condition when callingctrl.LoggerFrom(ctx)
?
the
|
Thank you @astefanutti for your detailed explanation! Hi @kevin85421, The Here is a quick concurrent test to simulate the situation: func test(ctx context.Context) {
ctx = ctrl.LoggerInto(ctx, ctrl.Log)
_ = ctrl.LoggerFrom(ctx)
}
func BenchmarkRaceLoggerInto(b *testing.B) {
ctx := context.Background()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
test(ctx)
}
})
} Then run it with the race detector enabled ▶ go test ./... -count=1 -race -bench BenchmarkRaceLoggerInto
goos: darwin
goarch: arm64
BenchmarkRaceLoggerInto-10 1000000 1055 ns/op
PASS
ok 2.901s As you can see there is no race reported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank @rueian @astefanutti for the explanation! It is pretty helpful!
Why are these changes needed?
We currently write logs through two different interfaces, the
logr
and thelogrus
.Following the discussion #1793 (comment), we would like to revisit and unify our logging format for further usages, which requires a unified structure format, such as filtering logs by a k8s namespace.
This PR replaces the usages of
logrus
with thelogr
, which is recommended by the kubebuilder, to unify our logging format. I will add namespace logging in the next PR.Related issue number
Checks