@grafana/data#DataQueryError TypeScript Examples

The following examples show how to use @grafana/data#DataQueryError. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: explore.test.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
describe('getFirstQueryErrorWithoutRefId', () => {
  describe('when called with a null value', () => {
    it('then it should return undefined', () => {
      const errors: DataQueryError[] = null;
      const result = getFirstQueryErrorWithoutRefId(errors);

      expect(result).toBeUndefined();
    });
  });

  describe('when called with an array with only refIds', () => {
    it('then it should return undefined', () => {
      const errors: DataQueryError[] = [{ refId: 'A' }, { refId: 'B' }];
      const result = getFirstQueryErrorWithoutRefId(errors);

      expect(result).toBeUndefined();
    });
  });

  describe('when called with an array with and without refIds', () => {
    it('then it should return undefined', () => {
      const errors: DataQueryError[] = [
        { refId: 'A' },
        { message: 'A message' },
        { refId: 'B' },
        { message: 'B message' },
      ];
      const result = getFirstQueryErrorWithoutRefId(errors);

      expect(result).toBe(errors[1]);
    });
  });
});
Example #2
Source File: PanelInspector.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
renderErrorTab(error?: DataQueryError) {
    if (!error) {
      return null;
    }
    if (error.data) {
      return (
        <>
          <h3>{error.data.message}</h3>
          <JSONFormatter json={error} open={2} />
        </>
      );
    }
    return <div>{error.message}</div>;
  }
Example #3
Source File: runRequest.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
export function processQueryError(err: any): DataQueryError {
  const error = (err || {}) as DataQueryError;

  if (!error.message) {
    if (typeof err === 'string' || err instanceof String) {
      return { message: err } as DataQueryError;
    }

    let message = 'Query error';
    if (error.message) {
      message = error.message;
    } else if (error.data && error.data.message) {
      message = error.data.message;
    } else if (error.data && error.data.error) {
      message = error.data.error;
    } else if (error.status) {
      message = `Query error: ${error.status} ${error.statusText}`;
    }
    error.message = message;
  }

  return error;
}
Example #4
Source File: ErrorContainer.test.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
makeError = (propOverrides?: DataQueryError): DataQueryError => {
  const queryError: DataQueryError = {
    data: {
      message: 'Error data message',
      error: 'Error data content',
    },
    message: 'Error message',
    status: 'Error status',
    statusText: 'Error status text',
    refId: 'A',
    cancelled: false,
  };
  Object.assign(queryError, propOverrides);
  return queryError;
}
Example #5
Source File: datasource.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
processError = (err: any, target: LokiQuery): DataQueryError => {
    const error: DataQueryError = {
      message: (err && err.statusText) || 'Unknown error during query transaction. Please check JS console logs.',
      refId: target.refId,
    };

    if (err.data) {
      if (typeof err.data === 'string') {
        error.message = err.data;
      } else if (err.data.error) {
        error.message = safeStringifyValue(err.data.error);
      }
    } else if (err.message) {
      error.message = err.message;
    } else if (typeof err === 'string') {
      error.message = err;
    }

    error.status = err.status;
    error.statusText = err.statusText;

    return error;
  };
Example #6
Source File: datasource.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
handleErrors = (err: any, target: PromQuery) => {
    const error: DataQueryError = {
      message: (err && err.statusText) || 'Unknown error during query transaction. Please check JS console logs.',
      refId: target.refId,
    };

    if (err.data) {
      if (typeof err.data === 'string') {
        error.message = err.data;
      } else if (err.data.error) {
        error.message = safeStringifyValue(err.data.error);
      }
    } else if (err.message) {
      error.message = err.message;
    } else if (typeof err === 'string') {
      error.message = err;
    }

    error.status = err.status;
    error.statusText = err.statusText;

    return error;
  };
Example #7
Source File: datasource.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
processQueryResult(queries: any, res: any): DataQueryResponse {
    const data: TestData[] = [];
    let error: DataQueryError | undefined = undefined;

    for (const query of queries) {
      const results = res.data.results[query.refId];

      for (const t of results.tables || []) {
        const table = t as TableData;
        table.refId = query.refId;
        table.name = query.alias;
        data.push(table);
      }

      for (const series of results.series || []) {
        data.push({ target: series.name, datapoints: series.points, refId: query.refId, tags: series.tags });
      }

      if (results.error) {
        error = {
          message: results.error,
        };
      }
    }

    return { data, error };
  }
Example #8
Source File: datasource.ts    From grafana-kdb-datasource-ws with Apache License 2.0 5 votes vote down vote up
// Build the DataFrames to return to Grafana
  buildDataFrames(series) {
    let data: MutableDataFrame[] = [];
    let error = {} as DataQueryError;

    series.data.forEach((target) => {
      if (target.meta.errorMessage) {
        error.message = target.meta.errorMessage;
        throw new Error(target.meta.errorMessage);
      }
      if (target.columns) {
        var fields = [];
        target.columns.forEach((column) => {
          fields.push({ name: column.text });
        });
        const frame = new MutableDataFrame({
          refId: target.refId,
          fields: fields,
        });
        target.rows.forEach((element) => {
          var row = [];
          element.forEach((entry) => {
            row.push(entry);
          });
          frame.appendRow(row);
        });
        data.push(frame);
      } else {
        // time series

        let datapoints = target.datapoints;
        const timeValues = datapoints.map((datapoint) => datapoint[1]);
        const values = datapoints.map((datapoint) => datapoint[0]);

        const fields = [
          { name: 'Time', values: timeValues, type: FieldType.time },
          {
            name: target.target,
            values: values,
          },
        ];

        data.push(
          new MutableDataFrame({
            refId: target.refId,
            fields: fields,
          })
        );
      }
    });
    return { data, state: 'done' };
  }
Example #9
Source File: LogRowContextProvider.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
getRowContexts = async (
  getRowContext: (row: LogRowModel, options?: any) => Promise<DataQueryResponse>,
  row: LogRowModel,
  limit: number
) => {
  const promises = [
    getRowContext(row, {
      limit,
    }),
    getRowContext(row, {
      // The start time is inclusive so we will get the one row we are using as context entry
      limit: limit + 1,
      direction: 'FORWARD',
    }),
  ];

  const results: Array<DataQueryResponse | DataQueryError> = await Promise.all(promises.map(p => p.catch(e => e)));

  return {
    data: results.map(result => {
      const dataResult: DataQueryResponse = result as DataQueryResponse;
      if (!dataResult.data) {
        return [];
      }

      const data: any[] = [];
      for (let index = 0; index < dataResult.data.length; index++) {
        const dataFrame = toDataFrame(dataResult.data[index]);
        const fieldCache = new FieldCache(dataFrame);
        const timestampField: Field<string> = fieldCache.getFieldByName('ts')!;
        const idField: Field<string> | undefined = fieldCache.getFieldByName('id');

        for (let fieldIndex = 0; fieldIndex < timestampField.values.length; fieldIndex++) {
          // TODO: this filtering is datasource dependant so it will make sense to move it there so the API is
          //  to return correct list of lines handling inclusive ranges or how to filter the correct line on the
          //  datasource.

          // Filter out the row that is the one used as a focal point for the context as we will get it in one of the
          // requests.
          if (idField) {
            // For Loki this means we filter only the one row. Issue is we could have other rows logged at the same
            // ns which came before but they come in the response that search for logs after. This means right now
            // we will show those as if they came after. This is not strictly correct but seems better than loosing them
            // and making this correct would mean quite a bit of complexity to shuffle things around and messing up
            //counts.
            if (idField.values.get(fieldIndex) === row.uid) {
              continue;
            }
          } else {
            // Fallback to timestamp. This should not happen right now as this feature is implemented only for loki
            // and that has ID. Later this branch could be used in other DS but mind that this could also filter out
            // logs which were logged in the same timestamp and that can be a problem depending on the precision.
            if (parseInt(timestampField.values.get(fieldIndex), 10) === row.timeEpochMs) {
              continue;
            }
          }

          const lineField: Field<string> = dataFrame.fields.filter(field => field.name === 'line')[0];
          const line = lineField.values.get(fieldIndex); // assuming that both fields have same length

          if (data.length === 0) {
            data[0] = [line];
          } else {
            data[0].push(line);
          }
        }
      }

      return data;
    }),
    errors: results.map(result => {
      const errorResult: DataQueryError = result as DataQueryError;
      if (!errorResult.message) {
        return '';
      }

      return errorResult.message;
    }),
  };
}
Example #10
Source File: explore.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
getFirstQueryErrorWithoutRefId = (errors?: DataQueryError[]) => {
  if (!errors) {
    return undefined;
  }

  return errors.filter(error => (error && error.refId ? false : true))[0];
}
Example #11
Source File: explore.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
getFirstNonQueryRowSpecificError = (queryErrors?: DataQueryError[]) => {
  const refId = getValueWithRefId(queryErrors);
  return refId ? null : getFirstQueryErrorWithoutRefId(queryErrors);
}
Example #12
Source File: runRequest.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
/*
 * This function should handle composing a PanelData from multiple responses
 */
