12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import { isString } from 'lodash';
- import { map } from 'rxjs/operators';
- import {
- ArrayVector,
- DataFrame,
- DataTransformerID,
- Field,
- FieldType,
- getFieldTypeFromValue,
- SynchronousDataTransformerInfo,
- } from '@grafana/data';
- import { findField } from 'app/features/dimensions';
- import { FieldExtractorID, fieldExtractors } from './fieldExtractors';
- export interface ExtractFieldsOptions {
- source?: string;
- format?: FieldExtractorID;
- replace?: boolean;
- }
- export const extractFieldsTransformer: SynchronousDataTransformerInfo<ExtractFieldsOptions> = {
- id: DataTransformerID.extractFields,
- name: 'Extract fields',
- description: 'Parse fields from the contends of another',
- defaultOptions: {},
- operator: (options) => (source) => source.pipe(map((data) => extractFieldsTransformer.transformer(options)(data))),
- transformer: (options: ExtractFieldsOptions) => {
- return (data: DataFrame[]) => {
- return data.map((v) => addExtractedFields(v, options));
- };
- },
- };
- function addExtractedFields(frame: DataFrame, options: ExtractFieldsOptions): DataFrame {
- if (!options.source) {
- return frame;
- }
- const source = findField(frame, options.source);
- if (!source) {
- // this case can happen when there are multiple queries
- return frame;
- }
- const ext = fieldExtractors.getIfExists(options.format ?? FieldExtractorID.Auto);
- if (!ext) {
- throw new Error('unkonwn extractor');
- }
- const count = frame.length;
- const names: string[] = []; // keep order
- const values = new Map<string, any[]>();
- for (let i = 0; i < count; i++) {
- let obj = source.values.get(i);
- if (isString(obj)) {
- try {
- obj = ext.parse(obj);
- } catch {
- obj = {}; // empty
- }
- }
- for (const [key, val] of Object.entries(obj)) {
- let buffer = values.get(key);
- if (buffer == null) {
- buffer = new Array(count);
- values.set(key, buffer);
- names.push(key);
- }
- buffer[i] = val;
- }
- }
- const fields = names.map((name) => {
- const buffer = values.get(name);
- return {
- name,
- values: new ArrayVector(buffer),
- type: buffer ? getFieldTypeFromValue(buffer.find((v) => v != null)) : FieldType.other,
- config: {},
- } as Field;
- });
- if (!options.replace) {
- fields.unshift(...frame.fields);
- }
- return {
- ...frame,
- fields,
- };
- }
|