influx_series.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import _ from 'lodash';
  2. import TableModel from 'app/core/table_model';
  3. import { FieldType } from '@grafana/ui';
  4. export default class InfluxSeries {
  5. series: any;
  6. alias: any;
  7. annotation: any;
  8. constructor(options) {
  9. this.series = options.series;
  10. this.alias = options.alias;
  11. this.annotation = options.annotation;
  12. }
  13. getTimeSeries() {
  14. const output = [];
  15. let i, j;
  16. if (this.series.length === 0) {
  17. return output;
  18. }
  19. _.each(this.series, series => {
  20. const columns = series.columns.length;
  21. const tags = _.map(series.tags, (value, key) => {
  22. return key + ': ' + value;
  23. });
  24. for (j = 1; j < columns; j++) {
  25. let seriesName = series.name;
  26. const columnName = series.columns[j];
  27. if (columnName !== 'value') {
  28. seriesName = seriesName + '.' + columnName;
  29. }
  30. if (this.alias) {
  31. seriesName = this._getSeriesName(series, j);
  32. } else if (series.tags) {
  33. seriesName = seriesName + ' {' + tags.join(', ') + '}';
  34. }
  35. const datapoints = [];
  36. if (series.values) {
  37. for (i = 0; i < series.values.length; i++) {
  38. datapoints[i] = [series.values[i][j], series.values[i][0]];
  39. }
  40. }
  41. output.push({ target: seriesName, datapoints: datapoints });
  42. }
  43. });
  44. return output;
  45. }
  46. _getSeriesName(series, index) {
  47. const regex = /\$(\w+)|\[\[([\s\S]+?)\]\]/g;
  48. const segments = series.name.split('.');
  49. return this.alias.replace(regex, (match, g1, g2) => {
  50. const group = g1 || g2;
  51. const segIndex = parseInt(group, 10);
  52. if (group === 'm' || group === 'measurement') {
  53. return series.name;
  54. }
  55. if (group === 'col') {
  56. return series.columns[index];
  57. }
  58. if (!isNaN(segIndex)) {
  59. return segments[segIndex];
  60. }
  61. if (group.indexOf('tag_') !== 0) {
  62. return match;
  63. }
  64. const tag = group.replace('tag_', '');
  65. if (!series.tags) {
  66. return match;
  67. }
  68. return series.tags[tag];
  69. });
  70. }
  71. getAnnotations() {
  72. const list = [];
  73. _.each(this.series, series => {
  74. let titleCol = null;
  75. let timeCol = null;
  76. const tagsCol = [];
  77. let textCol = null;
  78. _.each(series.columns, (column, index) => {
  79. if (column === 'time') {
  80. timeCol = index;
  81. return;
  82. }
  83. if (column === 'sequence_number') {
  84. return;
  85. }
  86. if (column === this.annotation.titleColumn) {
  87. titleCol = index;
  88. return;
  89. }
  90. if (_.includes((this.annotation.tagsColumn || '').replace(' ', '').split(','), column)) {
  91. tagsCol.push(index);
  92. return;
  93. }
  94. if (column === this.annotation.textColumn) {
  95. textCol = index;
  96. return;
  97. }
  98. // legacy case
  99. if (!titleCol && textCol !== index) {
  100. titleCol = index;
  101. }
  102. });
  103. _.each(series.values, value => {
  104. const data = {
  105. annotation: this.annotation,
  106. time: +new Date(value[timeCol]),
  107. title: value[titleCol],
  108. // Remove empty values, then split in different tags for comma separated values
  109. tags: _.flatten(
  110. tagsCol
  111. .filter(t => {
  112. return value[t];
  113. })
  114. .map(t => {
  115. return value[t].split(',');
  116. })
  117. ),
  118. text: value[textCol],
  119. };
  120. list.push(data);
  121. });
  122. });
  123. return list;
  124. }
  125. getTable() {
  126. const table = new TableModel();
  127. let i, j;
  128. if (this.series.length === 0) {
  129. return table;
  130. }
  131. _.each(this.series, (series: any, seriesIndex: number) => {
  132. if (seriesIndex === 0) {
  133. j = 0;
  134. // Check that the first column is indeed 'time'
  135. if (series.columns[0] === 'time') {
  136. // Push this now before the tags and with the right type
  137. table.columns.push({ text: 'Time', type: FieldType.time });
  138. j++;
  139. }
  140. _.each(_.keys(series.tags), key => {
  141. table.columns.push({ text: key });
  142. });
  143. for (; j < series.columns.length; j++) {
  144. table.columns.push({ text: series.columns[j] });
  145. }
  146. }
  147. if (series.values) {
  148. for (i = 0; i < series.values.length; i++) {
  149. const values = series.values[i];
  150. const reordered = [values[0]];
  151. if (series.tags) {
  152. for (const key in series.tags) {
  153. if (series.tags.hasOwnProperty(key)) {
  154. reordered.push(series.tags[key]);
  155. }
  156. }
  157. }
  158. for (j = 1; j < values.length; j++) {
  159. reordered.push(values[j]);
  160. }
  161. table.rows.push(reordered);
  162. }
  163. }
  164. });
  165. return table;
  166. }
  167. }