Loki: remove angular (#49471)

* loki: remove angular

Co-Authored-By: Joey Tawadrous <joey.tawadrous@grafana.com>

* better backward-compatibility

* slightly better typescript check

Co-authored-by: Joey Tawadrous <joey.tawadrous@grafana.com>
This commit is contained in:
Gábor Farkas 2022-06-07 12:41:16 +02:00 committed by GitHub
parent e9fac9ee03
commit cb96f51c73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 93 deletions

View File

@ -22,7 +22,6 @@ import { MetricSelect } from '../core/components/Select/MetricSelect';
import { TagFilter } from '../core/components/TagFilter/TagFilter';
import { HelpModal } from '../core/components/help/HelpModal';
import { SearchField, SearchResults, SearchResultsFilter } from '../features/search';
import { LokiAnnotationsQueryEditor } from '../plugins/datasource/loki/components/AnnotationsQueryEditor';
const { SecretFormField } = LegacyForms;
@ -143,13 +142,6 @@ export function registerAngularDirectives() {
['onChange', { watchDepth: 'reference', wrapApply: true }],
]);
react2AngularDirective('lokiAnnotationsQueryEditor', LokiAnnotationsQueryEditor, [
'expr',
'maxLines',
'instant',
'onChange',
['datasource', { watchDepth: 'reference' }],
]);
react2AngularDirective('datasourceHttpSettingsNext', DataSourceHttpSettings, [
'defaultUrl',
'showAccessOptions',

View File

@ -236,7 +236,7 @@ export function getAnnotationsFromData(
*/
export function shouldUseMappingUI(datasource: DataSourceApi): boolean {
const { type } = datasource;
return type !== 'prometheus' && type !== 'elasticsearch';
return type !== 'prometheus' && type !== 'elasticsearch' && type !== 'loki';
}
/**
@ -244,5 +244,5 @@ export function shouldUseMappingUI(datasource: DataSourceApi): boolean {
*/
export function shouldUseLegacyRunner(datasource: DataSourceApi): boolean {
const { type } = datasource;
return type === 'prometheus' || type === 'elasticsearch';
return type === 'prometheus' || type === 'elasticsearch' || type === 'loki';
}

View File

@ -1,21 +0,0 @@
import { LokiQuery } from './types';
/**
* Just a simple wrapper for a react component that is actually implementing the query editor.
*/
export class LokiAnnotationsQueryCtrl {
static templateUrl = 'partials/annotations.editor.html';
declare annotation: any;
/** @ngInject */
constructor($scope: any) {
this.annotation = $scope.ctrl.annotation;
this.annotation.target = this.annotation.target || {};
this.onQueryChange = this.onQueryChange.bind(this);
}
onQueryChange(query: LokiQuery) {
this.annotation.expr = query.expr;
this.annotation.maxLines = query.maxLines;
this.annotation.instant = query.instant;
}
}

View File

@ -1,49 +1,126 @@
// Libraries
import React, { memo } from 'react';
import { AnnotationQuery } from '@grafana/data';
import { EditorRow, EditorField } from '@grafana/experimental';
import { Input } from '@grafana/ui';
// Types
import { LokiDatasource } from '../datasource';
import { LokiQuery } from '../types';
import { getNormalizedLokiQuery } from '../query_utils';
import { LokiQuery, LokiQueryType } from '../types';
import { LokiOptionFields } from './LokiOptionFields';
import { LokiQueryField } from './LokiQueryField';
import { LokiQueryEditorProps } from './types';
interface Props {
expr: string;
maxLines?: number;
instant?: boolean;
datasource: LokiDatasource;
onChange: (query: LokiQuery) => void;
}
type Props = LokiQueryEditorProps & {
annotation?: AnnotationQuery<LokiQuery>;
onAnnotationChange?: (annotation: AnnotationQuery<LokiQuery>) => void;
};
export const LokiAnnotationsQueryEditor = memo(function LokiAnnotationQueryEditor(props: Props) {
const { expr, maxLines, instant, datasource, onChange } = props;
const { annotation, onAnnotationChange } = props;
// this should never happen, but we want to keep typescript happy
if (annotation === undefined || onAnnotationChange === undefined) {
return null;
}
const onChangeQuery = (query: LokiQuery) => {
// the current version of annotations only stores an optional boolean
// field `instant` to handle the instant/range switch.
// we need to maintain compatiblity for now, so we do the same.
// we explicitly call `getNormalizedLokiQuery` to make sure `queryType`
// is set up correctly.
const instant = getNormalizedLokiQuery(query).queryType === LokiQueryType.Instant;
onAnnotationChange({
...annotation,
expr: query.expr,
maxLines: query.maxLines,
instant,
});
};
const queryWithRefId: LokiQuery = {
refId: '',
expr,
maxLines,
instant,
expr: annotation.expr,
maxLines: annotation.maxLines,
instant: annotation.instant,
queryType: annotation.queryType,
};
return (
<div className="gf-form-group">
<LokiQueryField
datasource={datasource}
query={queryWithRefId}
onChange={onChange}
onRunQuery={() => {}}
onBlur={() => {}}
history={[]}
ExtraFieldElement={
<LokiOptionFields
lineLimitValue={queryWithRefId?.maxLines?.toString() || ''}
resolution={queryWithRefId.resolution || 1}
query={queryWithRefId}
onRunQuery={() => {}}
onChange={onChange}
<>
<div className="gf-form-group">
<LokiQueryField
datasource={props.datasource}
query={queryWithRefId}
onChange={onChangeQuery}
onRunQuery={() => {}}
onBlur={() => {}}
history={[]}
ExtraFieldElement={
<LokiOptionFields
lineLimitValue={queryWithRefId?.maxLines?.toString() || ''}
resolution={queryWithRefId.resolution || 1}
query={queryWithRefId}
onRunQuery={() => {}}
onChange={onChangeQuery}
/>
}
/>
</div>
<EditorRow>
<EditorField
label="Title"
tooltip={
'Use either the name or a pattern. For example, {{instance}} is replaced with label value for the label instance.'
}
>
<Input
type="text"
placeholder="alertname"
value={annotation.titleFormat}
onChange={(event) => {
onAnnotationChange({
...annotation,
titleFormat: event.currentTarget.value,
});
}}
/>
}
/>
</div>
</EditorField>
<EditorField label="Tags">
<Input
type="text"
placeholder="label1,label2"
value={annotation.tagKeys}
onChange={(event) => {
onAnnotationChange({
...annotation,
tagKeys: event.currentTarget.value,
});
}}
/>
</EditorField>
<EditorField
label="Text"
tooltip={
'Use either the name or a pattern. For example, {{instance}} is replaced with label value for the label instance.'
}
>
<Input
type="text"
placeholder="instance"
value={annotation.textFormat}
onChange={(event) => {
onAnnotationChange({
...annotation,
textFormat: event.currentTarget.value,
});
}}
/>
</EditorField>
</EditorRow>
</>
);
});

View File

@ -47,6 +47,7 @@ import { renderLegendFormat } from '../prometheus/legend';
import { addLabelToQuery } from './add_label_to_query';
import { transformBackendResult } from './backendResultTransformer';
import { LokiAnnotationsQueryEditor } from './components/AnnotationsQueryEditor';
import { DEFAULT_RESOLUTION } from './components/LokiOptionFields';
import LanguageProvider from './language_provider';
import { escapeLabelValueInSelector } from './language_utils';
@ -118,6 +119,9 @@ export class LokiDatasource
const settingsData = instanceSettings.jsonData || {};
this.maxLines = parseInt(settingsData.maxLines ?? '0', 10) || DEFAULT_MAX_LINES;
this.useBackendMode = config.featureToggles.lokiBackendMode ?? false;
this.annotations = {
QueryEditor: LokiAnnotationsQueryEditor,
};
}
_request(apiUrl: string, data?: any, options?: Partial<BackendSrvRequest>): Observable<Record<string, any>> {

View File

@ -1,6 +1,5 @@
import { DataSourcePlugin } from '@grafana/data';
import { LokiAnnotationsQueryCtrl } from './LokiAnnotationsQueryCtrl';
import LokiCheatSheet from './components/LokiCheatSheet';
import LokiQueryEditorByApp from './components/LokiQueryEditorByApp';
import { ConfigEditor } from './configuration/ConfigEditor';
@ -9,5 +8,4 @@ import { LokiDatasource } from './datasource';
export const plugin = new DataSourcePlugin(LokiDatasource)
.setQueryEditor(LokiQueryEditorByApp)
.setConfigEditor(ConfigEditor)
.setQueryEditorHelp(LokiCheatSheet)
.setAnnotationQueryCtrl(LokiAnnotationsQueryCtrl);
.setQueryEditorHelp(LokiCheatSheet);

View File

@ -1,28 +0,0 @@
<loki-annotations-query-editor
expr="ctrl.annotation.expr"
max-lines="ctrl.annotation.maxLines"
instant="ctrl.annotation.instant"
on-change="ctrl.onQueryChange"
datasource="ctrl.datasource"
>
</loki-annotations-query-editor>
<div class="gf-form-group">
<h5 class="section-heading">Field formats<tip>For title and text fields, use either the name or a pattern. For example, {{instance}} is replaced with label value for the label instance.</tip></h5>
<div class="gf-form-inline">
<div class="gf-form">
<span class="gf-form-label width-5">Title</span>
<input type="text" class="gf-form-input max-width-9" ng-model='ctrl.annotation.titleFormat' placeholder="alertname"></input>
</div>
<div class="gf-form">
<span class="gf-form-label width-5">Tags</span>
<input type="text" class="gf-form-input max-width-9" ng-model='ctrl.annotation.tagKeys' placeholder="label1,label2"></input>
</div>
<div class="gf-form-inline">
<div class="gf-form">
<span class="gf-form-label width-5">Text</span>
<input type="text" class="gf-form-input max-width-9" ng-model='ctrl.annotation.textFormat' placeholder="instance"></input>
</div>
</div>
</div>
</div>