response_parser.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import moment from 'moment';
  2. import _ from 'lodash';
  3. export default class ResponseParser {
  4. constructor(private results) {}
  5. parseQueryResult() {
  6. let data: any = [];
  7. let columns: any = [];
  8. for (let i = 0; i < this.results.length; i++) {
  9. if (this.results[i].query.raw) {
  10. const xaxis = this.results[i].query.xaxis;
  11. const yaxises = this.results[i].query.yaxis;
  12. const spliton = this.results[i].query.spliton;
  13. columns = this.results[i].result.data.Tables[0].Columns;
  14. const rows = this.results[i].result.data.Tables[0].Rows;
  15. data = _.concat(
  16. data,
  17. this.parseRawQueryResultRow(this.results[i].query, columns, rows, xaxis, yaxises, spliton)
  18. );
  19. } else {
  20. const value = this.results[i].result.data.value;
  21. const alias = this.results[i].query.alias;
  22. data = _.concat(data, this.parseQueryResultRow(this.results[i].query, value, alias));
  23. }
  24. }
  25. return data;
  26. }
  27. parseRawQueryResultRow(query: any, columns, rows, xaxis: string, yaxises: string, spliton: string) {
  28. const data: any[] = [];
  29. const columnsForDropdown = _.map(columns, column => ({ text: column.ColumnName, value: column.ColumnName }));
  30. const xaxisColumn = columns.findIndex(column => column.ColumnName === xaxis);
  31. const yaxisesSplit = yaxises.split(',');
  32. const yaxisColumns = {};
  33. _.forEach(yaxisesSplit, yaxis => {
  34. yaxisColumns[yaxis] = columns.findIndex(column => column.ColumnName === yaxis);
  35. });
  36. const splitonColumn = columns.findIndex(column => column.ColumnName === spliton);
  37. const convertTimestamp = xaxis === 'timestamp';
  38. _.forEach(rows, row => {
  39. _.forEach(yaxisColumns, (yaxisColumn, yaxisName) => {
  40. const bucket =
  41. splitonColumn === -1
  42. ? ResponseParser.findOrCreateBucket(data, yaxisName)
  43. : ResponseParser.findOrCreateBucket(data, row[splitonColumn]);
  44. const epoch = convertTimestamp ? ResponseParser.dateTimeToEpoch(row[xaxisColumn]) : row[xaxisColumn];
  45. bucket.datapoints.push([row[yaxisColumn], epoch]);
  46. bucket.refId = query.refId;
  47. bucket.query = query.query;
  48. bucket.columnsForDropdown = columnsForDropdown;
  49. });
  50. });
  51. return data;
  52. }
  53. parseQueryResultRow(query: any, value, alias: string) {
  54. const data: any[] = [];
  55. if (ResponseParser.isSingleValue(value)) {
  56. const metricName = ResponseParser.getMetricFieldKey(value);
  57. const aggField = ResponseParser.getKeyForAggregationField(value[metricName]);
  58. const epoch = ResponseParser.dateTimeToEpoch(value.end);
  59. data.push({
  60. target: metricName,
  61. datapoints: [[value[metricName][aggField], epoch]],
  62. refId: query.refId,
  63. query: query.query,
  64. });
  65. return data;
  66. }
  67. const groupedBy = ResponseParser.hasSegmentsField(value.segments[0]);
  68. if (!groupedBy) {
  69. const metricName = ResponseParser.getMetricFieldKey(value.segments[0]);
  70. const dataTarget = ResponseParser.findOrCreateBucket(data, metricName);
  71. for (let i = 0; i < value.segments.length; i++) {
  72. const epoch = ResponseParser.dateTimeToEpoch(value.segments[i].end);
  73. const aggField: string = ResponseParser.getKeyForAggregationField(value.segments[i][metricName]);
  74. dataTarget.datapoints.push([value.segments[i][metricName][aggField], epoch]);
  75. }
  76. dataTarget.refId = query.refId;
  77. dataTarget.query = query.query;
  78. } else {
  79. for (let i = 0; i < value.segments.length; i++) {
  80. const epoch = ResponseParser.dateTimeToEpoch(value.segments[i].end);
  81. for (let j = 0; j < value.segments[i].segments.length; j++) {
  82. const metricName = ResponseParser.getMetricFieldKey(value.segments[i].segments[j]);
  83. const aggField = ResponseParser.getKeyForAggregationField(value.segments[i].segments[j][metricName]);
  84. const target = this.getTargetName(value.segments[i].segments[j], alias);
  85. const bucket = ResponseParser.findOrCreateBucket(data, target);
  86. bucket.datapoints.push([value.segments[i].segments[j][metricName][aggField], epoch]);
  87. bucket.refId = query.refId;
  88. bucket.query = query.query;
  89. }
  90. }
  91. }
  92. return data;
  93. }
  94. getTargetName(segment, alias: string) {
  95. let metric = '';
  96. let segmentName = '';
  97. let segmentValue = '';
  98. for (const prop in segment) {
  99. if (_.isObject(segment[prop])) {
  100. metric = prop;
  101. } else {
  102. segmentName = prop;
  103. segmentValue = segment[prop];
  104. }
  105. }
  106. if (alias) {
  107. const regex = /\{\{([\s\S]+?)\}\}/g;
  108. return alias.replace(regex, (match, g1, g2) => {
  109. const group = g1 || g2;
  110. if (group === 'metric') {
  111. return metric;
  112. } else if (group === 'groupbyname') {
  113. return segmentName;
  114. } else if (group === 'groupbyvalue') {
  115. return segmentValue;
  116. }
  117. return match;
  118. });
  119. }
  120. return metric + `{${segmentName}="${segmentValue}"}`;
  121. }
  122. static isSingleValue(value) {
  123. return !ResponseParser.hasSegmentsField(value);
  124. }
  125. static findOrCreateBucket(data, target) {
  126. let dataTarget = _.find(data, ['target', target]);
  127. if (!dataTarget) {
  128. dataTarget = { target: target, datapoints: [] };
  129. data.push(dataTarget);
  130. }
  131. return dataTarget;
  132. }
  133. static hasSegmentsField(obj) {
  134. const keys = _.keys(obj);
  135. return _.indexOf(keys, 'segments') > -1;
  136. }
  137. static getMetricFieldKey(segment) {
  138. const keys = _.keys(segment);
  139. return _.filter(_.without(keys, 'start', 'end'), key => {
  140. return _.isObject(segment[key]);
  141. })[0];
  142. }
  143. static getKeyForAggregationField(dataObj): string {
  144. const keys = _.keys(dataObj);
  145. return _.intersection(keys, ['sum', 'avg', 'min', 'max', 'count', 'unique'])[0];
  146. }
  147. static dateTimeToEpoch(dateTime) {
  148. return moment(dateTime).valueOf();
  149. }
  150. static parseMetricNames(result) {
  151. const keys = _.keys(result.data.metrics);
  152. return ResponseParser.toTextValueList(keys);
  153. }
  154. parseMetadata(metricName: string) {
  155. const metric = this.results.data.metrics[metricName];
  156. if (!metric) {
  157. throw Error('No data found for metric: ' + metricName);
  158. }
  159. return {
  160. primaryAggType: metric.defaultAggregation,
  161. supportedAggTypes: metric.supportedAggregations,
  162. supportedGroupBy: metric.supportedGroupBy.all,
  163. };
  164. }
  165. parseGroupBys() {
  166. return ResponseParser.toTextValueList(this.results.supportedGroupBy);
  167. }
  168. parseQuerySchema() {
  169. const result = {
  170. Type: 'AppInsights',
  171. Tables: {}
  172. };
  173. if (this.results && this.results.data && this.results.data.Tables) {
  174. for (let i = 0; i < this.results.data.Tables[0].Rows.length; i++) {
  175. const column = this.results.data.Tables[0].Rows[i];
  176. const columnTable = column[0];
  177. const columnName = column[1];
  178. const columnType = column[2];
  179. if (result.Tables[columnTable]) {
  180. result.Tables[columnTable].OrderedColumns.push({ Name: columnName, Type: columnType });
  181. } else {
  182. result.Tables[columnTable] = {
  183. Name: columnTable,
  184. OrderedColumns: [
  185. { Name: columnName, Type: columnType }
  186. ]
  187. };
  188. }
  189. }
  190. }
  191. return result;
  192. }
  193. static toTextValueList(values) {
  194. const list: any[] = [];
  195. for (let i = 0; i < values.length; i++) {
  196. list.push({
  197. text: values[i],
  198. value: values[i],
  199. });
  200. }
  201. return list;
  202. }
  203. }