-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Add task dimensions to ServiceEmitter
#18876
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
Add task dimensions to ServiceEmitter
#18876
Conversation
This patch adds task dimensions to the ServiceEmitter so different monitors don't need to pass the holder to get the dimensions and append it during every monitor call. This also ensures that all task metrics emitted contain the task dimensions by default and are emitted in the same format. The dimensions added include taskId, dataSource, taskType, groupId and id. id is added primarily for backward compatibility as some monitors were previously emitting the id dimension rather than taskId. We can remove it in later release as it's been deprecated already.
kfaraz
left a comment
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 for the changes, @abhishekrb19 ! The task dimensions wiring is much cleaner and easy to follow now!
| * @return a universally useful JVM-wide monitor | ||
| */ | ||
| public static Monitor createCompoundJvmMonitor(Map<String, String[]> dimensions) | ||
| public static Monitor createCompoundJvmMonitor() |
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.
Is this class/method used anywhere? I couldn't find any usage.
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 don’t think they’re used anywhere. Opened a separate PR to remove this unused class altogether: #18877
| /** | ||
| * Provides identifying information for a task. Implementations return {@code null} | ||
| * when used in server processes that are not {@code CliPeon}. | ||
| * when used in server processes that are not {@code CliPeon}. Note that t |
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.
Incomplete javadoc?
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.
Whoops, removed.
| String getTaskId(); | ||
|
|
||
| /** | ||
| * @return the taskId, or {@code null} if called from a server that is not {@code CliPeon}. |
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.
| * @return the taskId, or {@code null} if called from a server that is not {@code CliPeon}. | |
| * @return the type name of this task, or {@code null} if called from a server that is not {@code CliPeon}. |
| String getTaskType(); | ||
|
|
||
| /** | ||
| * @return the taskId, or {@code null} if called from a server that is not {@code CliPeon}. |
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.
| * @return the taskId, or {@code null} if called from a server that is not {@code CliPeon}. | |
| * @return the group ID of this task, or {@code null} if called from a server that is not {@code CliPeon}. |
| } | ||
|
|
||
| /** | ||
| * Initialize a stub service emitter and auto-{@link #start()} it for test convenience. |
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.
Instead of doing the auto-start in the constructor, add a static utility method that may be used something like
ServiceEmitter emitter = StubServiceEmitter.createStarted();
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.
Good idea, done
| public Map<String, String> getMetricDimensions() | ||
| { | ||
| return Map.of( | ||
| DruidMetrics.DATASOURCE, getDataSource(), |
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: Each getter invokes the taskProvider separately. Maybe just invoke it once and assign the result to a Task task variable.
| /** | ||
| * Initialize a stub service emitter. Tests must explicitly call {@link #start()}. | ||
| */ | ||
| public StubServiceEmitter(String service, String host, TaskHolder taskHolder) |
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.
We should update the LatchableEmitter constructor to accept a TaskHolder too.
Otherwise, the task dimensions will not show up in embedded tests.
You could also add a short test method in any of the existing tests to verify the new dimensions.
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.
You could also add a short test method in any of the existing tests to verify the new dimensions.
Oh, I suppose this would require MMs. You could add a metric verification in the KubernetesTaskRunnerDockerTest since that test runs peons and also uses an event collector + latchable emitter combo to wait on metrics.
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.
We should update the LatchableEmitter constructor to accept a TaskHolder too.
Otherwise, the task dimensions will not show up in embedded tests.
Sounds good, updated.
Oh, I suppose this would require MMs. You could add a metric verification in the KubernetesTaskRunnerDockerTest since that test runs peons and also uses an event collector + latchable emitter combo to wait on metrics.
I’m trying to figure out how to run the Docker tests locally to verify this...I’m looking at the GHA Docker tests to see what I’m missing in my setup. It would probably be a good idea to add a brief README or update the javadocs, to document how devs can run these tests locally, since it requires some additional setup like installing dependencies like k3s, etc.
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.
Yeah, that's fair, let me create a PR to add the steps for running these tests.
Meanwhile, we can merge this PR and you can add the tests in a follow up.
since it requires some additional setup like installing dependencies like k3s, etc.
I might need to check but AFAIR, the tests just need docker to be running. There are some steps required though, like setting the Druid image name etc.
| public void close() | ||
| { | ||
| try { | ||
| emitter.close(); |
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.
Isn't the emitter always a NoopEmitter, why do we need to invoke start and close on it?
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.
Ah, I intended to delegate this to the base class via super.close() here, similar to how start() invokes super.start() to delegate to the base class, which takes care of additional initialization. We could skip this in close() as it doesn't do much, but it feels cleaner to do the same way here as well for completeness.
| { | ||
| private final ImmutableMap<String, String> serviceDimensions; | ||
| private final Emitter emitter; | ||
| protected final Emitter emitter; |
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.
Why not private?
| import org.apache.druid.guice.ManageLifecycle; | ||
| import org.apache.druid.java.util.emitter.core.Emitter; | ||
|
|
||
| public class StubServiceEmitterModule implements Module |
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.
Instead of adding this, I wonder if we shouldn't just move LatchableEmitterModule to processing/src/test/.
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.
Yeah, I considered doing this. However, all the unit tests use StubServiceEmitter directly and moving LatchableEmitterModule to processing would also require moving non-test classes like DruidNode and other dependencies from the server module into processing. Given that, I’ve left this test stub module in place for now and we can refactor these test dependencies later if needed.
I’ve also wired TaskHolder into LatchableEmitterModule so the embedded tests can make use of it as needed.
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.
Given that, I’ve left this test stub module in place for now and we can refactor these test dependencies later if needed.
Makes sense, thanks!
@abhishekrb19 , did you mean monitors like |
|
@kfaraz thanks for taking a look!
That's right, all the |
kfaraz
left a comment
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 👍🏻
This patch adds task dimensions to the
ServiceEmitterso individual monitors no longer need to pass the task holder to retrieve task dimensions and append them on every monitor call. Some of the monitors were even missing these task dimensions.The added dimensions include
taskId,dataSource,taskTypeandgroupId. This change ensures that all task metrics are emitted with these task dimensions by default and in a consistent format.Changes:
TaskHolderinto theServiceEmittervia theEmitterModule.TaskHolder.getMetricDimensions()and override it as appropriate.start()by callingTaskHolder.getMetricDimensions(). This is done during thestart()explicitly to ensure all the dependencies are ready.TaskHolderandNoopTaskHolderclasses from theservermodule to theprocessingmodule for better reuse.dimensionmap from the individual monitor implementation since this is taken care of already.TestLoadSpecHolder; this isn’t really in scope for this change, so I’m happy to move it out to simplify review if needed.Release note
All task metrics are emitted with the following dimensions:
taskId,dataSource,taskType,groupId, andid(for backward compatibility;idwill be removed in favor of thetaskIddimension in a future release).This PR has: