Skip to content
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

Expose hint levels #200

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Expose hint levels #200

wants to merge 3 commits into from

Conversation

pcmanus
Copy link

@pcmanus pcmanus commented Oct 10, 2022

Composition hints in federation 2 are generated with a "level" (which can currently be one of of "DEBUG", "INFO" or "WARN"). This commit modify harmonizer to include those levels in the output and the type definitions to decode them, and include them in the supergraph output for future use by rover.

Fixes #102

Composition hints in federation 2 are generated with a "level" (which
can currently be one of of "DEBUG", "INFO" or "WARN"). This commit
modify harmonizer to include those levels in the output and the type
definitions to decode them, and include them in the `supergraph` output
for future use by `rover`.

Fixes apollographql#102
}
let maybe_captures = RE.captures(&self.message);
if let Some(captures) = maybe_captures {
(captures.get(1).unwrap().as_str().to_string(), captures.get(2).unwrap().as_str().to_string())
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a more structured way that we can get this data from the underlying JS library? I don't love the need to use a regex here for this - if we could instead put that info in a JSON object or something instead of parsing out the string I think this will be more robust

Copy link
Author

Choose a reason for hiding this comment

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

I'm not a huge fan either, but I was worried about either making it weird to use, or have backward compatibility problems.

Let me however remark that this method is not about the hint "level". A hint has fundamentally 3 components at the moment:

  1. the message, which describe the particular hint.
  2. the code, which categorize hints (same as we have for errors).
  3. the level, which is WARN, INFO or DEBUG for now.

The level, that is introduced by this patch, is shipped as a separate field in the underlying JSON object, and thus deserialized separately, so no worry on this one.

But what this method is trying to do is give access to the message and code separately. Because the issue is that unfortunately, instead of having the message and code as separate fields in the underlying JSON, do_compose.js has been using the Hint.toString() method to generate a single pre-formatted string of the form "[<code>] <message>" and calling this "message".

So first, I acknowledge that this isn't strictly hint level related and so one could make the argument this shouldn't be in this patch. But I think the ultimate goal should be that in the rover UX, errors and hints can be displayed in a consistent way, where errors can just be considered as the highest "hint level" (in fact, we do hope to "merge" hints and errors in the code at some point in the future to clean things up). But doing that cleanly implies rover can access the hint code and message separately, the same way it does for errors, so it can maybe colorize the code and/or format it however it pleases. This could also allow flexibility like grouping messages by code for both hints and errors, or filtering certain code, etc.

Long story short, the current BuildHint.message field of hint.rs is currently unfortunately not really just the hint message, it is a pre-formatted string with both the code and (raw) message and this method is meant to provide a way out of this.

In theory, a better alternative would be to change BuildHint.message to only be the actual hint message and to add a BuildHint.code for the code, and to maybe also ensure those are separate in the underlying JSON object so it's easier to do, but I was kind of worried about breaking things by doing those things. So the idea of this method was to keep BuiltHint.message unchanged so we don't break existing usages, but to allow future usages to be able to access the code and message components individually.

Anyway, hope this clarify. If you're not worry about the concerns around breaking existing code, I'm happy to change all this, but I think it would require some care around versioning this properly, because if we change this, currently rover version would need to not use federation-rs versions with such changes (or rather, if they do, the hint will suddenly not be displayed with their code since it wouldn't be part of BuildHint.message anymore).

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we have to worry about breaking existing code! We should definitely change the underlying library code away from the .toString here - the only thing that matters is that we don't remove fields from the JSON that's actually emitted by the supergraph binary. Everything else is an internal contract - we only need to hold up the end to end guarantee.

Copy link
Author

Choose a reason for hiding this comment

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

the only thing that matters is that we don't remove fields from the JSON that's actually emitted by the supergraph binary

But currently, the JSON of the supergraph binary has the message field for hints that is the pre-formatted string containing both the "raw" message and the code. And existing rover versions kind of assume this is what this field contains, but we ultimately want rover to be able to access separately and not as a pre-formatted string. So if we do the "cleanest" change here without backward compatibility concerns, we would be changing that message field to now be only the "raw" message, without code, and the code would be a new field. Technically this is not a field removal, but it's changing what the field holds, and I assume that would be an issue too?

The alternative could be keep the message field containing the pre-formatted string (we can still stop having the pre-formatted string in the JSON from javascript, but the supergraph binary itself would be the one formatting the string for its own JSON output), but also add 2 new fields, code and raw_message, with the message field essentially becoming deprecated but kept for backward compatibility.

Does that make sense, or am I overcomplicating this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Technically this is not a field removal, but it's changing what the field holds, and I assume that would be an issue too?

Yeah - I think you're right here, we want older versions to still be able to work.

The alternative could be keep the message field containing the pre-formatted string (we can still stop having the pre-formatted string in the JSON from javascript, but the supergraph binary itself would be the one formatting the string for its own JSON output), but also add 2 new fields, code and raw_message, with the message field essentially becoming deprecated but kept for backward compatibility.

Old versions of Rover will discard any new unused JSON fields (we should test this to verify of course), but this approach sounds perfectly reasonable to me!

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the feedback. I'll try to update the patch accordingly ... when I find a bit of time for it.

hints.push({ message: composed_hint.toString() });
hints.push({
message: composed_hint.toString(),
level: composed_hint.definition.level,
Copy link
Contributor

Choose a reason for hiding this comment

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

it looks like we are putting that info right into the JSON object here in the JS code - can we just do something like

let data = serde_json::from_string(data_from_js);
let message = data["message"];
let level = data["level"];

?

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.

feat(composition): add hint levels to output types
2 participants