impl: 添加一个数据测试工具(rition-testsuite,用于从测试数据中模拟数据上传情况) doc: 补充建表sql todo: 前端面板立项main
@ -0,0 +1,103 @@ |
||||
/* |
||||
Navicat Premium Data Transfer |
||||
|
||||
Source Server : mysql |
||||
Source Server Type : MySQL |
||||
Source Server Version : 80027 (8.0.27) |
||||
Source Host : 127.0.0.1:3306 |
||||
Source Schema : rition |
||||
|
||||
Target Server Type : MySQL |
||||
Target Server Version : 80027 (8.0.27) |
||||
File Encoding : 65001 |
||||
|
||||
Date: 08/05/2024 10:15:09 |
||||
*/ |
||||
|
||||
SET NAMES utf8mb4; |
||||
SET FOREIGN_KEY_CHECKS = 0; |
||||
|
||||
-- ---------------------------- |
||||
-- Table structure for alert |
||||
-- ---------------------------- |
||||
DROP TABLE IF EXISTS `alert`; |
||||
CREATE TABLE `alert` ( |
||||
`id` bigint NOT NULL, |
||||
`instance_id` varchar(64) NOT NULL COMMENT '出现警告的实例id', |
||||
`rule` bigint NOT NULL COMMENT '触发的规则', |
||||
`time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '警告出现的时间', |
||||
`status` tinyint NOT NULL DEFAULT '0', |
||||
PRIMARY KEY (`id`), |
||||
KEY `idx_instance` (`instance_id`), |
||||
KEY `idx_rule` (`rule`) |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |
||||
|
||||
-- ---------------------------- |
||||
-- Table structure for contract |
||||
-- ---------------------------- |
||||
DROP TABLE IF EXISTS `contract`; |
||||
CREATE TABLE `contract` ( |
||||
`id` bigint NOT NULL, |
||||
`instance_id` varchar(64) NOT NULL COMMENT '绑定的实例', |
||||
`contract` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '联系方式', |
||||
`type` tinyint NOT NULL COMMENT '联系方式类型', |
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
`status` tinyint NOT NULL DEFAULT '0', |
||||
PRIMARY KEY (`id`), |
||||
KEY `idx_id` (`id`), |
||||
KEY `idx_instance` (`instance_id`) |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |
||||
|
||||
-- ---------------------------- |
||||
-- Table structure for ecs |
||||
-- ---------------------------- |
||||
DROP TABLE IF EXISTS `ecs`; |
||||
CREATE TABLE `ecs` ( |
||||
`id` varchar(128) NOT NULL COMMENT '实例id', |
||||
`name` varchar(255) NOT NULL COMMENT '主机名称', |
||||
`ip` varchar(15) NOT NULL COMMENT '主机绑定分配的ip', |
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
`status` tinyint NOT NULL DEFAULT '0', |
||||
PRIMARY KEY (`id`), |
||||
KEY `idx_id` (`id`), |
||||
KEY `idx_ip` (`ip`) |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |
||||
|
||||
-- ---------------------------- |
||||
-- Table structure for record |
||||
-- ---------------------------- |
||||
DROP TABLE IF EXISTS `record`; |
||||
CREATE TABLE `record` ( |
||||
`id` bigint NOT NULL, |
||||
`instance_id` varchar(64) NOT NULL COMMENT '实例id', |
||||
`metric_data` json NOT NULL COMMENT '监控指标值,使用json格式存储', |
||||
`time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '数据时间', |
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
`status` tinyint NOT NULL DEFAULT '0', |
||||
PRIMARY KEY (`id`), |
||||
KEY `idx_id` (`id`), |
||||
KEY `idx_time` (`time`) |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |
||||
|
||||
-- ---------------------------- |
||||
-- Table structure for rule |
||||
-- ---------------------------- |
||||
DROP TABLE IF EXISTS `rule`; |
||||
CREATE TABLE `rule` ( |
||||
`id` bigint NOT NULL COMMENT '规则id', |
||||
`instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '规则对应的实例id', |
||||
`expression` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '需要计算的指标项或者表达式', |
||||
`condition` tinyint NOT NULL COMMENT '触发条件', |
||||
`threshold` varchar(32) NOT NULL COMMENT '阈值', |
||||
`trigger` tinyint NOT NULL COMMENT '触发方法,实时计算或定时计算', |
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '规则描述', |
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
`status` tinyint NOT NULL DEFAULT '0', |
||||
PRIMARY KEY (`id`), |
||||
KEY `idx_instance` (`instance_id`) |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1; |
@ -0,0 +1,13 @@ |
||||
package rition.backend.api.v1.dto.request; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class MetricDataRequest { |
||||
private String instanceId; |
||||
private Long start; |
||||
private Long end; |
||||
private List<String> metricItems; |
||||
} |
@ -0,0 +1,18 @@ |
||||
package rition.backend.api.v1.panel; |
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestBody; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import rition.backend.api.v1.dto.request.MetricDataRequest; |
||||
import rition.backend.api.v1.dto.response.Response; |
||||
|
||||
@RestController |
||||
@RequestMapping("/panel/metrics") |
||||
public class MetricsViewController { |
||||
|
||||
@GetMapping("/list") |
||||
public Response<Object> getMetrics(@RequestBody MetricDataRequest metricDataRequest) { |
||||
return Response.success(); |
||||
} |
||||
} |
@ -0,0 +1,10 @@ |
||||
package rition.backend.api.v1.panel; |
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
@RestController |
||||
@RequestMapping("/panel") |
||||
public class PanelController { |
||||
|
||||
} |
@ -1,4 +1,18 @@ |
||||
package rition.service.monitor; |
||||
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecord; |
||||
import org.springframework.kafka.annotation.KafkaListener; |
||||
import org.springframework.stereotype.Service; |
||||
import rition.common.data.dto.MetricDataDto; |
||||
|
||||
@Service |
||||
public class MonitorService { |
||||
|
||||
@KafkaListener( |
||||
topics = {"${rition.kafka.data-collecting.topic}"}, |
||||
groupId = "${rition.kafka.data-collecting.group}" |
||||
) |
||||
public void processMetricData(ConsumerRecord<String, MetricDataDto> metricDataConsumerRecord) { |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,25 @@ |
||||
package rition.service.monitor.configure; |
||||
|
||||
import lombok.Data; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
@Data |
||||
@Configuration |
||||
@ConfigurationProperties("rition.kafka") |
||||
public class MonitorServiceKafkaConfigure { |
||||
private DataCollectingKafkaConfig dataCollecting; |
||||
private AlertMessageKafkaConfig alertMessageKafkaConfig; |
||||
|
||||
@Data |
||||
public static class DataCollectingKafkaConfig { |
||||
private String topic; |
||||
private String group; |
||||
} |
||||
|
||||
@Data |
||||
public static class AlertMessageKafkaConfig { |
||||
private String topic; |
||||
private String group; |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
spring: |
||||
datasource: |
||||
driver-class-name: com.mysql.cj.jdbc.Driver |
||||
url: jdbc:mysql://127.0.0.1:3306/rition?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true |
||||
username: root |
||||
password: Test2333! |
||||
kafka: |
||||
bootstrap-servers: '127.0.0.1:9092' |
||||
consumer: |
||||
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer |
||||
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer |
||||
properties: |
||||
spring: |
||||
json: |
||||
trusted: |
||||
packages: "rition.common.data.dto" |
||||
producer: |
||||
retries: 4 |
||||
compression-type: zstd |
||||
key-serializer: org.apache.kafka.common.serialization.StringSerializer |
||||
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer |
||||
acks: 1 |
||||
properties: |
||||
linger: |
||||
ms: 200 |
||||
|
||||
rition: |
||||
kafka: |
||||
data-collecting: |
||||
topic: 'ecs-metric-data-topic' |
||||
group: 'ecs-metric-data-group' |
@ -0,0 +1,23 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<parent> |
||||
<groupId>net.rition</groupId> |
||||
<artifactId>service</artifactId> |
||||
<version>${revision}</version> |
||||
</parent> |
||||
|
||||
<artifactId>panel</artifactId> |
||||
|
||||
<properties> |
||||
<maven.compiler.source>17</maven.compiler.source> |
||||
<maven.compiler.target>17</maven.compiler.target> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
|
||||
</dependencies> |
||||
</project> |
@ -0,0 +1,7 @@ |
||||
package rition.service.panel; |
||||
|
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Service |
||||
public class PanelService { |
||||
} |
@ -0,0 +1,9 @@ |
||||
root = true |
||||
|
||||
[*] |
||||
charset = utf-8 |
||||
indent_style = space |
||||
indent_size = 2 |
||||
end_of_line = lf |
||||
insert_final_newline = true |
||||
trim_trailing_whitespace = true |
@ -0,0 +1,7 @@ |
||||
/dist |
||||
/src-capacitor |
||||
/src-cordova |
||||
/.quasar |
||||
/node_modules |
||||
.eslintrc.cjs |
||||
/quasar.config.*.temporary.compiled* |
@ -0,0 +1,65 @@ |
||||
module.exports = { |
||||
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy |
||||
// This option interrupts the configuration hierarchy at this file |
||||
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos) |
||||
root: true, |
||||
|
||||
parserOptions: { |
||||
ecmaVersion: 2021, // Allows for the parsing of modern ECMAScript features |
||||
}, |
||||
|
||||
env: { |
||||
node: true, |
||||
browser: true |
||||
}, |
||||
|
||||
// Rules order is important, please avoid shuffling them |
||||
extends: [ |
||||
// Base ESLint recommended rules |
||||
// 'eslint:recommended', |
||||
|
||||
// Uncomment any of the lines below to choose desired strictness, |
||||
// but leave only one uncommented! |
||||
// See https://eslint.vuejs.org/rules/#available-rules |
||||
'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention) |
||||
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) |
||||
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) |
||||
|
||||
// https://github.com/prettier/eslint-config-prettier#installation |
||||
// usage with Prettier, provided by 'eslint-config-prettier'. |
||||
'prettier' |
||||
], |
||||
|
||||
plugins: [ |
||||
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files |
||||
// required to lint *.vue files |
||||
'vue', |
||||
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674 |
||||
// Prettier has not been included as plugin to avoid performance impact |
||||
// add it as an extension for your IDE |
||||
|
||||
], |
||||
|
||||
globals: { |
||||
ga: 'readonly', // Google Analytics |
||||
cordova: 'readonly', |
||||
__statics: 'readonly', |
||||
__QUASAR_SSR__: 'readonly', |
||||
__QUASAR_SSR_SERVER__: 'readonly', |
||||
__QUASAR_SSR_CLIENT__: 'readonly', |
||||
__QUASAR_SSR_PWA__: 'readonly', |
||||
process: 'readonly', |
||||
Capacitor: 'readonly', |
||||
chrome: 'readonly' |
||||
}, |
||||
|
||||
// add your custom rules here |
||||
rules: { |
||||
|
||||
'prefer-promise-reject-errors': 'off', |
||||
|
||||
// allow debugger during development only |
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' |
||||
} |
||||
} |
@ -1,24 +1,33 @@ |
||||
# Logs |
||||
logs |
||||
*.log |
||||
.DS_Store |
||||
.thumbs.db |
||||
node_modules |
||||
|
||||
# Quasar core related directories |
||||
.quasar |
||||
/dist |
||||
/quasar.config.*.temporary.compiled* |
||||
|
||||
# Cordova related directories and files |
||||
/src-cordova/node_modules |
||||
/src-cordova/platforms |
||||
/src-cordova/plugins |
||||
/src-cordova/www |
||||
|
||||
# Capacitor related directories and files |
||||
/src-capacitor/www |
||||
/src-capacitor/node_modules |
||||
|
||||
# Log files |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
pnpm-debug.log* |
||||
lerna-debug.log* |
||||
|
||||
node_modules |
||||
dist |
||||
dist-ssr |
||||
*.local |
||||
|
||||
# Editor directories and files |
||||
.vscode/* |
||||
!.vscode/extensions.json |
||||
.idea |
||||
.DS_Store |
||||
*.suo |
||||
*.ntvs* |
||||
*.njsproj |
||||
*.sln |
||||
*.sw? |
||||
|
||||
# local .env files |
||||
.env.local* |
||||
|
@ -0,0 +1,5 @@ |
||||
# pnpm-related options |
||||
shamefully-hoist=true |
||||
strict-peer-dependencies=false |
||||
# to get the latest compatible packages when creating the project https://github.com/pnpm/pnpm/issues/6463 |
||||
resolution-mode=highest |
@ -1,3 +1,3 @@ |
||||
# rition-panel |
||||
# RitionPanel |
||||
|
||||
rition的面板 |
||||
Panel of Rition project |
||||
|
@ -1,13 +1,21 @@ |
||||
<!doctype html> |
||||
<html lang="en"> |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="UTF-8" /> |
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||
<title>Vite + Vue</title> |
||||
<title><%= productName %></title> |
||||
|
||||
<meta charset="utf-8"> |
||||
<meta name="description" content="<%= productDescription %>"> |
||||
<meta name="format-detection" content="telephone=no"> |
||||
<meta name="msapplication-tap-highlight" content="no"> |
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>"> |
||||
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="icons/favicon-128x128.png"> |
||||
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png"> |
||||
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png"> |
||||
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png"> |
||||
<link rel="icon" type="image/ico" href="favicon.ico"> |
||||
</head> |
||||
<body> |
||||
<div id="app"></div> |
||||
<script type="module" src="/src/main.js"></script> |
||||
<!-- quasar:entry-point --> |
||||
</body> |
||||
</html> |
||||
|
@ -0,0 +1,39 @@ |
||||
{ |
||||
"compilerOptions": { |
||||
"baseUrl": ".", |
||||
"paths": { |
||||
"src/*": [ |
||||
"src/*" |
||||
], |
||||
"app/*": [ |
||||
"*" |
||||
], |
||||
"components/*": [ |
||||
"src/components/*" |
||||
], |
||||
"layouts/*": [ |
||||
"src/layouts/*" |
||||
], |
||||
"pages/*": [ |
||||
"src/pages/*" |
||||
], |
||||
"assets/*": [ |
||||
"src/assets/*" |
||||
], |
||||
"boot/*": [ |
||||
"src/boot/*" |
||||
], |
||||
"stores/*": [ |
||||
"src/stores/*" |
||||
], |
||||
"vue$": [ |
||||
"node_modules/vue/dist/vue.runtime.esm-bundler.js" |
||||
] |
||||
} |
||||
}, |
||||
"exclude": [ |
||||
"dist", |
||||
".quasar", |
||||
"node_modules" |
||||
] |
||||
} |
@ -1,18 +1,37 @@ |
||||
{ |
||||
"name": "rition-panel", |
||||
"version": "0.0.1", |
||||
"description": "Panel of Rition project", |
||||
"productName": "RitionPanel", |
||||
"author": "lensfrex <lensferno@outlook.com>", |
||||
"private": true, |
||||
"version": "0.0.0", |
||||
"type": "module", |
||||
"scripts": { |
||||
"dev": "vite", |
||||
"build": "vite build", |
||||
"preview": "vite preview" |
||||
"lint": "eslint --ext .js,.vue ./", |
||||
"format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore", |
||||
"test": "echo \"No test specified\" && exit 0", |
||||
"dev": "quasar dev", |
||||
"build": "quasar build" |
||||
}, |
||||
"dependencies": { |
||||
"vue": "^3.4.21" |
||||
"axios": "^1.2.1", |
||||
"@quasar/extras": "^1.16.4", |
||||
"quasar": "^2.16.0", |
||||
"vue": "^3.4.18", |
||||
"vue-router": "^4.0.12" |
||||
}, |
||||
"devDependencies": { |
||||
"@vitejs/plugin-vue": "^5.0.4", |
||||
"vite": "^5.2.0" |
||||
"eslint": "^8.57.0", |
||||
"eslint-plugin-vue": "^9.0.0", |
||||
"vite-plugin-checker": "^0.6.4", |
||||
"eslint-config-prettier": "^8.1.0", |
||||
"prettier": "^2.5.1", |
||||
"@quasar/app-vite": "^1.9.0", |
||||
"autoprefixer": "^10.4.2", |
||||
"postcss": "^8.4.14" |
||||
}, |
||||
"engines": { |
||||
"node": "^20 || ^18 || ^16", |
||||
"npm": ">= 6.13.4", |
||||
"yarn": ">= 1.21.1" |
||||
} |
||||
} |
||||
|
@ -0,0 +1,27 @@ |
||||
/* eslint-disable */ |
||||
// https://github.com/michael-ciniawsky/postcss-load-config |
||||
|
||||
module.exports = { |
||||
plugins: [ |
||||
// https://github.com/postcss/autoprefixer |
||||
require('autoprefixer')({ |
||||
overrideBrowserslist: [ |
||||
'last 4 Chrome versions', |
||||
'last 4 Firefox versions', |
||||
'last 4 Edge versions', |
||||
'last 4 Safari versions', |
||||
'last 4 Android versions', |
||||
'last 4 ChromeAndroid versions', |
||||
'last 4 FirefoxAndroid versions', |
||||
'last 4 iOS versions' |
||||
] |
||||
}) |
||||
|
||||
// https://github.com/elchininet/postcss-rtlcss |
||||
// If you want to support RTL css, then |
||||
// 1. yarn/npm install postcss-rtlcss |
||||
// 2. optionally set quasar.config.js > framework > lang to an RTL language |
||||
// 3. uncomment the following line: |
||||
// require('postcss-rtlcss') |
||||
] |
||||
} |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 859 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,207 @@ |
||||
/* eslint-env node */ |
||||
|
||||
/* |
||||
* This file runs in a Node context (it's NOT transpiled by Babel), so use only |
||||
* the ES6 features that are supported by your Node version. https://node.green/
|
||||
*/ |
||||
|
||||
// Configuration for your app
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
|
||||
|
||||
|
||||
const { configure } = require('quasar/wrappers'); |
||||
|
||||
|
||||
module.exports = configure(function (/* ctx */) { |
||||
return { |
||||
// https://v2.quasar.dev/quasar-cli-vite/prefetch-feature
|
||||
// preFetch: true,
|
||||
|
||||
// app boot file (/src/boot)
|
||||
// --> boot files are part of "main.js"
|
||||
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
||||
boot: [ |
||||
|
||||
'axios', |
||||
], |
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||
css: [ |
||||
'app.scss' |
||||
], |
||||
|
||||
// https://github.com/quasarframework/quasar/tree/dev/extras
|
||||
extras: [ |
||||
// 'ionicons-v4',
|
||||
// 'mdi-v7',
|
||||
// 'fontawesome-v6',
|
||||
// 'eva-icons',
|
||||
// 'themify',
|
||||
// 'line-awesome',
|
||||
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
|
||||
|
||||
'roboto-font', // optional, you are not bound to it
|
||||
'material-icons', // optional, you are not bound to it
|
||||
], |
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
|
||||
build: { |
||||
target: { |
||||
browser: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ], |
||||
node: 'node20' |
||||
}, |
||||
|
||||
vueRouterMode: 'hash', // available values: 'hash', 'history'
|
||||
// vueRouterBase,
|
||||
// vueDevtools,
|
||||
// vueOptionsAPI: false,
|
||||
|
||||
// rebuildCache: true, // rebuilds Vite/linter/etc cache on startup
|
||||
|
||||
// publicPath: '/',
|
||||
// analyze: true,
|
||||
// env: {},
|
||||
// rawDefine: {}
|
||||
// ignorePublicFolder: true,
|
||||
// minify: false,
|
||||
// polyfillModulePreload: true,
|
||||
// distDir
|
||||
|
||||
// extendViteConf (viteConf) {},
|
||||
// viteVuePluginOptions: {},
|
||||
|
||||
vitePlugins: [ |
||||
['vite-plugin-checker', { |
||||
eslint: { |
||||
lintCommand: 'eslint "./**/*.{js,mjs,cjs,vue}"' |
||||
} |
||||
}, { server: false }] |
||||
] |
||||
}, |
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
|
||||
devServer: { |
||||
// https: true
|
||||
open: true // opens browser window automatically
|
||||
}, |
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
|
||||
framework: { |
||||
config: {}, |
||||
|
||||
// iconSet: 'material-icons', // Quasar icon set
|
||||
// lang: 'en-US', // Quasar language pack
|
||||
|
||||
// For special cases outside of where the auto-import strategy can have an impact
|
||||
// (like functional components as one of the examples),
|
||||
// you can manually specify Quasar components/directives to be available everywhere:
|
||||
//
|
||||
// components: [],
|
||||
// directives: [],
|
||||
|
||||
// Quasar plugins
|
||||
plugins: [] |
||||
}, |
||||
|
||||
// animations: 'all', // --- includes all animations
|
||||
// https://v2.quasar.dev/options/animations
|
||||
animations: [], |
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#property-sourcefiles
|
||||
// sourceFiles: {
|
||||
// rootComponent: 'src/App.vue',
|
||||
// router: 'src/router/index',
|
||||
// store: 'src/store/index',
|
||||
// registerServiceWorker: 'src-pwa/register-service-worker',
|
||||
// serviceWorker: 'src-pwa/custom-service-worker',
|
||||
// pwaManifestFile: 'src-pwa/manifest.json',
|
||||
// electronMain: 'src-electron/electron-main',
|
||||
// electronPreload: 'src-electron/electron-preload'
|
||||
// },
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr
|
||||
ssr: { |
||||
// ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name!
|
||||
// will mess up SSR
|
||||
|
||||
// extendSSRWebserverConf (esbuildConf) {},
|
||||
// extendPackageJson (json) {},
|
||||
|
||||
pwa: false, |
||||
|
||||
// manualStoreHydration: true,
|
||||
// manualPostHydrationTrigger: true,
|
||||
|
||||
prodPort: 3000, // The default port that the production server should use
|
||||
// (gets superseded if process.env.PORT is specified at runtime)
|
||||
|
||||
middlewares: [ |
||||
'render' // keep this as last one
|
||||
] |
||||
}, |
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa
|
||||
pwa: { |
||||
workboxMode: 'generateSW', // or 'injectManifest'
|
||||
injectPwaMetaTags: true, |
||||
swFilename: 'sw.js', |
||||
manifestFilename: 'manifest.json', |
||||
useCredentialsForManifestTag: false, |
||||
// useFilenameHashes: true,
|
||||
// extendGenerateSWOptions (cfg) {}
|
||||
// extendInjectManifestOptions (cfg) {},
|
||||
// extendManifestJson (json) {}
|
||||
// extendPWACustomSWConf (esbuildConf) {}
|
||||
}, |
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova
|
||||
cordova: { |
||||
// noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
|
||||
}, |
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor
|
||||
capacitor: { |
||||
hideSplashscreen: true |
||||
}, |
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron
|
||||
electron: { |
||||
// extendElectronMainConf (esbuildConf)
|
||||
// extendElectronPreloadConf (esbuildConf)
|
||||
|
||||
// specify the debugging port to use for the Electron app when running in development mode
|
||||
inspectPort: 5858, |
||||
|
||||
bundler: 'packager', // 'packager' or 'builder'
|
||||
|
||||
packager: { |
||||
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
|
||||
|
||||
// OS X / Mac App Store
|
||||
// appBundleId: '',
|
||||
// appCategoryType: '',
|
||||
// osxSign: '',
|
||||
// protocol: 'myapp://path',
|
||||
|
||||
// Windows only
|
||||
// win32metadata: { ... }
|
||||
}, |
||||
|
||||
builder: { |
||||
// https://www.electron.build/configuration/configuration
|
||||
|
||||
appId: 'rition-panel' |
||||
} |
||||
}, |
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex
|
||||
bex: { |
||||
contentScripts: [ |
||||
'my-content-script' |
||||
], |
||||
|
||||
// extendBexScriptsConf (esbuildConf) {}
|
||||
// extendBexManifestJson (json) {}
|
||||
} |
||||
} |
||||
}); |
@ -1,30 +1,9 @@ |
||||
<script setup> |
||||
import HelloWorld from './components/HelloWorld.vue' |
||||
</script> |
||||
|
||||
<template> |
||||
<div> |
||||
<a href="https://vitejs.dev" target="_blank"> |
||||
<img src="/vite.svg" class="logo" alt="Vite logo" /> |
||||
</a> |
||||
<a href="https://vuejs.org/" target="_blank"> |
||||
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" /> |
||||
</a> |
||||
</div> |
||||
<HelloWorld msg="Vite + Vue" /> |
||||
<router-view /> |
||||
</template> |
||||
|
||||
<style scoped> |
||||
.logo { |
||||
height: 6em; |
||||
padding: 1.5em; |
||||
will-change: filter; |
||||
transition: filter 300ms; |
||||
} |
||||
.logo:hover { |
||||
filter: drop-shadow(0 0 2em #646cffaa); |
||||
} |
||||
.logo.vue:hover { |
||||
filter: drop-shadow(0 0 2em #42b883aa); |
||||
} |
||||
</style> |
||||
<script setup> |
||||
defineOptions({ |
||||
name: 'App' |
||||
}); |
||||
</script> |
||||
|
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 496 B |
@ -0,0 +1,24 @@ |
||||
import { boot } from 'quasar/wrappers' |
||||
import axios from 'axios' |
||||
|
||||
// Be careful when using SSR for cross-request state pollution
|
||||
// due to creating a Singleton instance here;
|
||||
// If any client changes this (global) instance, it might be a
|
||||
// good idea to move this instance creation inside of the
|
||||
// "export default () => {}" function below (which runs individually
|
||||
// for each client)
|
||||
const api = axios.create({ baseURL: 'https://api.example.com' }) |
||||
|
||||
export default boot(({ app }) => { |
||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||
|
||||
app.config.globalProperties.$axios = axios |
||||
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
|
||||
// so you won't necessarily have to import axios in each vue file
|
||||
|
||||
app.config.globalProperties.$api = api |
||||
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
|
||||
// so you can easily perform requests against your app's API
|
||||
}) |
||||
|
||||
export { api } |
@ -0,0 +1,48 @@ |
||||
<template> |
||||
<q-item |
||||
clickable |
||||
tag="a" |
||||
target="_blank" |
||||
:href="props.link" |
||||
> |
||||
<q-item-section |
||||
v-if="props.icon" |
||||
avatar |
||||
> |
||||
<q-icon :name="props.icon" /> |
||||
</q-item-section> |
||||
|
||||
<q-item-section> |
||||
<q-item-label>{{ props.title }}</q-item-label> |
||||
<q-item-label caption>{{ props.caption }}</q-item-label> |
||||
</q-item-section> |
||||
</q-item> |
||||
</template> |
||||
|
||||
<script setup> |
||||
defineOptions({ |
||||
name: 'EssentialLink' |
||||
}) |
||||
|
||||
const props = defineProps({ |
||||
title: { |
||||
type: String, |
||||
required: true |
||||
}, |
||||
|
||||
caption: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
|
||||
link: { |
||||
type: String, |
||||
default: '#' |
||||
}, |
||||
|
||||
icon: { |
||||
type: String, |
||||
default: '' |
||||
} |
||||
}) |
||||
</script> |
@ -1,40 +0,0 @@ |
||||
<script setup> |
||||
import { ref } from 'vue' |
||||
|
||||
defineProps({ |
||||
msg: String, |
||||
}) |
||||
|
||||
const count = ref(0) |
||||
</script> |
||||
|
||||
<template> |
||||
<h1>{{ msg }}</h1> |
||||
|
||||
<div class="card"> |
||||
<button type="button" @click="count++">count is {{ count }}</button> |
||||
<p> |
||||
Edit |
||||
<code>components/HelloWorld.vue</code> to test HMR |
||||
</p> |
||||
</div> |
||||
|
||||
<p> |
||||
Check out |
||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank" |
||||
>create-vue</a |
||||
>, the official Vue + Vite starter |
||||
</p> |
||||
<p> |
||||
Install |
||||
<a href="https://github.com/vuejs/language-tools" target="_blank">Volar</a> |
||||
in your IDE for a better DX |
||||
</p> |
||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p> |
||||
</template> |
||||
|
||||
<style scoped> |
||||
.read-the-docs { |
||||
color: #888; |
||||
} |
||||
</style> |
@ -0,0 +1 @@ |
||||
// app global css in SCSS form |
@ -0,0 +1,25 @@ |
||||
// Quasar SCSS (& Sass) Variables |
||||
// -------------------------------------------------- |
||||
// To customize the look and feel of this app, you can override |
||||
// the Sass/SCSS variables found in Quasar's source Sass/SCSS files. |
||||
|
||||
// Check documentation for full list of Quasar variables |
||||
|
||||
// Your own variables (that are declared here) and Quasar's own |
||||
// ones will be available out of the box in your .vue/.scss/.sass files |
||||
|
||||
// It's highly recommended to change the default colors |
||||
// to match your app's branding. |
||||
// Tip: Use the "Theme Builder" on Quasar's documentation website. |
||||
|
||||
$primary : #1976D2; |
||||
$secondary : #26A69A; |
||||
$accent : #9C27B0; |
||||
|
||||
$dark : #1D1D1D; |
||||
$dark-page : #121212; |
||||
|
||||
$positive : #21BA45; |
||||
$negative : #C10015; |
||||
$info : #31CCEC; |
||||
$warning : #F2C037; |
@ -0,0 +1,106 @@ |
||||
<template> |
||||
<q-layout view="lHh Lpr lFf"> |
||||
<q-header elevated> |
||||
<q-toolbar> |
||||
<q-btn |
||||
flat |
||||
dense |
||||
round |
||||
icon="menu" |
||||
aria-label="Menu" |
||||
@click="toggleLeftDrawer" |
||||
/> |
||||
|
||||
<q-toolbar-title> |
||||
Quasar App |
||||
</q-toolbar-title> |
||||
|
||||
<div>Quasar v{{ $q.version }}</div> |
||||
</q-toolbar> |
||||
</q-header> |
||||
|
||||
<q-drawer |
||||
v-model="leftDrawerOpen" |
||||
show-if-above |
||||
bordered |
||||
> |
||||
<q-list> |
||||
<q-item-label |
||||
header |
||||
> |
||||
Essential Links |
||||
</q-item-label> |
||||
|
||||
<EssentialLink |
||||
v-for="link in linksList" |
||||
:key="link.title" |
||||
v-bind="link" |
||||
/> |
||||
</q-list> |
||||
</q-drawer> |
||||
|
||||
<q-page-container> |
||||
<router-view /> |
||||
</q-page-container> |
||||
</q-layout> |
||||
</template> |
||||
|
||||
<script setup> |
||||
import { ref } from 'vue' |
||||
import EssentialLink from 'components/EssentialLink.vue' |
||||
|
||||
defineOptions({ |
||||
name: 'MainLayout' |
||||
}) |
||||
|
||||
const linksList = [ |
||||
{ |
||||
title: 'Docs', |
||||
caption: 'quasar.dev', |
||||
icon: 'school', |
||||
link: 'https://quasar.dev' |
||||
}, |
||||
{ |
||||
title: 'Github', |
||||
caption: 'github.com/quasarframework', |
||||
icon: 'code', |
||||
link: 'https://github.com/quasarframework' |
||||
}, |
||||
{ |
||||
title: 'Discord Chat Channel', |
||||
caption: 'chat.quasar.dev', |
||||
icon: 'chat', |
||||
link: 'https://chat.quasar.dev' |
||||
}, |
||||
{ |
||||
title: 'Forum', |
||||
caption: 'forum.quasar.dev', |
||||
icon: 'record_voice_over', |
||||
link: 'https://forum.quasar.dev' |
||||
}, |
||||
{ |
||||
title: 'Twitter', |
||||
caption: '@quasarframework', |
||||
icon: 'rss_feed', |
||||
link: 'https://twitter.quasar.dev' |
||||
}, |
||||
{ |
||||
title: 'Facebook', |
||||
caption: '@QuasarFramework', |
||||
icon: 'public', |
||||
link: 'https://facebook.quasar.dev' |
||||
}, |
||||
{ |
||||
title: 'Quasar Awesome', |
||||
caption: 'Community Quasar projects', |
||||
icon: 'favorite', |
||||
link: 'https://awesome.quasar.dev' |
||||
} |
||||
] |
||||
|
||||
const leftDrawerOpen = ref(false) |
||||
|
||||
function toggleLeftDrawer () { |
||||
leftDrawerOpen.value = !leftDrawerOpen.value |
||||
} |
||||
</script> |
@ -1,5 +0,0 @@ |
||||
import { createApp } from 'vue' |
||||
import './style.css' |
||||
import App from './App.vue' |
||||
|
||||
createApp(App).mount('#app') |
@ -0,0 +1,29 @@ |
||||
<template> |
||||
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center"> |
||||
<div> |
||||
<div style="font-size: 30vh"> |
||||
404 |
||||
</div> |
||||
|
||||
<div class="text-h2" style="opacity:.4"> |
||||
Oops. Nothing here... |
||||
</div> |
||||
|
||||
<q-btn |
||||
class="q-mt-xl" |
||||
color="white" |
||||
text-color="blue" |
||||
unelevated |
||||
to="/" |
||||
label="Go Home" |
||||
no-caps |
||||
/> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup> |
||||
defineOptions({ |
||||
name: 'ErrorNotFound' |
||||
}); |
||||
</script> |
@ -0,0 +1,15 @@ |
||||
<template> |
||||
<q-page class="flex flex-center"> |
||||
<img |
||||
alt="Quasar logo" |
||||
src="~assets/quasar-logo-vertical.svg" |
||||
style="width: 200px; height: 200px" |
||||
> |
||||
</q-page> |
||||
</template> |
||||
|
||||
<script setup> |
||||
defineOptions({ |
||||
name: 'IndexPage' |
||||
}); |
||||
</script> |
@ -0,0 +1,30 @@ |
||||
import { route } from 'quasar/wrappers' |
||||
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router' |
||||
import routes from './routes' |
||||
|
||||
/* |
||||
* If not building with SSR mode, you can |
||||
* directly export the Router instantiation; |
||||
* |
||||
* The function below can be async too; either use |
||||
* async/await or return a Promise which resolves |
||||
* with the Router instance. |
||||
*/ |
||||
|
||||
export default route(function (/* { store, ssrContext } */) { |
||||
const createHistory = process.env.SERVER |
||||
? createMemoryHistory |
||||
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory) |
||||
|
||||
const Router = createRouter({ |
||||
scrollBehavior: () => ({ left: 0, top: 0 }), |
||||
routes, |
||||
|
||||
// Leave this as is and make changes in quasar.conf.js instead!
|
||||
// quasar.conf.js -> build -> vueRouterMode
|
||||
// quasar.conf.js -> build -> publicPath
|
||||
history: createHistory(process.env.VUE_ROUTER_BASE) |
||||
}) |
||||
|
||||
return Router |
||||
}) |
@ -0,0 +1,18 @@ |
||||
const routes = [ |
||||
{ |
||||
path: '/', |
||||
component: () => import('layouts/MainLayout.vue'), |
||||
children: [ |
||||
{ path: '', component: () => import('pages/IndexPage.vue') } |
||||
] |
||||
}, |
||||
|
||||
// Always leave this as last one,
|
||||
// but you can also remove it
|
||||
{ |
||||
path: '/:catchAll(.*)*', |
||||
component: () => import('pages/ErrorNotFound.vue') |
||||
} |
||||
] |
||||
|
||||
export default routes |
@ -1,79 +0,0 @@ |
||||
:root { |
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; |
||||
line-height: 1.5; |
||||
font-weight: 400; |
||||
|
||||
color-scheme: light dark; |
||||
color: rgba(255, 255, 255, 0.87); |
||||
background-color: #242424; |
||||
|
||||
font-synthesis: none; |
||||
text-rendering: optimizeLegibility; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
a { |
||||
font-weight: 500; |
||||
color: #646cff; |
||||
text-decoration: inherit; |
||||
} |
||||
a:hover { |
||||
color: #535bf2; |
||||
} |
||||
|
||||
body { |
||||
margin: 0; |
||||
display: flex; |
||||
place-items: center; |
||||
min-width: 320px; |
||||
min-height: 100vh; |
||||
} |
||||
|
||||
h1 { |
||||
font-size: 3.2em; |
||||
line-height: 1.1; |
||||
} |
||||
|
||||
button { |
||||
border-radius: 8px; |
||||
border: 1px solid transparent; |
||||
padding: 0.6em 1.2em; |
||||
font-size: 1em; |
||||
font-weight: 500; |
||||
font-family: inherit; |
||||
background-color: #1a1a1a; |
||||
cursor: pointer; |
||||
transition: border-color 0.25s; |
||||
} |
||||
button:hover { |
||||
border-color: #646cff; |
||||
} |
||||
button:focus, |
||||
button:focus-visible { |
||||
outline: 4px auto -webkit-focus-ring-color; |
||||
} |
||||
|
||||
.card { |
||||
padding: 2em; |
||||
} |
||||
|
||||
#app { |
||||
max-width: 1280px; |
||||
margin: 0 auto; |
||||
padding: 2rem; |
||||
text-align: center; |
||||
} |
||||
|
||||
@media (prefers-color-scheme: light) { |
||||
:root { |
||||
color: #213547; |
||||
background-color: #ffffff; |
||||
} |
||||
a:hover { |
||||
color: #747bff; |
||||
} |
||||
button { |
||||
background-color: #f9f9f9; |
||||
} |
||||
} |
@ -1,7 +0,0 @@ |
||||
import { defineConfig } from 'vite' |
||||
import vue from '@vitejs/plugin-vue' |
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({ |
||||
plugins: [vue()], |
||||
}) |
@ -0,0 +1,15 @@ |
||||
package client |
||||
|
||||
type Config struct { |
||||
CenterServer string `json:"centerServer,omitempty"` |
||||
} |
||||
|
||||
type Client struct { |
||||
config Config |
||||
} |
||||
|
||||
func NetClient(config Config) *Client { |
||||
return &Client{ |
||||
config: config, |
||||
} |
||||
} |
@ -0,0 +1,54 @@ |
||||
package client |
||||
|
||||
import ( |
||||
"bytes" |
||||
"encoding/json" |
||||
"fmt" |
||||
"io" |
||||
"net/http" |
||||
) |
||||
|
||||
type DataItem struct { |
||||
Metric string `json:"metric"` |
||||
Tags map[string]string `json:"tags"` |
||||
Timestamp int64 `json:"timestamp"` |
||||
Value any `json:"value"` |
||||
} |
||||
|
||||
type ReportResponse struct { |
||||
RequestId string `json:"request_id,omitempty"` |
||||
Message string `json:"message,omitempty"` |
||||
} |
||||
|
||||
func (c *Client) Report(dataItem []DataItem) (*ReportResponse, error) { |
||||
reportJsonBytes, err := json.Marshal(dataItem) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
// send report data
|
||||
resp, err := http.Post(c.config.CenterServer, "application/json", bytes.NewBuffer(reportJsonBytes)) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
// get response
|
||||
defer func(Body io.ReadCloser) { |
||||
_ = Body.Close() |
||||
}(resp.Body) |
||||
|
||||
respBytes, err := io.ReadAll(resp.Body) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
fmt.Println(string(respBytes)) |
||||
|
||||
response := ReportResponse{} |
||||
err = json.Unmarshal(respBytes, &response) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &response, nil |
||||
} |
@ -0,0 +1,5 @@ |
||||
module rition-testsuite |
||||
|
||||
go 1.22.0 |
||||
|
||||
require github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect |
@ -0,0 +1,2 @@ |
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= |
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= |
@ -0,0 +1,28 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"flag" |
||||
"rition-testsuite/client" |
||||
"rition-testsuite/service" |
||||
"time" |
||||
) |
||||
|
||||
func main() { |
||||
// --report '127.0.0.1:22019' --disk_dev nvme0n1 --mount / --net_dev wlp0s20f3 --interval 30
|
||||
centerServer := flag.String("report", "http://localhost:8000/api/metric/put", "上报中心") |
||||
interval := flag.Int("interval", 5, "上报间隔,单位为秒") |
||||
dataFile := flag.String("data", "./data/abnormal_data_22000_500_171.json", "数据文件") |
||||
flag.Parse() |
||||
|
||||
config := service.Config{ |
||||
ClientConfig: client.Config{ |
||||
CenterServer: *centerServer, |
||||
}, |
||||
ReportInterval: time.Duration(*interval) * time.Second, |
||||
DataFileLocation: *dataFile, |
||||
} |
||||
|
||||
srv := service.NewService(config) |
||||
srv.Run() |
||||
//srv.Report()
|
||||
} |
@ -0,0 +1,69 @@ |
||||
package service |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"fmt" |
||||
"github.com/emirpasic/gods/v2/sets/hashset" |
||||
"os" |
||||
"rition-testsuite/client" |
||||
"sort" |
||||
"time" |
||||
) |
||||
|
||||
func (s *Service) Run() { |
||||
data, err := os.ReadFile(s.config.DataFileLocation) |
||||
if err != nil { |
||||
fmt.Println(err.Error()) |
||||
return |
||||
} |
||||
|
||||
fileDataItemList := make([]client.DataItem, 0) |
||||
err = json.Unmarshal(data, &fileDataItemList) |
||||
if err != nil { |
||||
fmt.Println(err.Error()) |
||||
return |
||||
} |
||||
|
||||
sort.Slice(fileDataItemList, func(i, j int) bool { |
||||
return fileDataItemList[i].Timestamp < fileDataItemList[j].Timestamp |
||||
}) |
||||
|
||||
times := hashset.New[int64]() |
||||
fileDataMap := map[int64][]client.DataItem{} |
||||
for _, dataItem := range fileDataItemList { |
||||
if _, has := fileDataMap[dataItem.Timestamp]; !has { |
||||
fileDataMap[dataItem.Timestamp] = make([]client.DataItem, 0, 22) |
||||
} |
||||
|
||||
fileDataMap[dataItem.Timestamp] = append(fileDataMap[dataItem.Timestamp], dataItem) |
||||
times.Add(dataItem.Timestamp) |
||||
} |
||||
|
||||
i := 0 |
||||
timesValue := times.Values() |
||||
sort.Slice(timesValue, func(i, j int) bool { |
||||
return timesValue[i] < timesValue[j] |
||||
}) |
||||
|
||||
fileDataItemList = nil |
||||
times = nil |
||||
|
||||
ticker := time.NewTicker(s.config.ReportInterval) |
||||
defer ticker.Stop() |
||||
for range ticker.C { |
||||
if i < len(timesValue) { |
||||
fmt.Printf("reporting: %d\n", timesValue[i]) |
||||
s.Report(fileDataMap[timesValue[i]]) |
||||
i++ |
||||
} else { |
||||
return |
||||
} |
||||
} |
||||
} |
||||
|
||||
func (s *Service) Report(dataList []client.DataItem) { |
||||
_, err := s.client.Report(dataList) |
||||
if err != nil { |
||||
fmt.Println("err: ", err.Error()) |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
package service |
||||
|
||||
import ( |
||||
"rition-testsuite/client" |
||||
"time" |
||||
) |
||||
|
||||
type Config struct { |
||||
ClientConfig client.Config |
||||
DataFileLocation string |
||||
|
||||
ReportInterval time.Duration `json:"reportInterval,omitempty"` |
||||
} |
||||
|
||||
type Service struct { |
||||
config Config |
||||
client *client.Client |
||||
} |
||||
|
||||
func NewService(config Config) *Service { |
||||
service := Service{ |
||||
config: config, |
||||
client: client.NetClient(config.ClientConfig), |
||||
} |
||||
|
||||
return &service |
||||
} |