소스 검색

[monitor]feature:param yml support key-value map (#57)

tomsun28 3 년 전
부모
커밋
636303021f

+ 21 - 0
collector/src/main/java/com/usthe/collector/dispatch/timer/WheelTimerTask.java

@@ -12,6 +12,7 @@ import com.usthe.common.entity.job.Job;
 import com.usthe.common.entity.job.Metrics;
 import com.usthe.common.util.AesUtil;
 import com.usthe.common.util.CommonConstants;
+import com.usthe.common.util.GsonUtil;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ArrayList;
@@ -84,6 +85,26 @@ public class WheelTimerTask implements TimerTask {
             while (iterator.hasNext()) {
                 Map.Entry<String, JsonElement> entry = iterator.next();
                 JsonElement element = entry.getValue();
+                String key = entry.getKey();
+                // 替换KEY-VALUE情况的属性 比如http headers params
+                if (key != null && key.startsWith("^_^") && key.endsWith("^_^")) {
+                    key = key.replaceAll("\\^_\\^", "");
+                    Configmap param = configmap.get(key);
+                    if (param.getType() == (byte) 3) {
+                        String jsonValue = (String) param.getValue();
+                         Map<String, String> map = GsonUtil.fromJson(jsonValue, Map.class);
+                         if (map != null) {
+                             map.forEach((name, value) -> {
+                                 if (name != null && !"".equals(name.trim())) {
+                                     jsonObject.addProperty(name, value);
+                                 }
+                             });
+                         }
+                    }
+                    iterator.remove();
+                    continue;
+                }
+                // 替换正常的VALUE值
                 if (element.isJsonPrimitive()) {
                     // 判断是否含有特殊字符 替换
                     String value = element.getAsString();

+ 1 - 1
common/src/main/java/com/usthe/common/entity/job/Configmap.java

@@ -28,7 +28,7 @@ public class Configmap {
     private Object value;
 
     /**
-     * 参数类型 0:数字 1:字符串 2:加密串
+     * 参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串
      * number,string,secret
      * 数字,非加密字符串,加密字符串
      */

+ 3 - 3
common/src/main/java/com/usthe/common/entity/manager/Param.java

@@ -63,11 +63,11 @@ public class Param {
     private String value;
 
     /**
-     * 参数类型 0:数字 1:字符串 2:加密串
+     * 参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串
      */
-    @ApiModelProperty(value = "参数类型 0:数字 1:字符串 2:加密串", accessMode = READ_WRITE, position = 4)
+    @ApiModelProperty(value = "参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串", accessMode = READ_WRITE, position = 4)
     @Min(0)
-    @Max(2)
+    @Max(3)
     private byte type;
 
     /**

+ 16 - 4
common/src/main/java/com/usthe/common/entity/manager/ParamDefine.java

@@ -111,28 +111,40 @@ public class ParamDefine {
     private List<Option> options;
 
     /**
+     * 当type为key-value时有效,表示key的别名描述
+     */
+    @ApiModelProperty(value = "当type为key-value时有效,表示key的别名描述", example = "Name", accessMode = READ_WRITE, position = 9)
+    private String keyAlias;
+
+    /**
+     * 当type为key-value时有效,表示value的别名描述
+     */
+    @ApiModelProperty(value = "当type为key-value时有效,表示value的别名描述", example = "Value", accessMode = READ_WRITE, position = 10)
+    private String valueAlias;
+
+    /**
      * 此条记录创建者
      */
-    @ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 9)
+    @ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11)
     private String creator;
 
     /**
      * 此条记录最新修改者
      */
-    @ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 10)
+    @ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12)
     private String modifier;
 
     /**
      * 记录创建时间
      */
-    @ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 11)
+    @ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13)
     @Column(insertable = false, updatable = false)
     private LocalDateTime gmtCreate;
 
     /**
      * 记录最新修改时间
      */
-    @ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 12)
+    @ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14)
     @Column(insertable = false, updatable = false)
     private LocalDateTime gmtUpdate;
 

+ 3 - 0
manager/src/main/java/com/usthe/manager/service/impl/MonitorServiceImpl.java

