Skip to content

Commit

Permalink
Query UI: Add tenant box
Browse files Browse the repository at this point in the history
With this commit as tenant box is added to the query UI. It can be used
to specify which tenant to use when making a query.

Signed-off-by: Jacob Baungard Hansen <jacobbaungard@redhat.com>
  • Loading branch information
jacobbaungard committed Nov 1, 2023
1 parent ec6b8b6 commit a394cb5
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 50 deletions.
2 changes: 1 addition & 1 deletion cmd/thanos/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ func runQuery(

ins := extpromhttp.NewTenantInstrumentationMiddleware(tenantHeader, defaultTenant, reg, nil)
// TODO(bplotka in PR #513 review): pass all flags, not only the flags needed by prefix rewriting.
ui.NewQueryUI(logger, endpoints, webExternalPrefix, webPrefixHeaderName, alertQueryURL).Register(router, ins)
ui.NewQueryUI(logger, endpoints, webExternalPrefix, webPrefixHeaderName, alertQueryURL, tenantHeader, defaultTenant).Register(router, ins)

api := apiv1.NewQueryAPI(
logger,
Expand Down
80 changes: 40 additions & 40 deletions pkg/ui/bindata.go

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions pkg/ui/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ type Query struct {
now func() model.Time
}

func NewQueryUI(logger log.Logger, endpointSet *query.EndpointSet, externalPrefix, prefixHeader, alertQueryURL string) *Query {
func NewQueryUI(logger log.Logger, endpointSet *query.EndpointSet, externalPrefix, prefixHeader, alertQueryURL string, tenantHeader string, defaultTenant string) *Query {
tmplVariables := map[string]string{
"Component": component.Query.String(),
"queryURL": alertQueryURL,
"Component": component.Query.String(),
"queryURL": alertQueryURL,
"tenantHeader": tenantHeader,
"defaultTenant": defaultTenant,
}
runtimeInfo := api.GetRuntimeInfoFunc(logger)

Expand Down
2 changes: 2 additions & 0 deletions pkg/ui/react-app/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<script>
const THANOS_COMPONENT="{{ .Component }}";
const THANOS_QUERY_URL="{{ .queryURL }}";
const THANOS_TENANT_HEADER="{{ .tenantHeader }}";
const THANOS_DEFAULT_TENANT="{{ .defaultTenant }}";
</script>

<!--
Expand Down
2 changes: 2 additions & 0 deletions pkg/ui/react-app/src/pages/graph/Panel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const defaultProps: PanelProps = {
engine: 'prometheus',
analyze: false,
disableAnalyzeCheckbox: false,
tenant: 'default-tenant',
},
onOptionsChanged: (): void => {
// Do nothing.
Expand Down Expand Up @@ -101,6 +102,7 @@ describe('Panel', () => {
engine: 'prometheus',
analyze: false,
disableAnalyzeCheckbox: false,
tenant: 'default-tenant',
};
const graphPanel = mount(<Panel {...defaultProps} options={options} />);
const controls = graphPanel.find(GraphControls);
Expand Down
48 changes: 42 additions & 6 deletions pkg/ui/react-app/src/pages/graph/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Store } from '../../thanos/pages/stores/store';
import PathPrefixProps from '../../types/PathPrefixProps';
import { QueryParams } from '../../types/types';
import { parseDuration } from '../../utils';
import { defaultTenant, tenantHeader } from '../../thanos/config';

export interface PanelProps {
id: string;
Expand Down Expand Up @@ -76,6 +77,7 @@ export interface PanelOptions {
engine: string;
analyze: boolean;
disableAnalyzeCheckbox: boolean;
tenant: string;
}

export enum PanelType {
Expand All @@ -98,6 +100,7 @@ export const PanelDefaultOptions: PanelOptions = {
engine: '',
analyze: false,
disableAnalyzeCheckbox: false,
tenant: '',
};

class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
Expand Down Expand Up @@ -132,6 +135,7 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
this.handleChangeAnalyze = this.handleChangeAnalyze.bind(this);
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseLeave = this.handleMouseLeave.bind(this);
this.handleChangeTenant = this.handleChangeTenant.bind(this);
}
componentDidUpdate({ options: prevOpts }: PanelProps): void {
const {
Expand All @@ -145,6 +149,7 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
usePartialResponse,
engine,
analyze,
tenant,
// TODO: Add support for Store Matches
} = this.props.options;
if (
Expand All @@ -157,7 +162,8 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
prevOpts.usePartialResponse !== usePartialResponse ||
prevOpts.forceTracing !== forceTracing ||
prevOpts.engine !== engine ||
prevOpts.analyze !== analyze
prevOpts.analyze !== analyze ||
prevOpts.tenant !== tenant
// Check store matches
) {
this.executeQuery();
Expand Down Expand Up @@ -215,25 +221,35 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
params.append('max_source_resolution', this.props.options.maxSourceResolution);
params.append('engine', this.props.options.engine);
params.append('analyze', this.props.options.analyze.toString());
params.append('tenant', this.props.options.tenant);
// TODO path prefix here and elsewhere.
break;
case 'table':
path = '/api/v1/query';
params.append('time', endTime.toString());
params.append('engine', this.props.options.engine);
params.append('analyze', this.props.options.analyze.toString());
params.append('tenant', this.props.options.tenant);
break;
default:
throw new Error('Invalid panel type "' + this.props.options.type + '"');
}

// Create request headers
const requestHeaders: HeadersInit = new Headers();
requestHeaders.set('Content-Type', 'application/json');

if (this.props.options.forceTracing) {
requestHeaders.set('X-Thanos-Force-Tracing', 'true');
}

if (this.props.options.tenant.length > 0) {
requestHeaders.set(tenantHeader, this.props.options.tenant);
}

fetch(`${this.props.pathPrefix}${path}?${params}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
// Conditionally add the header if the checkbox is enabled
...(this.props.options.forceTracing ? { 'X-Thanos-Force-Tracing': 'true' } : {}),
},
headers: requestHeaders,
cache: 'no-store',
credentials: 'same-origin',
signal: abortController.signal,
Expand Down Expand Up @@ -359,6 +375,10 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
this.setOptions({ analyze: event.target.checked });
};

handleChangeTenant = (event: React.ChangeEvent<HTMLInputElement>): void => {
this.setOptions({ tenant: event.target.value });
};

handleMouseEnter = () => {
this.setState({ isHovered: true });
};
Expand Down Expand Up @@ -536,6 +556,22 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> {
<option value="prometheus">Prometheus</option>
<option value="thanos">Thanos</option>
</Input>
<Label style={{ marginLeft: '10px', display: 'inline-block' }} className="control-label">
Tenant
</Label>
<Input
style={{
width: 'auto',
marginLeft: '10px',
display: 'inline-block',
}}
id={`tenant=${id}`}
type="text"
bsSize="sm"
onChange={this.handleChangeTenant}
placeholder={`${defaultTenant}`}
value={options.tenant}
></Input>
</div>
<div className="float-right" onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<Checkbox
Expand Down
12 changes: 12 additions & 0 deletions pkg/ui/react-app/src/thanos/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
declare const THANOS_QUERY_URL: string;
declare const THANOS_TENANT_HEADER: string;
declare const THANOS_DEFAULT_TENANT: string;

export let queryURL = THANOS_QUERY_URL;
if (queryURL === '' || queryURL === '{{ .queryURL }}') {
queryURL = 'http://localhost:10902';
}

export let defaultTenant = THANOS_DEFAULT_TENANT;
if (defaultTenant === '' || defaultTenant === '{{ .defaultTenant }}') {
defaultTenant = 'default-tenant';
}

export let tenantHeader = THANOS_TENANT_HEADER;
if (tenantHeader === '' || tenantHeader === '{{ .tenantHeader }}') {
tenantHeader = 'thanos-tenant';
}
5 changes: 5 additions & 0 deletions pkg/ui/react-app/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ export const parseOption = (param: string): Partial<PanelOptions> => {

case 'analyze':
return { analyze: decodedValue === '1' };

case 'tenant':
return { tenant: decodedValue };
}
return {};
};
Expand All @@ -258,6 +261,7 @@ export const toQueryString = ({ key, options }: PanelMeta): string => {
storeMatches,
engine,
analyze,
tenant,
} = options;
const time = isPresent(endTime) ? formatTime(endTime) : false;
const urlParams = [
Expand All @@ -271,6 +275,7 @@ export const toQueryString = ({ key, options }: PanelMeta): string => {
formatWithKey('store_matches', JSON.stringify(storeMatches, ['name'])),
formatWithKey('engine', engine),
formatWithKey('analyze', analyze ? 1 : 0),
formatWithKey('tenant', tenant),
time ? `${formatWithKey('end_input', time)}&${formatWithKey('moment_input', time)}` : '',
isPresent(resolution) ? formatWithKey('step_input', resolution) : '',
];
Expand Down
1 change: 1 addition & 0 deletions pkg/ui/react-app/src/utils/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ describe('Utils', () => {
engine: 'prometheus',
analyze: false,
disableAnalyzeCheckbox: false,
tenant: 'default-tenant',
},
})
).toEqual(
Expand Down

0 comments on commit a394cb5

Please sign in to comment.