@cloudcare/guance-front-tools 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"title":"Redis (非codis) NEW","dashboardExtend":{"groupUnfoldStatus":{"redis server":true}},"main":{"vars":[{"type":"CUSTOM_LIST","datasource":"custom","name":"机房","seq":0,"hide":0,"multiple":false,"includeStar":false,"valueSort":"desc","code":"datacenter","definition":{"value":"new,JQ,Tencent,old","defaultVal":{"label":"new","value":"new"}}},{"type":"PROMQL_QUERY","datasource":"dataflux","name":"集群名称","seq":1,"hide":0,"multiple":false,"includeStar":false,"valueSort":"desc","code":"cluster","definition":{"value":"query_result(count(label_replace(redis_up{datacenter=\"#{datacenter}\",job!~\".*Codis.+\"} , \"Name\", \"#{1}\", \"job\", \"(.+)\") or redis_up{idc=\"#{datacenter}\",job=\"redis\"}) by (Name))","defaultVal":{"label":"base-rediscluster","value":"base-rediscluster"}}},{"type":"PROMQL_QUERY","datasource":"dataflux","name":"DB","seq":2,"hide":0,"multiple":false,"includeStar":false,"valueSort":"desc","code":"db","definition":{"value":"query_result(sum(redis_db_keys{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"} or redis_db_keys{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}) by (db) > 0)","defaultVal":{"label":"db0","value":"db0"}}}],"charts":[{"extend":{"settings":{}},"group":{"name":"default"},"pos":{"x":0,"y":0.5,"h":17.2,"w":24},"name":"超过SLA负载的集群 ","queries":[{"datasource":"dataflux","qtype":"promql","type":"table","query":{"q":" count by (idc,Name) (max(avg(rate(redis_cpu_sys_seconds_total{}[1d]) offset 1d +rate(redis_cpu_user_seconds_total{}[1d]) offset 1d) by (Name,instance,idc)) by (Name,idc) * 100 > 30 or max(1 - avg(irate(node_cpu_seconds_total{mode=\"idle\",role=\"proxy\"}[1d])offset 1d) by (instance,Name,idc)) by (Name,idc) * 100 > 30)","type":"promql"}}],"type":"table"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":2,"h":7.7,"w":4},"name":"节点内存上限","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"avg(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"} or redis_config_maxmemory{idc=~\"#{datacenter}\",Name=\"#{cluster}\"})","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":4,"y":2,"h":7.7,"w":4},"name":"节点数量","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"count(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"} or redis_config_maxmemory{idc=~\"#{datacenter}\",Name=\"#{cluster}\"})","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":8,"y":2,"h":7.7,"w":4},"name":"集群总内存","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"avg(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"}) * sum (redis_instance_info{datacenter=~\"#{datacenter}\",job=\"#{cluster}\",role=\"master\"}) or avg(redis_config_maxmemory{idc=~\"#{datacenter}\",Name=\"#{cluster}\"}) * sum (redis_instance_info{idc=~\"#{datacenter}\",Name=\"#{cluster}\",role=\"master\"})","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"avg(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"}) * count(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"}) / 2","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":2,"h":7.7,"w":4},"name":"集群已用内存","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum(redis_memory_used_bytes{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}) / (sum (redis_instance_info{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"}) / sum (redis_instance_info{datacenter=~\"#{datacenter}\",job=\"#{cluster}\",role=\"master\"}) ) or sum(redis_memory_used_bytes{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}) / (sum (redis_instance_info{idc=~\"#{datacenter}\",Name=\"#{cluster}\"}) / sum (redis_instance_info{idc=~\"#{datacenter}\",Name=\"#{cluster}\",role=\"master\"}) )","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":16,"y":2,"h":7.7,"w":4},"name":"key数量","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum(redis_db_keys{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\", db=~\"#{db}\"}) / (sum (redis_instance_info{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"}) / sum (redis_instance_info{datacenter=~\"#{datacenter}\",job=\"#{cluster}\",role=\"master\"}) ) or sum(redis_db_keys{idc=~\"#{datacenter}\",Name=~\"#{cluster}\", db=~\"#{db}\"}) / (sum (redis_instance_info{idc=~\"#{datacenter}\",Name=\"#{cluster}\"}) / sum (redis_instance_info{idc=~\"#{datacenter}\",Name=\"#{cluster}\",role=\"master\"}) ) ","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":20,"y":2,"h":7.7,"w":4},"name":"集群总内存使用率","queries":[{"datasource":"dataflux","qtype":"promql","type":"gauge","query":{"q":"sum(redis_memory_used_bytes{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}) / (avg(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"}) * count(redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=\"#{cluster}\"})) or sum(redis_memory_used_bytes{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}) / (avg(redis_config_maxmemory{idc=~\"#{datacenter}\",Name=\"#{cluster}\"}) * count(redis_config_maxmemory{idc=~\"#{datacenter}\",Name=\"#{cluster}\"}))","type":"promql"}}],"type":"gauge"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":24.8,"h":15.3,"w":12},"name":"OPS/sec","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_commands_processed_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_commands_processed_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":24.8,"h":15.3,"w":12},"name":"命令执行时间","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"avg(irate(redis_commands_duration_seconds_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])) by (instance) ","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"avg(irate(redis_commands_duration_seconds_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])) by (instance) ","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":40,"h":15.3,"w":12},"name":"slowlog","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"delta(redis_slowlog_last_id{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"delta(redis_slowlog_last_id{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":40,"h":15.3,"w":12},"name":"slowlog detail","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_slowlog{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":55.2,"h":15.3,"w":12},"name":"key 数量","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"sum(redis_db_keys{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\", db=~\"#{db}\"}) by (instance)","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"sum(redis_db_keys{idc=~\"#{datacenter}\",Name=~\"#{cluster}\", db=~\"#{db}\"}) by (instance)","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":55.2,"h":15.3,"w":12},"name":"key 设置ttl的百分比","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"sum(redis_db_keys{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\", db=~\"#{db}\"}) by (instance)","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_db_keys_expiring{idc=~\"#{datacenter}\",Name=~\"#{cluster}\", db=~\"#{db}\"}/redis_db_keys{idc=~\"#{datacenter}\",Name=~\"#{cluster}\", db=~\"#{db}\"}\r","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":70.4,"h":15.3,"w":12},"name":"CPU使用率(多线程最大400%)","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"rate(redis_cpu_sys_seconds_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m]) + rate(redis_cpu_user_seconds_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":70.4,"h":15.3,"w":12},"name":"redis内存使用率","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_memory_used_bytes{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"} / redis_config_maxmemory{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_memory_used_bytes{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"} / redis_config_maxmemory{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":85.6,"h":15.3,"w":12},"name":"redis 网络io","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_net_input_bytes_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"1 - irate(redis_net_output_bytes_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_net_input_bytes_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"1 - irate(redis_net_output_bytes_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":85.6,"h":15.3,"w":12},"name":"命中率","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_keyspace_hits_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m]) / irate(redis_commands_processed_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_keyspace_hits_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m]) / irate(redis_commands_processed_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":100.8,"h":15.3,"w":12},"name":"key过期","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"increase(redis_expired_keys_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[1m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"increase(redis_expired_keys_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[1m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":100.8,"h":15.3,"w":12},"name":"连接数使用率","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_connected_clients{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"} / redis_config_maxclients{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_connected_clients{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"} / redis_config_maxclients{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":116,"h":15.3,"w":12},"name":"redis_memory_used_bytes(key所占用内存)","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_memory_used_bytes{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_memory_used_bytes{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":116,"h":15.3,"w":12},"name":"key驱逐","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_evicted_keys_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m])","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_evicted_keys_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m])","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":131.2,"h":15.3,"w":12},"name":"redis_memory_used_rss_bytes(redis实际使用内存)","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_memory_used_rss_bytes{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_memory_used_rss_bytes{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":131.2,"h":15.3,"w":12},"name":"命令执行时间","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_commands_duration_seconds_total{datacenter=~\"#{datacenter}\",job=~\"#{cluster}\"}[5m]) ","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"irate(redis_commands_duration_seconds_total{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}[5m]) ","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":146.4,"h":15.3,"w":12},"name":"keyprefixes memory ","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_keyprefixes_mem{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":146.4,"h":15.3,"w":12},"name":"主从延迟","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_connected_slave_lag_seconds{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":0,"y":161.6,"h":15.3,"w":12},"name":"keyprefixes number","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_keyprefixes_num{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":161.6,"h":15.3,"w":12},"name":"hotkey detail","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_hotkey{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"redis server"},"pos":{"x":12,"y":176.8,"h":15.3,"w":12},"name":"bigkey detail","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"redis_bigkey{idc=~\"#{datacenter}\",Name=~\"#{cluster}\"}","type":"promql"}}],"type":"sequence"}],"groups":[{"name":"redis server"}]}}
@@ -60,8 +60,10 @@ import yargs from 'yargs';
60
60
  // | 'iframe'
61
61
  const grafanaPanelTypeToGuanceChartMap = {
62
62
  stat: 'singlestat',
63
+ singlestat: 'singlestat',
63
64
  barchart: 'bar',
64
65
  timeseries: 'sequence',
66
+ graph: 'sequence',
65
67
  piechart: 'pie',
66
68
  histogram: 'histogram',
67
69
  bargauge: 'toplist',
@@ -71,8 +73,11 @@ const grafanaPanelTypeToGuanceChartMap = {
71
73
  heatmap: 'heatmap',
72
74
  treemap: 'treemap',
73
75
  };
76
+ const GRAFANA_KEYWORKD = ['__interval'];
74
77
  function replaceVariableStr(grafanaExpr) {
75
78
  return grafanaExpr.replace(/\$([\d_\w]+)/g, (match, $0) => {
79
+ if (GRAFANA_KEYWORKD.includes($0))
80
+ return match;
76
81
  return `#{${$0}}`;
77
82
  });
78
83
  }
@@ -259,18 +264,28 @@ const covert = (grafanaData) => {
259
264
  value: values.join(','),
260
265
  };
261
266
  }
267
+ let value = _variable.query;
268
+ if (value && typeof value === 'object' && value.query) {
269
+ value = replaceVariableStr(value.query);
270
+ }
271
+ else if (value && typeof value === 'string') {
272
+ value = replaceVariableStr(_variable.query);
273
+ }
274
+ else {
275
+ return;
276
+ }
262
277
  const guanceVariableItem = {
263
278
  type: VARIABLE_MAP[type],
264
279
  datasource: VARIABLE_DATASOURCE_MAP[type],
265
280
  name: _variable.label,
266
281
  seq: index,
267
282
  hide: _variable.hide ? 1 : 0,
268
- multiple: _variable.multi,
269
- includeStar: _variable.includeAll,
283
+ multiple: _variable.multi !== undefined ? _variable.multi : true,
284
+ includeStar: _variable.includeAll !== undefined ? _variable.includeAll : true,
270
285
  valueSort: 'desc',
271
286
  code: _variable.name,
272
287
  definition: {
273
- value: replaceVariableStr(_variable.query),
288
+ value: value,
274
289
  defaultVal: defaultVal,
275
290
  },
276
291
  };
@@ -358,6 +373,11 @@ export function run(args) {
358
373
  try {
359
374
  const grafanaJSONData = JSON.parse(fs.readFileSync(grafanaJsonPath, 'utf-8'));
360
375
  const covertResult = covert(grafanaJSONData);
376
+ // 确保目录存在
377
+ const dir = path.dirname(outGuanceJsonPath);
378
+ if (!fs.existsSync(dir)) {
379
+ fs.mkdirSync(dir, { recursive: true }); // recursive: true 确保递归创建目录
380
+ }
361
381
  fs.writeFileSync(outGuanceJsonPath, JSON.stringify(covertResult), 'utf-8');
362
382
  }
363
383
  catch (err) {
@@ -64,8 +64,10 @@ import type { DashboardData as GrafanaDashboardType, VariableModel, Panel, RowPa
64
64
  // | 'iframe'
65
65
  const grafanaPanelTypeToGuanceChartMap: { [key: string]: GuanceChartType } = {
66
66
  stat: 'singlestat',
67
+ singlestat: 'singlestat',
67
68
  barchart: 'bar',
68
69
  timeseries: 'sequence',
70
+ graph: 'sequence',
69
71
  piechart: 'pie',
70
72
  histogram: 'histogram',
71
73
  bargauge: 'toplist',
@@ -75,9 +77,10 @@ const grafanaPanelTypeToGuanceChartMap: { [key: string]: GuanceChartType } = {
75
77
  heatmap: 'heatmap',
76
78
  treemap: 'treemap',
77
79
  }
78
-
80
+ const GRAFANA_KEYWORKD = ['__interval']
79
81
  function replaceVariableStr(grafanaExpr: string): string {
80
82
  return grafanaExpr.replace(/\$([\d_\w]+)/g, (match, $0) => {
83
+ if (GRAFANA_KEYWORKD.includes($0)) return match
81
84
  return `#{${$0}}`
82
85
  })
83
86
  }
@@ -257,18 +260,26 @@ const covert = (grafanaData: GrafanaDashboardType): GuanceDashboardType => {
257
260
  value: values.join(','),
258
261
  }
259
262
  }
263
+ let value = _variable.query
264
+ if (value && typeof value === 'object' && value.query) {
265
+ value = replaceVariableStr(value.query as string)
266
+ } else if (value && typeof value === 'string') {
267
+ value = replaceVariableStr(_variable.query as string)
268
+ } else {
269
+ return
270
+ }
260
271
  const guanceVariableItem: ChartVarsItem = {
261
272
  type: VARIABLE_MAP[type],
262
273
  datasource: VARIABLE_DATASOURCE_MAP[type],
263
274
  name: _variable.label,
264
275
  seq: index,
265
276
  hide: _variable.hide ? 1 : 0,
266
- multiple: _variable.multi,
267
- includeStar: _variable.includeAll,
277
+ multiple: _variable.multi !== undefined ? _variable.multi : true,
278
+ includeStar: _variable.includeAll !== undefined ? _variable.includeAll : true,
268
279
  valueSort: 'desc',
269
280
  code: _variable.name,
270
281
  definition: {
271
- value: replaceVariableStr(_variable.query as string),
282
+ value: value,
272
283
  defaultVal: defaultVal,
273
284
  },
274
285
  }
@@ -367,6 +378,11 @@ export async function run(args) {
367
378
  try {
368
379
  const grafanaJSONData = JSON.parse(fs.readFileSync(grafanaJsonPath, 'utf-8'))
369
380
  const covertResult = covert(grafanaJSONData)
381
+ // 确保目录存在
382
+ const dir = path.dirname(outGuanceJsonPath)
383
+ if (!fs.existsSync(dir)) {
384
+ fs.mkdirSync(dir, { recursive: true }) // recursive: true 确保递归创建目录
385
+ }
370
386
  fs.writeFileSync(outGuanceJsonPath, JSON.stringify(covertResult), 'utf-8')
371
387
  } catch (err) {
372
388
  throw new Error(err)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcare/guance-front-tools",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,7 +23,8 @@
23
23
  "clean": "rm -rf ./lib/generated && rm -rf ./lib/esm && rm -rf ./lib/cjs",
24
24
  "generate": "node scripts/generate.mjs",
25
25
  "format": "prettier -c .",
26
- "validate": "node scripts/validate.mjs"
26
+ "validate": "node scripts/validate.mjs",
27
+ "prepare": "npm run build"
27
28
  },
28
29
  "devDependencies": {
29
30
  "ajv": "8.11.0",
package/test/xx.json ADDED
@@ -0,0 +1 @@
1
+ {"title":"SHOWCASE: Loki NGINX Service Mesh - JSON version","dashboardExtend":{"groupUnfoldStatus":{"WELCOME TO GRAFANA PLAY!":true,"KPI's":true,"Request statistics over time":true,"Acquisition and Behaviour":false}},"main":{"vars":[{"type":"PROMQL_QUERY","datasource":"dataflux","name":"Label Name","seq":1,"hide":0,"multiple":true,"includeStar":false,"valueSort":"desc","code":"label_name","definition":{"value":"label_names()","defaultVal":{"label":"","value":""}}},{"type":"PROMQL_QUERY","datasource":"dataflux","name":"Label Value","seq":2,"hide":0,"multiple":true,"includeStar":true,"valueSort":"desc","code":"label_value","definition":{"value":"label_values(#{label_name})","defaultVal":{"label":"all values","value":"__all__"}}},{"type":"PROMQL_QUERY","datasource":"dataflux","name":"Job","seq":3,"hide":0,"multiple":true,"includeStar":true,"valueSort":"desc","code":"job","definition":{"value":"label_values({#{label_name}=~\"#{label_value}\"}, job)","defaultVal":{"label":"*","value":"*"}}},{"type":"PROMQL_QUERY","datasource":"dataflux","name":"Instance","seq":4,"hide":0,"multiple":true,"includeStar":true,"valueSort":"desc","code":"instance","definition":{"value":"label_values({#{label_name}=~\"#{label_value}\"}, instance)","defaultVal":{"label":"*","value":"*"}}},{"type":"CUSTOM_LIST","datasource":"custom","name":"query1","seq":5,"hide":0,"multiple":true,"includeStar":true,"valueSort":"desc","code":"query0","definition":{"value":"key:value","defaultVal":{"label":"key:value","value":"key:value"}}}],"charts":[{"extend":{"settings":{}},"group":{"name":"WELCOME TO GRAFANA PLAY!"},"pos":{"x":0,"y":2,"h":15.3,"w":6},"name":"","queries":[{"query":{"content":"![foo](https://grafana.com/about/events/grafanacon/assets/2023/graphic-golden-grot2.svg)\n"}}],"type":"text"},{"extend":{"settings":{}},"group":{"name":"WELCOME TO GRAFANA PLAY!"},"pos":{"x":0,"y":17.2,"h":5.8,"w":9},"name":"","queries":[{"query":{"content":"# THE DASHBOARD SHOWCASE FOR JULY, 2023:\n\n## The [Loki NGINX Service Mesh](https://play.grafana.org/d/T512JVH7z/loki-nginx-service-mesh-json-version?orgId=1), by [Ward Bekker](https://twitter.com/i/flow/login?redirect_after_login=%2Fwardbekker). 👇"}}],"type":"text"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":0,"y":2,"h":7.7,"w":5},"name":"Total requests ","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum by(host) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"}[$__interval])) ","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":5,"y":2,"h":15.3,"w":7},"name":"Requests per status code","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum by (status) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | __error__=\"\" [$__interval]))","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":12,"y":2,"h":7.7,"w":3},"name":"NGINX logs in bytes","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"bytes_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"}[$__interval])","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":15,"y":2,"h":7.7,"w":3},"name":"% of 5xx requests ","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum(count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | status >= 500 |__error__=\"\"[$__interval])) / (sum(count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | __error__=\"\"[$__interval]))/ 100)","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":18,"y":2,"h":7.7,"w":6},"name":"","queries":[{"query":{"content":"📊 Dashboard created by Ward Bekker (hope you like it!)\n\n🐦 Follow me on [Twitter](https://twitter.com/wardbekker) & [LinkedIn](https://www.linkedin.com/in/wardbekker/) for Grafana Loki updates \n\n🎥 Check out my [Grafana Loki video's](https://www.youtube.com/playlist?list=PLDGkOdUX1UjqEzcxQrbROMy8DN7MZv_h4) on Youtube"}}],"type":"text"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":0,"y":9.6,"h":7.7,"w":5},"name":"Realtime visitors ","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"count(sum by (remote_addr) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | __error__=\"\" [$__interval])))","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":12,"y":9.6,"h":7.7,"w":3},"name":"# NGINX log lines","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"}[$__interval])","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":15,"y":9.6,"h":7.7,"w":3},"name":"Total Bytes Sent","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum by (host) (sum_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | unwrap body_bytes_sent | __error__=\"\" [$__interval]))","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":18,"y":9.6,"h":7.7,"w":6},"name":"% of requests by Googlebot","queries":[{"datasource":"dataflux","qtype":"promql","type":"singlestat","query":{"q":"sum(count_over_time(({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} |= \"Googlebot\")[$__interval])) / (sum(count_over_time(({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} != \"Googlebot\")[$__interval])) / 100)","type":"promql"}}],"type":"singlestat"},{"extend":{"settings":{}},"group":{"name":"KPI's"},"pos":{"x":12,"y":17.2,"h":21,"w":3},"name":"Top Countries","queries":[{"datasource":"dataflux","qtype":"promql","type":"table","query":{"q":"topk(10, sum by (geoip_country_code) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | geoip_country_code != \"\" and __error__=\"\" [$__interval])))","type":"promql"}}],"type":"table"},{"extend":{"settings":{}},"group":{"name":"Request statistics over time"},"pos":{"x":0,"y":2,"h":17.2,"w":8},"name":"95th percentile of Request Time","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"quantile_over_time(0.95,{#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | unwrap request_time | __error__=\"\" [$__interval]) by (host)","type":"promql"}},{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"max by (host) (max_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | unwrap request_time | __error__=\"\" [$__interval]))","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"Request statistics over time"},"pos":{"x":8,"y":2,"h":17.2,"w":8},"name":"HTTP status codes over time","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"sum by (status) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | __error__=\"\" [$__interval]))","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"Request statistics over time"},"pos":{"x":16,"y":2,"h":17.2,"w":8},"name":"Bytes Sent","queries":[{"datasource":"dataflux","qtype":"promql","type":"sequence","query":{"q":"sum by (host) (sum_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | status=200 | unwrap body_bytes_sent | __error__=\"\" [$__interval]))","type":"promql"}}],"type":"sequence"},{"extend":{"settings":{}},"group":{"name":"Acquisition and Behaviour"},"pos":{"x":0,"y":70.4,"h":11.5,"w":9},"name":"Top 10 HTTP Referers","queries":[{"datasource":"dataflux","qtype":"promql","type":"table","query":{"q":"topk(10, sum by (http_referer) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | http_referer != \"\" and http_referer !~ \".*?#{host}.*?\" and http_referer !~ \".*?\\\\*\\\\*\\\\*.*?\" | __error__=\"\" [15m])))","type":"promql"}}],"type":"table"},{"extend":{"settings":{}},"group":{"name":"Acquisition and Behaviour"},"pos":{"x":9,"y":70.4,"h":11.5,"w":15},"name":"Top 10 User Agents","queries":[{"datasource":"dataflux","qtype":"promql","type":"table","query":{"q":"topk(10, sum by (http_user_agent) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | __error__=\"\" [15m])))","type":"promql"}}],"type":"table"},{"extend":{"settings":{}},"group":{"name":"Acquisition and Behaviour"},"pos":{"x":0,"y":81.8,"h":15.3,"w":9},"name":"Top 10 visitor IPs","queries":[{"datasource":"dataflux","qtype":"promql","type":"table","query":{"q":"topk(10, sum by (remote_addr, geoip_country_code) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} | json | __error__=\"\" [15m])))","type":"promql"}}],"type":"table"},{"extend":{"settings":{}},"group":{"name":"Acquisition and Behaviour"},"pos":{"x":9,"y":81.8,"h":15.3,"w":15},"name":"Top 10 Requested Pages","queries":[{"datasource":"dataflux","qtype":"promql","type":"table","query":{"q":"topk(10, sum by (request_uri) (count_over_time({#{label_name}=~\"#{label_value}\", job=~\"#{job}\", instance=~\"#{instance}\"} !~ `\\.ico|\\.svg|\\.css|\\.png|\\.txt|\\.js|\\.xml` | json | status = 200 and request_uri != \"/\" | __error__=\"\" [15m])))","type":"promql"}}],"type":"table"}],"groups":[{"name":"WELCOME TO GRAFANA PLAY!"},{"name":"KPI's"},{"name":"Request statistics over time"},{"name":"Acquisition and Behaviour"}]}}