@@ -236,6 +236,9 @@ public class MonitorServiceImpl implements MonitorService {
                         case "checkbox":
                             // todo checkbox校验
                             break;
+                        case "key-value":
+                            // todo key-value校验
+                            break;
                         // todo 更多参数定义与实际值格式校验
                         default:
                             throw new IllegalArgumentException("ParamDefine type " + paramDefine.getType() + " is invalid.");

+ 4 - 2
manager/src/main/resources/define/app/A-example.yml

@@ -5,7 +5,7 @@ app: example
 name:
   zh-CN: 模拟应用类型
   en-US: EXAMPLE APP
-# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
+# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串, 3-map映射的json串
 # 强制固定必须参数 - host
 configmap:
   - key: host
@@ -16,6 +16,8 @@ configmap:
     type: 1
   - key: password
     type: 2
+  - key: headers
+    type: 3
 # 指标组列表
 metrics:
 # 第一个监控指标组 cpu
@@ -69,7 +71,7 @@ metrics:
       ssl: false
       # 请求头内容
       headers:
-        apiVersion: v1
+        ^_^headers^_^: ^_^headers^_^
       # 请求参数内容
       params:
         param1: param1

+ 7 - 1
manager/src/main/resources/define/param/A-example.yml

@@ -48,4 +48,10 @@ param:
       - label: PUT请求
         value: PUT
       - label: DELETE请求
-        value: DELETE
+        value: DELETE
+  - field: headers
+    name: 请求头
+    type: key-value
+    required: false
+    keyAlias: Header Name
+    valueAlias: Header Value

+ 3 - 0
web-app/src/app/pojo/ParamDefine.ts

@@ -9,4 +9,7 @@ export class ParamDefine {
   limit: number | undefined;
   //'[{"label":"GET请求","value":"GET"},{"label":"PUT请求","value":"PUT"}]'
   options!: any[];
+  // 当type为key-value时有效,表示别名描述
+  keyAlias!: string;
+  valueAlias!: string;
 }

+ 12 - 0
web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.html

@@ -147,6 +147,18 @@
             </label>
           </nz-radio-group>
         </nz-form-control>
+
+        <nz-form-label *ngIf="paramDefine.type === 'key-value'" nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field"
+          >{{ paramDefine.name }}
+        </nz-form-label>
+        <nz-form-control *ngIf="paramDefine.type === 'key-value'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
+          <app-key-value-input
+            [(value)]="params[i].value"
+            [id]="paramDefine.field"
+            keyAlias="Header Name"
+            valueAlias="Header Value"
+          ></app-key-value-input>
+        </nz-form-control>
       </nz-form-item>
 
       <nz-divider></nz-divider>

+ 7 - 1
web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts

@@ -78,7 +78,13 @@ export class MonitorEditComponent implements OnInit {
             if (param === undefined) {
               param = new Param();
               param.field = define.field;
-              param.type = define.type === 'number' ? 0 : 1;
+              if (define.type === 'number') {
+                param.type = 0;
+              } else if (define.type === 'key-value') {
+                param.type = 3;
+              } else {
+                param.type = 1;
+              }
               if (define.type === 'boolean') {
                 param.value = false;
               }

+ 12 - 0
web-app/src/app/routes/monitor/monitor-new/monitor-new.component.html

@@ -156,6 +156,18 @@
             </label>
           </nz-radio-group>
         </nz-form-control>
+
+        <nz-form-label *ngIf="paramDefine.type === 'key-value'" nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field"
+          >{{ paramDefine.name }}
+        </nz-form-label>
+        <nz-form-control *ngIf="paramDefine.type === 'key-value'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
+          <app-key-value-input
+            [(value)]="params[i].value"
+            [id]="paramDefine.field"
+            [keyAlias]="paramDefine.keyAlias ? paramDefine.keyAlias : 'Name'"
+            [valueAlias]="paramDefine.valueAlias ? paramDefine.valueAlias : 'Value'"
+          ></app-key-value-input>
+        </nz-form-control>
       </nz-form-item>
 
       <nz-divider></nz-divider>

+ 7 - 1
web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts

@@ -58,7 +58,13 @@ export class MonitorNewComponent implements OnInit {
           this.paramDefines.forEach(define => {
             let param = new Param();
             param.field = define.field;
-            param.type = define.type === 'number' ? 0 : 1;
+            if (define.type === 'number') {
+              param.type = 0;
+            } else if (define.type === 'key-value') {
+              param.type = 3;
+            } else {
+              param.type = 1;
+            }
             if (define.type === 'boolean') {
               param.value = false;
             }

+ 0 - 2
web-app/src/app/shared/components/README.md

@@ -1,2 +0,0 @@
-### 公共通用小组件
-

+ 12 - 0
web-app/src/app/shared/components/key-value-input/key-value-input.component.html

@@ -0,0 +1,12 @@
+<div *ngFor="let item of keyValues; let i = index" nz-row>
+  <div nz-col nzSpan="10">
+    <input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key" (ngModelChange)="onChange()" />
+  </div>
+  <div nz-col nzSpan="11">
+    <input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value" (ngModelChange)="onChange()" />
+  </div>
+  <div nz-col nzSpan="3">
+    <i nz-icon nzType="plus-circle" class="dynamic-button" *ngIf="i === 0" (click)="addNew($event)"></i>
+    <i nz-icon nzType="minus-circle" class="dynamic-button" (click)="removeCurrent(i, $event)"></i>
+  </div>
+</div>

+ 12 - 0
web-app/src/app/shared/components/key-value-input/key-value-input.component.less

@@ -0,0 +1,12 @@
+.dynamic-button {
+  cursor: pointer;
+  position: relative;
+  top: 4px;
+  font-size: 15px;
+  transition: all 0.3s;
+  margin-left: 6%;
+}
+
+.dynamic-button:hover {
+  font-size: 26px;
+}

+ 25 - 0
web-app/src/app/shared/components/key-value-input/key-value-input.component.spec.ts

@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { KeyValueInputComponent } from './key-value-input.component';
+
+describe('KeyValueInputComponent', () => {
+  let component: KeyValueInputComponent;
+  let fixture: ComponentFixture<KeyValueInputComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ KeyValueInputComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(KeyValueInputComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 63 - 0
web-app/src/app/shared/components/key-value-input/key-value-input.component.ts

@@ -0,0 +1,63 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+
+@Component({
+  selector: 'app-key-value-input',
+  templateUrl: './key-value-input.component.html',
+  styleUrls: ['./key-value-input.component.less']
+})
+export class KeyValueInputComponent implements OnInit {
+  constructor() {}
+
+  @Input() value!: any;
+  @Output() readonly valueChange = new EventEmitter<string>();
+
+  @Input()
+  keyAlias: string = 'Key';
+  @Input()
+  valueAlias: string = 'Value';
+
+  keyValues: any[] = [];
+
+  ngOnInit(): void {
+    if (this.value == undefined) {
+      this.value = {
+        '': ''
+      };
+    } else {
+      this.value = JSON.parse(this.value);
+    }
+    Object.keys(this.value).map(item => {
+      this.keyValues.push({
+        key: item,
+        value: this.value[item]
+      });
+    });
+  }
+
+  addNew(e?: MouseEvent) {
+    if (e) {
+      e.preventDefault();
+    }
+    this.keyValues.push({
+      key: '',
+      value: ''
+    });
+  }
+  removeCurrent(index: number, e?: MouseEvent) {
+    if (e) {
+      e.preventDefault();
+    }
+    if (this.keyValues.length > 1) {
+      this.keyValues.splice(index, 1);
+    }
+  }
+  onChange() {
+    this.value = {};
+    this.keyValues.forEach(item => {
+      if (item != null && item.key != null) {
+        this.value[item.key] = item.value;
+      }
+    });
+    this.valueChange.emit(JSON.stringify(this.value));
+  }
+}

+ 2 - 1
web-app/src/app/shared/shared.module.ts

@@ -6,6 +6,7 @@ import { DelonACLModule } from '@delon/acl';
 import { DelonFormModule } from '@delon/form';
 import { AlainThemeModule } from '@delon/theme';
 
+import { KeyValueInputComponent } from './components/key-value-input/key-value-input.component';
 import { TimezonePipe } from './pipe/timezone.pipe';
 import { SHARED_DELON_MODULES } from './shared-delon.module';
 import { SHARED_ZORRO_MODULES } from './shared-zorro.module';
@@ -18,7 +19,7 @@ const THIRDMODULES: Array<Type<void>> = [];
 
 // #region your components & directives
 
-const COMPONENTS: Array<Type<void>> = [];
+const COMPONENTS: Array<Type<void>> = [KeyValueInputComponent];
 const DIRECTIVES: Array<Type<void>> = [TimezonePipe];
 
 // #endregion