-
Notifications
You must be signed in to change notification settings - Fork 47
Variables: support object-based values with multiple properties #1236
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
base: variable-value-properties
Are you sure you want to change the base?
Conversation
packages/scenes/src/variables/variants/query/QueryVariable.test.tsx
Outdated
Show resolved
Hide resolved
packages/scenes/src/variables/variants/query/toMetricFindValues.test.ts
Outdated
Show resolved
Hide resolved
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.
hm.. this is tricky, torn on how to proceed, feels messy somehow to add it like this.
maybe a unified variable approach is best, at least from a technical stand point, interested in trying it out just to see how it would change things, simplify things
torn a bit where the text/value prop bit should be as well, inside the value / options provider abstraction or outside it
|
|
||
| export interface CustomVariableState extends MultiValueVariableState { | ||
| query: string; | ||
| optionsProvider: OptionsProviderSettings; |
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.
not sure I like this, think it would be better if this was a simple interface.
something like
export interface VariableValueProvider {
getValues(arg: VariableGetOptionsArgs): Observable<MetricFindValueWithOptionalProperties>
}Hm.. Interested in trying to do this in a new SelectVariable (and leave CustomVariable and QueryVariable as is for now). just to get a sense of how that would work/look.
The query string state property of CustomVariable should not really exist, it's an option that should be part of provider object/class (as it's type and value depends on the provider).
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.
did a quick test here: 1449343
hm.. the problem with that approach is that it becomes a bit of a pain to update the state of the value providers (have to create a new one), would have to make the value providers scene objects to solve that, which feels a bit overkill / hoping to avoid that :(
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 can inject an instance of the provider, that would be neat. My thought here is to try keeping the changes minimal from a consumer perspective and not to break the existing contract (like passing query):
new CustomVariable({ query: '[]', optionsProvider: { type: 'json' } });vs
new CustomVariable({ optionsProvider: { getOptions(arg) { ... } } });Interested in trying to do this in a new SelectVariable (and leave CustomVariable and QueryVariable as is for now). just to get a sense of how that would work/look.
👍🏾👍🏾 It would give us a good idea of how proposal 3 of the design doc would look like.
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.
If we are to make a change to CustomVariable and still use the query property for the csv/json content, I think we should try to make the smallest / simplest thing, just adding a new option.
valuesFormat: 'csv' | 'json' I think we can wait with textProp and valueProp for now (trying to simplify, remove all options that are not 100% needed). we can use same heurstic as toMetricFindValues (property named value and text, if not use first string for value, rest goes to properties)
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.
About the heuristic to find values and labels, wouldn't it be better not to assume we will be able to rely on them (or at that it'll be easy to rely on them) for all the datasources that will start getting support (Elastic and Postgres) and for all the scenarios from a user perspective?
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.
+1 on @torkelo comment of having minimal interface change here, type: 'csv' | 'json', or valuesFormat: 'csv' | 'json'. With custom variable it's really valuesFormat?: 'json' as CSV is the default already.
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.
Sorry for backtracking a bit on previous feedback, variables are complex, it takes time to find the right change, if we are to modify the current Custom and Query I think a more minimalistic change could work
thoughts?
| refresh: VariableRefresh.onDashboardLoad, | ||
| sort: VariableSort.disabled, | ||
| ...initialState, | ||
| optionsProvider: { ...initialState.optionsProvider, type: 'query' }, |
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 feels unnecessary here, as it's inside the QueryVariable, we know the provider
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 was added it to be able to pass custom valueProp and textProp
| options.unshift(...customOptions); | ||
| } | ||
| return new Observable((subscriber) => { | ||
| buildOptionsProvider(this as unknown as MultiValueVariable) |
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 looks less then ideal
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.
On the pros side, it's quite simple to rely on the factory function ; on the cons side, a new instance has to be built every time.
To mitigate the cons, could we rely on memoization?
| return []; | ||
| } | ||
|
|
||
| const processedDataFrames = getProcessedDataFrames(frames); |
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.
Both elastic and postgres use the metricFindQuery so already return MetricFindValue, so this function will return already on line 29 (unless we update those data sources to handle variables differently)
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 think it was mentioned when we reached the consensus on the design doc. Besides pinging the owners of the Elastic and Postgres datasources, is the change in this PR enough?
|
|
||
| export interface CustomVariableState extends MultiValueVariableState { | ||
| query: string; | ||
| optionsProvider: OptionsProviderSettings; |
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.
If we are to make a change to CustomVariable and still use the query property for the csv/json content, I think we should try to make the smallest / simplest thing, just adding a new option.
valuesFormat: 'csv' | 'json' I think we can wait with textProp and valueProp for now (trying to simplify, remove all options that are not 100% needed). we can use same heurstic as toMetricFindValues (property named value and text, if not use first string for value, rest goes to properties)
packages/scenes/src/variables/variants/MultiValueVariable.test.ts
Outdated
Show resolved
Hide resolved
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.
In my opinion this PR introduces a lot of unjustified infrastructure(providers, runtime registration, factories) for really solving the problem of supporting json values. The provider approach would be nice if we were to scale the format options, but I cannot see introducing any new formats any time soon - maybe yaml would make sense, but I doubt truly.
Things like buildOptionsProvider(... could really be solved by instance functions (this.parseXXX) that under the hood could use utils for the parsing if we want to abstract anything. So much easier to reason about IMO, think about debugging for example: CustomVariable.parseValues() vs CustomVariable/buildOptionsProvider()/registry/provider/getOptions
i think solution like this in the variable should be enough to get the same result:
private parseValues(query: string, format?: 'csv' | 'json') {
return format === 'json' ? this.parseJson(query) : this.parseCsv(query);
}|
|
||
| type BuilderFunction = (variable: CustomVariable | QueryVariable) => CustomOptionsProvider; | ||
|
|
||
| const OPTIONS_PROVIDERS_REGISTRY = new Map<string, BuilderFunction>([ |
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.
Do we anticipate more formats introduction? I don't see a justification for having this complexity at this stage. Eventually when we decide to unify custom/query variable under List variable, this will become unnecessary.
|
|
||
| export interface CustomVariableState extends MultiValueVariableState { | ||
| query: string; | ||
| optionsProvider: OptionsProviderSettings; |
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.
+1 on @torkelo comment of having minimal interface change here, type: 'csv' | 'json', or valuesFormat: 'csv' | 'json'. With custom variable it's really valuesFormat?: 'json' as CSV is the default already.
Based on #1228, resolves https://github.com/grafana/grafana-org/issues/555
Design doc
This PR:
csv,jsonandqueryjsonandqueryproviders to support object values with multiple propertiesCustomVariableandQueryVariableto use options providersMultiValueVariableto support value objectsThe other changes are consequences of the changes above.
Todos
DataSourceVariableto use its own options provider?