export function processResponsePacket(packet: DataQueryResponse, state: RunningQueryState): RunningQueryState {
  const request = state.panelData.request;
  const packets: MapOfResponsePackets = {
    ...state.packets,
  };

  packets[packet.key || 'A'] = packet;

  let loadingState = packet.state || LoadingState.Done;
  let error: DataQueryError | undefined = undefined;

  // Update the time range
  const range = { ...request.range };
  const timeRange = isString(range.raw.from)
    ? {
        from: dateMath.parse(range.raw.from, false),
        to: dateMath.parse(range.raw.to, true),
        raw: range.raw,
      }
    : range;

  const combinedData = flatten(
    lodashMap(packets, (packet: DataQueryResponse) => {
      if (packet.error) {
        loadingState = LoadingState.Error;
        error = packet.error;
      }
      return packet.data;
    })
  );

  const panelData = {
    state: loadingState,
    series: combinedData,
    error,
    request,
    timeRange,
  };

  return { packets, panelData };
}
Example #13
Source File: datasource.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
getLogRowContext = (row: LogRowModel, options?: LokiContextQueryOptions): Promise<{ data: DataFrame[] }> => {
    const target = this.prepareLogRowContextQueryTarget(
      row,
      (options && options.limit) || 10,
      (options && options.direction) || 'BACKWARD'
    );

    const reverse = options && options.direction === 'FORWARD';
    return this._request(RANGE_QUERY_ENDPOINT, target)
      .pipe(
        catchError((err: any) => {
          if (err.status === 404) {
            return of(err);
          }

          const error: DataQueryError = {
            message: 'Error during context query. Please check JS console logs.',
            status: err.status,
            statusText: err.statusText,
          };
          throw error;
        }),
        switchMap((res: { data: LokiStreamResponse; status: number }) =>
          iif(
            () => res.status === 404,
            defer(() =>
              this._request(LEGACY_QUERY_ENDPOINT, target).pipe(
                catchError((err: any) => {
                  const error: DataQueryError = {
                    message: 'Error during context query. Please check JS console logs.',
                    status: err.status,
                    statusText: err.statusText,
                  };
                  throw error;
                }),
                map((res: { data: LokiLegacyStreamResponse }) => ({
                  data: res.data ? res.data.streams.map(stream => legacyLogStreamToDataFrame(stream, reverse)) : [],
                }))
              )
            ),
            defer(() =>
              of({
                data: res.data ? res.data.data.result.map(stream => lokiStreamResultToDataFrame(stream, reverse)) : [],
              })
            )
          )
        )
      )
      .toPromise();
  };
Example #14
Source File: datasource.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
throwUnless = (err: any, condition: boolean, target: LokiQuery) => {
    if (condition) {
      return of(err);
    }

    const error: DataQueryError = this.processError(err, target);
    throw error;
  };
Example #15
Source File: QueryEditor.tsx    From grafana-kdb-datasource-ws with Apache License 2.0 4 votes vote down vote up
// useAsyncFunction(checked) {
  //   const { onChange, query, onRunQuery } = this.props;
  //   if (!checked) {
  //     onChange({ ...query, useAsyncFunction: checked });
  //     onRunQuery();
  //     this.setState({ useAsyncFunction: checked });
  //   } else {
  //     onChange({ ...query, useAsyncFunction: checked, asyncProcTypes: '' });
  //     onRunQuery();
  //     this.setState({ useAsyncFunction: checked, asyncField: '' });
  //   }
  // }

  // asyncFieldChanged(asyncField) {
  //   const { onChange, query, onRunQuery } = this.props;

  //   onChange({ ...query, asyncProcTypes: asyncField });
  //   onRunQuery();

  //   this.setState({ asyncField: asyncField });
  // }

  // useCustomPostback(checked) {
  //   const { onChange, query, onRunQuery } = this.props;
  //   if (!checked) {
  //     onChange({ ...query, useCustomPostback: checked });
  //     onRunQuery();
  //     this.setState({ useCustomPostback: checked });
  //   } else {
  //     onChange({ ...query, useCustomPostback: checked, postbackFunction: '' });
  //     onRunQuery();
  //     this.setState({ useCustomPostback: checked, postbackFunction: '' });
  //   }
  // }

  render() {
    const query = defaults(this.props.query, defaultQuery);

    const data = this.props.data;
    var error: DataQueryError;
    if (data) {
      error = data.error;
    }

    var selectAddButtonOptions = this.selectAddButtonOptions;

    if (!this.state.useConflation) {
      selectAddButtonOptions = selectAddButtonOptions.filter((o) => o.value !== 'aggregate');
    }

    return (
      <div>
        <div className="gf-form-inline">
          <div className="gf-form">
            <span className="gf-form-label query-keyword width-10">Query Type</span>
            <Select
              width={20}
              placeholder="Select Query Type"
              options={this.queryOptions}
              onChange={(e: SelectableValue<string>) => this.onQueryChange(e.value)}
              value={this.state.queryTypeStr || ''}
            />
          </div>
          <div className="gf-form gf-form--grow">
            <div className="gf-form-label gf-form-label--grow"></div>
          </div>
        </div>
        {this.state.queryTypeStr && this.state.queryTypeStr === 'selectQuery' && (
          <div>
            <div className="gf-form-inline">
              <div className="gf-form">
                {/* <InlineField label="From" labelWidth={20} style={{color: '#33A2E5'}} grow={true}> */}
                <span className="gf-form-label query-keyword width-10">From</span>
                <SegmentAsync
                  width={20}
                  placeholder="Select Table"
                  loadOptions={this.getTableSegments.bind(this)}
                  onChange={(e: SelectableValue<string>) => this.onTableFromChange(e.value)}
                  value={this.state.tableFrom || ''}
                />
                {/* </InlineField> */}
              </div>
              <div className="gf-form gf-form--grow">
                <div className="gf-form-label gf-form-label--grow"></div>
              </div>
            </div>
            {this.state.useTemporalField && (
              <div className="gf-form-inline">
                <div className="gf-form">
                  <InlineFormLabel
                    className="query-keyword"
                    tooltip="Time series data is plotted against this column.  Results are also automatically filtered on this field using the date extents of the graph."
                  >
                    Time Column
                  </InlineFormLabel>
                  <SegmentAsync
                    width={20}
                    placeholder="time"
                    loadOptions={this.getTimeColumnSegments.bind(this)}
                    onChange={(e: SelectableValue<string>) => this.onTimeColumnChange(e.value)}
                    value={this.state.timeColumn || ''}
                  />
                </div>
                <div className="gf-form gf-form--grow">
                  <div className="gf-form-label gf-form-label--grow"></div>
                </div>
              </div>
            )}
            {/* <div className="gf-form-inline"> */}
            {this.state.selectSegments.length == 0 && (
              <div className="gf-form-inline">
                <span className="gf-form-label query-keyword width-10">Select</span>
                <div className="gf-form-label width-4">
                  <Button
                    type="button"
                    className="btn btn-primary"
                    onClick={this.addNewSelectSegment.bind(this)}
                    style={{ background: '#202226', padding: '10', outline: 'none' }}
                  >
                    +
                  </Button>
                </div>
                <div className="gf-form gf-form--grow">
                  <div className="gf-form-label gf-form-label--grow" style={{ padding: '10' }}></div>
                </div>
              </div>
            )}
            {this.state.selectSegments.map((segment) => {
              return (
                <div className="gf-form-inline">
                  {this.state.selectSegments.indexOf(segment) == 0 && (
                    <div className="gf-form-inline">
                      <span className="gf-form-label query-keyword width-10">Select</span>
                    </div>
                  )}
                  {this.state.selectSegments.indexOf(segment) > 0 && (
                    <label className="gf-form-label query-keyword width-10" />
                  )}
                  <div className="gf-form">
                    {/* <InlineSegmentGroup> */}
                    <Segment
                      className="query-keyword"
                      value="Column:"
                      options={this.removeOption}
                      onChange={() => this.removeSelectSegment(segment)}
                    />
                    <SegmentAsync
                      onChange={(e: SelectableValue<string>) => {
                        segment.value = e.value;
                        this.setSelectSegment(segment);
                      }}
                      loadOptions={this.getSelectOptions.bind(this)}
                      value={segment.value || ''}
                      placeholder="Select field"
                    />
                    {/* </InlineSegmentGroup> */}
                  </div>
                  {segment.alias && (
                    <div className="gf-form-inline">
                      <InlineSegmentGroup>
                        <Segment
                          value="Alias:"
                          options={this.removeOption}
                          onChange={() => this.removeSelectSegmentAlias(segment)}
                        />
                        <SegmentInput
                          onChange={(e: string) => {
                            segment.alias = e;
                            this.setSelectSegment(segment);
                          }}
                          value={segment.alias || ''}
                        />
                      </InlineSegmentGroup>
                    </div>
                  )}
                  {segment.aggregate && (
                    <div className="gf-form-inline">
                      <InlineSegmentGroup>
                        <Segment
                          value="Aggregate:"
                          options={this.removeOption}
                          onChange={() => this.removeSelectSegmentAggregate(segment)}
                        />
                        <Segment
                          onChange={(e: SelectableValue<string>) => {
                            segment.aggregate = e.value;
                            this.setSelectSegment(segment);
                          }}
                          options={this.aggregateOptions}
                          value={segment.aggregate || ''}
                        />
                      </InlineSegmentGroup>
                    </div>
                  )}
                  <div>
                    <ButtonSelect
                      options={selectAddButtonOptions}
                      onChange={(e: SelectableValue<string>) => this.onSelectAddButtonPress(e, segment)}
                      style={{ background: '#202226' }}
                    >
                      +
                    </ButtonSelect>
                  </div>
                  <div className="gf-form gf-form--grow">
                    <div className="gf-form-label gf-form-label--grow"></div>
                  </div>
                </div>
              );
            })}
            {this.state.whereSegments.length == 0 && (
              <div className="gf-form-inline">
                <InlineFormLabel
                  className="query-keyword"
                  width={10}
                  tooltip="'in' and 'within' operator arguments need to be provided as a comma seperated list (e.g. sym in AAPL,MSFT,IBM). 'within' requires lower bound first (e.g within 75,100; NOT within 100,75)."
                >
                  Where
                </InlineFormLabel>
                <div className="gf-form-label width-4">
                  <Button
                    type="button"
                    className="btn btn-primary"
                    onClick={this.addNewWhereSegment.bind(this)}
                    style={{ width: '5', background: '#202226', padding: '10', outline: 'hidden' }}
                  >
                    +
                  </Button>
                </div>
                <div className="gf-form gf-form--grow">
                  <div className="gf-form-label gf-form-label--grow"></div>
                </div>
              </div>
            )}
            {this.state.whereSegments.map((segment) => {
              return (
                <div className="gf-form-inline">
                  {this.state.whereSegments.indexOf(segment) == 0 && (
                    <div className="gf-form-inline">
                      <InlineFormLabel
                        className="query-keyword"
                        width={10}
                        tooltip="'in' and 'within' operator arguments need to be provided as a comma seperated list (e.g. sym in AAPL,MSFT,IBM). 'within' requires lower bound first (e.g within 75,100; NOT within 100,75)."
                      >
                        Where
                      </InlineFormLabel>
                    </div>
                  )}

                  {/* <div className="gf-form">   */}
                  {this.state.whereSegments.indexOf(segment) > 0 && (
                    <label className="gf-form-label query-keyword width-10" />
                  )}
                  <div className="gf-form">
                    <Segment value="Expr" options={this.removeOption} onChange={() => this.removeSegment(segment)} />
                    <SegmentAsync
                      onChange={(e: SelectableValue<string>) => {
                        segment.expressionField = e.value;
                        this.setWhereSegment(segment);
                        this.setWhereOperators(e.value);
                      }}
                      loadOptions={this.getSelectOptions.bind(this)}
                      value={segment.expressionField || ''}
                      placeholder="Select field"
                    />
                    <Segment
                      onChange={(e: SelectableValue<string>) => {
                        segment.operator = e.value;
                        this.setWhereSegment(segment);
                      }}
                      options={this.state.whereOperators}
                      value={segment.operator || '='}
                      defaultValue={'='}
                    />
                    <SegmentInput
                      onChange={(e: string) => {
                        segment.value = e;
                        this.setWhereSegment(segment);
                      }}
                      placeholder="enter value"
                      value={segment.value || ''}
                    />
                  </div>
                  {this.state.whereSegments.indexOf(segment) == this.state.whereSegments.length - 1 && (
                    <div className="gf-form-inline">
                      {' '}
                      <Button
                        type="button"
                        className="btn btn-primary"
                        onClick={this.addNewWhereSegment.bind(this)}
                        style={{ background: '#202226' }}
                      >
                        +
                      </Button>{' '}
                    </div>
                  )}
                  {/* </div> */}
                  <div className="gf-form gf-form--grow">
                    <div className="gf-form-label gf-form-label--grow"></div>
                  </div>
                </div>
              );
            })}

            {/* </div> */}
          </div>
        )}
        {this.state.queryTypeStr && this.state.queryTypeStr == 'functionQuery' && (
          <div className="gf-form-inline">
            <div className="gf-form" style={{ height: '111px' }}>
              <span className="gf-form-label query-keyword width-10" style={{ height: '111px' }}>
                Function
              </span>
              <textarea
                className="gf-form-textarea width-30"
                rows={5}
                style={{ background: '#0b0c0e' }}
                value={this.state.functionBody}
                placeholder="Enter function"
                onChange={this.onFunctionChange}
              ></textarea>
            </div>
            <div className="gf-form gf-form--grow" style={{ height: '111px' }}>
              <div className="gf-form-label gf-form-label--grow" style={{ height: '111px' }}></div>
            </div>
          </div>
        )}
        {this.state.queryTypeStr && this.state.queryTypeStr !== 'kdbSideQuery' && (
          <div>
            {/* {this.state.queryTypeStr && this.state.queryTypeStr == 'functionQuery' && (
              <div>
                <div className="gf-form-inline">
                  <div className="gf-form">
                    <InlineFormLabel
                      className="gf-form-label query-keyword width-15"
                      tooltip="This allows use of asynchronous functions provided they utilise a postback function. Enable 'Custom Postback' if using non-TorQ Gateway."
                    >
                      <span>
                        <input
                          type="checkbox"
                          className="width-2"
                          checked={this.state.useAsyncFunction}
                          onChange={(e) => this.useAsyncFunction(e.currentTarget.checked)}
                        />
                      </span>
                      Use Async with Postback
                    </InlineFormLabel>
                  </div>
                  {this.state.useAsyncFunction && (
                    <div className="gf-form">
                      <InlineFormLabel className="query-keyword">Proc Types:</InlineFormLabel>
                      <SegmentInput
                        placeholder="Proc"
                        value={this.state.asyncField || ''}
                        onChange={(e: string) => {
                          this.asyncFieldChanged(e);
                        }}
                      />
                    </div>
                  )}
                  {this.state.useAsyncFunction && (
                    <div className="gf-form">
                      <InlineFormLabel
                        className="gf-form-label query-keyword width-15"
                        tooltip="This allows use of asynchronous functions provided they utilise a postback function. Enable 'Custom Postback' if using non-TorQ Gateway."
                      >
                        <span>
                          <input
                            type="checkbox"
                            className="width-2"
                            checked={this.state.useCustomPostback}
                            onChange={(e) => this.useCustomPostback(e.currentTarget.checked)}
                          />
                        </span>
                        Custom Postback
                      </InlineFormLabel>
                    </div>
                  )}
                  <div className="gf-form gf-form--grow">
                    <div className="gf-form-label gf-form-label--grow"></div>
                  </div>
                </div>
                {this.state.useAsyncFunction && this.state.useCustomPostback && (
                  <div className="gf-form-inline" style={{ height: '111px;' }}>
                    <span className="gf-form-label query-keyword width-10" style={{ height: '111px' }} />
                    <div style={{ height: '111px;' }}>
                      <textarea
                        className="gf-form-textarea width-30"
                        rows={5}
                        style={{ background: '#0b0c0e' }}
                        value={this.state.postbackFunction}
                        placeholder="Enter custom postback function"
                        onChange={this.asyncFieldChanged}
                      />
                    </div>
                    <div className="gf-form gf-form--grow">
                      <div className="gf-form-label gf-form-label--grow" style={{ height: '111px' }}></div>
                    </div>
                  </div>
                )}
              </div>
            )} */}
            {this.state.formatAs && this.state.formatAs !== 'table' && (
              <div className="gf-form-inline">
                <div className="gf-form">
                  <InlineFormLabel
                    className="gf-form-label query-keyword width-15"
                    tooltip="Used to separate selected data into relevant groups. The column specified is the one which contains the groups by which you wish to separate your data."
                  >
                    <span>
                      <input
                        type="checkbox"
                        className="width-2"
                        checked={this.state.useGrouping}
                        onChange={(e) => this.useGrouping(e.currentTarget.checked)}
                      />
                    </span>
                    Use Grouping
                  </InlineFormLabel>
                </div>
                {this.state.useGrouping && (
                  <div className="gf-form">
                    <InlineFormLabel className="query-keyword">Group By</InlineFormLabel>
                    <SegmentInput
                      value={this.state.groupBy || ''}
                      onChange={(e: string) => {
                        this.onGroupByChange(e);
                      }}
                    />
                  </div>
                )}
                <div className="gf-form gf-form--grow">
                  <div className="gf-form-label gf-form-label--grow"></div>
                </div>
              </div>
            )}
            <div className="gf-form-inline">
              <div className="gf-form" style={{ wordBreak: 'break-word', textAlign: 'right' }}>
                <InlineFormLabel
                  className="gf-form-label query-keyword width-15"
                  tooltip="Used to enable a date/time column, acting as a key for each record."
                >
                  <span>
                    <input
                      type="checkbox"
                      className="width-2"
                      checked={this.state.useTemporalField}
                      onChange={(e) => this.useTemporalField(e.currentTarget.checked)}
                    />
                  </span>
                  Use Temporal Field
                </InlineFormLabel>
              </div>
              {this.state.queryTypeStr === 'functionQuery' && this.state.useTemporalField && (
                <SegmentAsync
                  width={20}
                  placeholder="time"
                  loadOptions={this.getTimeColumnSegments.bind(this)}
                  onChange={(e: SelectableValue<string>) => this.onTimeColumnChange(e.value)}
                  value={this.state.timeColumn || ''}
                />
              )}
              <div className="gf-form gf-form--grow">
                <div className="gf-form-label gf-form-label--grow"></div>
              </div>
            </div>
            {this.state.useTemporalField && (
              <div className="gf-form-inline">
                <div className="gf-form">
                  <InlineFormLabel
                    className="gf-form-label query-keyword width-15"
                    tooltip="The time series data is divided into 'buckets' of time, then reduced to a single point for each interval bucket."
                  >
                    <span>
                      <input
                        type="checkbox"
                        className="width-2"
                        checked={this.state.useConflation}
                        onChange={(e) => this.useConflation(e.currentTarget.checked)}
                      />
                    </span>
                    Use Conflation
                  </InlineFormLabel>
                  {this.state.useConflation && (
                    <div className="gf-form-inline">
                      <InlineFormLabel className="query-keyword">Duration</InlineFormLabel>
                      <SegmentInput
                        value={this.state.conflation.duration || 5}
                        onChange={(e: number) => {
                          this.onDurationChange(e);
                        }}
                      />
                      <InlineFormLabel className="query-keyword">Units</InlineFormLabel>
                      <Select
                        width={20}
                        options={this.unitOptions}
                        onChange={(e: SelectableValue<string>) => this.onUnitChange(e.value)}
                        value={this.state.conflation.unitType || 'm'}
                      />
                      <InlineFormLabel
                        className="query-keyword"
                        width={20}
                        tooltip="The data in each bucket are reduced to a single value per bucket via an aggregation. E.G. 'Average' would take the mean of all points within each 5 minute peroid, for every 5 minute period of your time series data. It would then be the means that are plotted."
                      >
                        Default Aggregation
                      </InlineFormLabel>
                      <Select
                        width={20}
                        options={this.aggregateOptions}
                        onChange={(e: SelectableValue<string>) => this.onAggregateChange(e.value)}
                        value={this.state.conflation.aggregate || 'Last'}
                      />
                    </div>
                  )}
                </div>
                <div className="gf-form gf-form--grow">
                  <div className="gf-form-label gf-form-label--grow"></div>
                </div>
              </div>
            )}
          </div>
        )}
        <div>
          <div className="gf-form-inline">
            <div className="gf-form">
              <InlineFormLabel className="gf-form-label query-keyword">Format as</InlineFormLabel>
              <Select
                width={20}
                options={this.formatOptions}
                onChange={(e: SelectableValue<string>) => this.onFormatChange(e.value)}
                value={this.state.formatAs || ''}
              />
            </div>
            <div className="gf-form">
              <InlineFormLabel
                className="query-keyword"
                tooltip="An integer used to limit the number of rows loaded by Grafana for performance purposes."
              >
                Row Limit
              </InlineFormLabel>
              <SegmentInput
                value={this.state.rowCountLimit || ''}
                onChange={(e: number) => {
                  this.onRowLimitChange(e);
                }}
              />
            </div>
            <div className="gf-form">
              <Button
                onClick={this.showHelp.bind(this)}
                className="btn btn-primary"
                style={{ background: '#202226', color: '#33A2E5', outline: 'none' }}
              >
                Show Help
                {!this.state.showHelp && <i className="fa fa-caret-right"></i>}
                {this.state.showHelp && <i className="fa fa-caret-down"></i>}
              </Button>
            </div>
            <div className="gf-form gf-form--grow">
              <div className="gf-form-label gf-form-label--grow"></div>
            </div>
          </div>
        </div>
        {this.state.showHelp && (
          <div className="gf-form">
            <pre className="gf-form-pre alert alert-info">
              {' '}
              {`
                Plugin Version:`}{' '}
              {this.version}{' '}
              {`
                First, choose the datasource you wish to query.
                Query Type - Built Query:
                  Essential:
                    From - Select Table:
                    - Click 'Select Table' and type in the table you wish to query. If not tables appear in a drop down, check your datasource is connected.
                    Time Column - Select Time:
                    - Click 'Select Time' and type the column you wish to use as the time axis for the graph. This field can be diabled in on table visualisation.
                    Select - Select Column:
                    - Click 'select column' and type the column you wish to select for your visualisation. More columns may be added using the plus button beside and typing 'Column'.
                    - To remove a column, click 'Column:' and press 'Remove' in the drop-down.
                    - The identification of a column can be customised by clicking the plus button bside the column and entering 'Alias'.
                    - If conflation is used, the aggregate function applied to a column can be changed by clicking the plus button, typing 'Aggregate' and choosing from the drop-down menu. 
                    - If you are creating a table and selecting a time coloumn, you may need to change the 'type' to 'time' in the visualisation menu.
                    Row Limit:
                    - This limits the number of records that can be returned by the server to aid the performance of Grafana. If row limit is reached, either change the number or use conflation.

                  Optional:
                    Where - Expression:
                    - Click the plus button and type 'Expression' to add a where-clause template.
                    - Each element can be changed in the where-clause by clicking on them.
                    - Click 'Expr:' and click 'Remove' to remove an expression.
                    Grouping - Select Field:
                    - To enable grouping, check the box. Then click 'Select Field', type the field by which to categorise your data.
                    Conflation - Duration, Units, Default Aggregation:
                    - To enable conflation, check the box. Then adjust the time-buckets by changing the number and units.
                    - The Default Aggregation is the operation applied across the records per time-bucket. This can be overriden under the 'Select Column' section by using the plus button.
                  
                  Example of using Alias, Where and Conflation:
                  FROM: trade
                  TIME COLUMN: time
                  SELECT: Column: price; Alias: GOOG
                  WHERE: Expr: sym = GOOG
                  USE CONFLATION: Duration - 30; Units - Seconds; Aggregation - Last
                
                  
                Query Type - Free-form Query:
                  Esential:
                    Function - Enter function:
                    - Enter a kdb select statement into the textbox.
                    - If using graph visualisation, ensure time is selected in your statement.
                    Time Column - time (Graph visualisation):
                    - Enter here the time column against which Grafana will plot your timeseries data.
                    - This can be disabled in table visualisation using the checkbox.

                  Optional:
                    Grouping - Select Field:
                    - In the function, ensure to select the column by which to group your data. DO NOT put it in the by-clause of the function for graphical visualisation.
                    - Type the column name into the grouping field.
                    Conflation - Duration, Units, Default Aggregation:
                    - To enable conflation, check the box. Then adjust the time-buckets by changing the number and units.
                    - The Default Aggregation is the operation applied across the records per time-bucket. 
                    - This is not currently independently configurable. To aggregate columns differently, add duplicate your query and change the column and aggregation.

                    
                Query Type - Function:
                    - Click 'Select Function' and type/choose the function to be used.
                    - The plugin will attempt to detect the number of arguments and create segments to be adjusted. If this fails, more argument segments can be added using the plus button.
                    - Conflation and row limit functions are explaining in the Built Query mode.


              `}
            </pre>
          </div>
        )}
        {error && (
          <Alert title={error.message} />
          // <div className="gf-form">
          //   <pre className="gf-form-pre alert alert-error">{error.message}</pre>
          // </div>
        )}
      </div>
    );
  }
Example #16
Source File: Explore.test.tsx    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
setup = (renderMethod: any, propOverrides?: object) => {
  const props: ExploreProps = {
    changeSize: jest.fn(),
    datasourceInstance: {
      meta: {
        metrics: true,
        logs: true,
      },
      components: {
        ExploreStartPage: {},
      },
    } as DataSourceApi,
    datasourceMissing: false,
    exploreId: ExploreId.left,
    initializeExplore: jest.fn(),
    initialized: true,
    modifyQueries: jest.fn(),
    update: {
      datasource: false,
      queries: false,
      range: false,
      mode: false,
      ui: false,
    },
    refreshExplore: jest.fn(),
    scanning: false,
    scanRange: {
      from: '0',
      to: '0',
    },
    scanStart: jest.fn(),
    scanStopAction: scanStopAction,
    setQueries: jest.fn(),
    split: false,
    queryKeys: [],
    initialDatasource: 'test',
    initialQueries: [],
    initialRange: {
      from: toUtc('2019-01-01 10:00:00'),
      to: toUtc('2019-01-01 16:00:00'),
      raw: {
        from: 'now-6h',
        to: 'now',
      },
    },
    mode: ExploreMode.Metrics,
    initialUI: {
      showingTable: false,
      showingGraph: false,
      showingLogs: false,
    },
    isLive: false,
    syncedTimes: false,
    updateTimeRange: jest.fn(),
    graphResult: [],
    loading: false,
    absoluteRange: {
      from: 0,
      to: 0,
    },
    showingGraph: false,
    showingTable: false,
    timeZone: 'UTC',
    onHiddenSeriesChanged: jest.fn(),
    toggleGraph: toggleGraph,
    queryResponse: {
      state: LoadingState.NotStarted,
      series: [],
      request: ({
        requestId: '1',
        dashboardId: 0,
        interval: '1s',
        panelId: 1,
        scopedVars: {
          apps: {
            value: 'value',
          },
        },
        targets: [
          {
            refId: 'A',
          },
        ],
        timezone: 'UTC',
        app: CoreApp.Explore,
        startTime: 0,
      } as unknown) as DataQueryRequest,
      error: {} as DataQueryError,
      timeRange: {
        from: toUtc('2019-01-01 10:00:00'),
        to: toUtc('2019-01-01 16:00:00'),
        raw: {
          from: 'now-6h',
          to: 'now',
        },
      },
    },
    originPanelId: 1,
    addQueryRow: jest.fn(),
  };

  const store = configureStore();

  Object.assign(props, propOverrides);
  return renderMethod(
    <Provider store={store}>
      <Explore {...props} />
    </Provider>
  );
}