From 3b3b61eca5a33842cead349839d73a644d59c62a Mon Sep 17 00:00:00 2001 From: nieziyan Date: Mon, 20 Nov 2023 19:12:32 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A1.=E8=A1=A8=E7=A9=BA=E9=97=B4?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=8E=872.Database|Email=20Monitor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jeecg/common/constant/DBSQL.java | 8 ++++ .../org/jeecg/modules/base/dto/ItemDto.java | 7 ++++ .../org/jeecg/modules/base/dto/SpaceInfo.java | 17 ++++++++ .../base/entity/postgre/AlarmItemDe.java | 23 +++++++++++ .../jeecg/modules/base/enums/SourceType.java | 2 +- .../controller/AlarmRuleController.java | 8 ++-- .../controller/SysDatabaseController.java | 6 +++ .../modules/mapper/AlarmItemDeMapper.java | 9 ++++ .../jeecg/modules/mapper/SpaceRowMapper.java | 22 ++++++++++ .../modules/service/IAlarmItemDeService.java | 11 +++++ .../modules/service/IAlarmItemService.java | 3 ++ .../modules/service/ISysDatabaseService.java | 3 ++ .../service/impl/AlarmItemDeServiceImpl.java | 21 ++++++++++ .../service/impl/AlarmItemServiceImpl.java | 41 ++++++++++++++++++- .../service/impl/SysDatabaseServiceImpl.java | 25 +++++++++++ .../job/{SysInfoJob.java => ServerJob.java} | 14 +++---- 16 files changed, 204 insertions(+), 16 deletions(-) create mode 100644 jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/SpaceInfo.java create mode 100644 jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/AlarmItemDe.java create mode 100644 jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/AlarmItemDeMapper.java create mode 100644 jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/SpaceRowMapper.java create mode 100644 jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemDeService.java create mode 100644 jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemDeServiceImpl.java rename jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/{SysInfoJob.java => ServerJob.java} (94%) diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DBSQL.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DBSQL.java index 423c16f9..e39a2b8d 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DBSQL.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DBSQL.java @@ -22,6 +22,14 @@ public interface DBSQL { "ON a.owner = d.owner AND a.table_name = d.segment_name " + "AND d.segment_type = 'TABLE' WHERE a.owner = '%s' " + "ORDER BY a.table_name"; + String SPACE_OR = "SELECT a.tablespace_name AS spaceName, total / 1024 / 1024 AS total," + + "Round( free / 1024 / 1024, 2 ) AS free," + + "Round( ( total - free ) / 1024 / 1024, 2 ) AS usage," + + "Round( ( total - free ) / total, 4 ) * 100 AS used " + + "FROM " + + "( SELECT tablespace_name, Sum( bytes ) free FROM DBA_FREE_SPACE GROUP BY tablespace_name ) a," + + "( SELECT tablespace_name, Sum( bytes ) total FROM DBA_DATA_FILES GROUP BY tablespace_name ) b " + + "WHERE a.tablespace_name = b.tablespace_name"; String DBINDEX_OR = "SELECT a.table_name AS tableName, a.num_rows AS numRow," + "COALESCE(ROUND((d.bytes / (1024 * 1024)), 2), 0) AS dataSize, " + "COALESCE(ROUND((d.bytes / (1024 * 1024)), 2), 0) AS indexSize, " + diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/ItemDto.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/ItemDto.java index bfc3520c..1e24e515 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/ItemDto.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/ItemDto.java @@ -3,6 +3,7 @@ package org.jeecg.modules.base.dto; import lombok.Data; import org.jeecg.modules.base.entity.monitor.Item; import org.jeecg.modules.base.entity.postgre.AlarmItem; +import org.jeecg.modules.base.entity.postgre.AlarmItemDe; import java.io.Serializable; @@ -20,4 +21,10 @@ public class ItemDto implements Serializable{ this.name = alarmItem.getName(); this.units = alarmItem.getUnits(); } + + public ItemDto(AlarmItemDe alarmItemDe) { + this.itemId = alarmItemDe.getId(); + this.name = alarmItemDe.getName(); + this.units = alarmItemDe.getUnits(); + } } diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/SpaceInfo.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/SpaceInfo.java new file mode 100644 index 00000000..21d19f4c --- /dev/null +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/dto/SpaceInfo.java @@ -0,0 +1,17 @@ +package org.jeecg.modules.base.dto; + +import lombok.Data; + +@Data +public class SpaceInfo { + + private String spaceName; + + private Integer total; + + private Double free; + + private Double usage; + + private Double used; +} diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/AlarmItemDe.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/AlarmItemDe.java new file mode 100644 index 00000000..82b7a312 --- /dev/null +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/AlarmItemDe.java @@ -0,0 +1,23 @@ +package org.jeecg.modules.base.entity.postgre; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import org.jeecg.common.system.base.entity.JeecgEntity; + +@Data +@TableName("alarm_item_de") +public class AlarmItemDe extends JeecgEntity { + + @TableField("name") + private String name; + + @TableField("units") + private String units; + + @TableField("description") + private String description; + + @TableField("source_type") + private String sourceType; +} diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SourceType.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SourceType.java index 80d26281..10a104b5 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SourceType.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SourceType.java @@ -12,7 +12,7 @@ import cn.hutool.core.util.StrUtil; public enum SourceType { EMAIL("Email"), - DATABASE("DataBase"), + DATABASE("Database"), SERVER("Server"); private String type; diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/AlarmRuleController.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/AlarmRuleController.java index 9625766a..b6da13e9 100644 --- a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/AlarmRuleController.java +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/AlarmRuleController.java @@ -67,11 +67,9 @@ public class AlarmRuleController { } @GetMapping("getItems") - @ApiOperation(value = "根据资源名称获取监控项",notes = "根据资源名称获取监控项") - public Result getItems(@RequestParam String sourceId){ - List alarmItems = alarmItemService.alarmItems(sourceId); - List itemDtos = alarmItems.stream().map(ItemDto::new).collect(Collectors.toList()); - return Result.OK(itemDtos); + @ApiOperation(value = "获取监控项",notes = "获取监控项") + public Result getItems(@RequestParam String sourceType, String sourceId){ + return Result.OK(alarmItemService.allItems(sourceType, sourceId)); } @PutMapping("updateStatus") diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/SysDatabaseController.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/SysDatabaseController.java index 732b5dbf..ce3c5bec 100644 --- a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/SysDatabaseController.java +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/controller/SysDatabaseController.java @@ -76,4 +76,10 @@ public class SysDatabaseController { @RequestParam String dbName) { return Result.OK(sysDatabaseService.dbInfo(sourceId, dbName)); } + + @GetMapping("spaceInfo") + @ApiOperation(value = "数据库表空间使用情况",notes = "数据库表空间使用情况") + public Result spaceInfo(@RequestParam String sourceId) { + return Result.OK(sysDatabaseService.spaceInfo(sourceId)); + } } diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/AlarmItemDeMapper.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/AlarmItemDeMapper.java new file mode 100644 index 00000000..5991c93b --- /dev/null +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/AlarmItemDeMapper.java @@ -0,0 +1,9 @@ +package org.jeecg.modules.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.base.entity.postgre.AlarmItem; +import org.jeecg.modules.base.entity.postgre.AlarmItemDe; + +public interface AlarmItemDeMapper extends BaseMapper { + +} diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/SpaceRowMapper.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/SpaceRowMapper.java new file mode 100644 index 00000000..b800baa3 --- /dev/null +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/mapper/SpaceRowMapper.java @@ -0,0 +1,22 @@ +package org.jeecg.modules.mapper; + +import org.jeecg.modules.base.dto.DBInfo; +import org.jeecg.modules.base.dto.SpaceInfo; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class SpaceRowMapper implements RowMapper { + + @Override + public SpaceInfo mapRow(ResultSet rs, int rowNum) throws SQLException { + SpaceInfo spaceInfo = new SpaceInfo(); + spaceInfo.setSpaceName(rs.getString("spaceName")); + spaceInfo.setTotal(rs.getInt("total")); + spaceInfo.setFree(rs.getDouble("free")); + spaceInfo.setUsage(rs.getDouble("usage")); + spaceInfo.setUsed(rs.getDouble("used")); + return spaceInfo; + } +} diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemDeService.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemDeService.java new file mode 100644 index 00000000..a34251d2 --- /dev/null +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemDeService.java @@ -0,0 +1,11 @@ +package org.jeecg.modules.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.modules.base.entity.postgre.AlarmItemDe; + +import java.util.List; + +public interface IAlarmItemDeService extends IService { + + List alarmItemDes(String sourceType); +} diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemService.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemService.java index 92d440d8..3bdc9156 100644 --- a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemService.java +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/IAlarmItemService.java @@ -2,6 +2,7 @@ package org.jeecg.modules.service; import com.baomidou.mybatisplus.extension.service.IService; import org.jeecg.common.api.vo.Result; +import org.jeecg.modules.base.dto.ItemDto; import org.jeecg.modules.base.entity.postgre.AlarmItem; import java.util.List; @@ -10,4 +11,6 @@ public interface IAlarmItemService extends IService { boolean syncServerItem(); List alarmItems(String sourceId); + + List allItems(String sourceType, String sourceId); } diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/ISysDatabaseService.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/ISysDatabaseService.java index 25073815..8834c763 100644 --- a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/ISysDatabaseService.java +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/ISysDatabaseService.java @@ -5,6 +5,7 @@ import org.jeecg.common.api.QueryRequest; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.base.dto.DBInfo; import org.jeecg.modules.base.dto.SourceDto; +import org.jeecg.modules.base.dto.SpaceInfo; import org.jeecg.modules.base.entity.postgre.SysDatabase; import org.jeecg.modules.base.bizVo.SourceVo; @@ -29,4 +30,6 @@ public interface ISysDatabaseService extends IService { List dbNames(String id); List dbInfo(String id, String dbName); + + List spaceInfo(String id); } diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemDeServiceImpl.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemDeServiceImpl.java new file mode 100644 index 00000000..ddcc3802 --- /dev/null +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemDeServiceImpl.java @@ -0,0 +1,21 @@ +package org.jeecg.modules.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.jeecg.modules.base.entity.postgre.AlarmItemDe; +import org.jeecg.modules.mapper.AlarmItemDeMapper; +import org.jeecg.modules.service.IAlarmItemDeService; +import org.springframework.stereotype.Service; + +import java.util.List; + + +@Service +public class AlarmItemDeServiceImpl extends ServiceImpl implements IAlarmItemDeService { + + public List alarmItemDes(String sourceType) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(AlarmItemDe::getSourceType,sourceType); + return list(wrapper); + } +} diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemServiceImpl.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemServiceImpl.java index 9bf0b772..7290f1f4 100644 --- a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemServiceImpl.java +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/AlarmItemServiceImpl.java @@ -3,19 +3,27 @@ package org.jeecg.modules.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.jeecg.common.api.vo.Result; import org.jeecg.common.constant.MonitorConstant; import org.jeecg.common.constant.Prompt; +import org.jeecg.common.util.RedisStreamUtil; +import org.jeecg.common.util.RedisUtil; +import org.jeecg.common.util.SpringContextUtils; +import org.jeecg.modules.base.dto.ItemDto; import org.jeecg.modules.base.entity.monitor.Host; import org.jeecg.modules.base.entity.monitor.Item; import org.jeecg.modules.base.entity.monitor.Servers; import org.jeecg.modules.base.entity.postgre.AlarmItem; +import org.jeecg.modules.base.entity.postgre.AlarmItemDe; import org.jeecg.modules.base.entity.postgre.SysServer; +import org.jeecg.modules.base.enums.SourceType; import org.jeecg.modules.feignclient.MonitorAlarm; import org.jeecg.modules.mapper.AlarmItemMapper; +import org.jeecg.modules.service.IAlarmItemDeService; import org.jeecg.modules.service.IAlarmItemService; import org.jeecg.modules.service.ISysDatabaseService; import org.jeecg.modules.service.ISysServerService; @@ -25,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static org.jeecg.modules.base.enums.SourceType.DATABASE; import static org.jeecg.modules.base.enums.SourceType.SERVER; @@ -40,7 +49,7 @@ public class AlarmItemServiceImpl extends ServiceImpl alarmItems(String sourceId) { if (StrUtil.isBlank(sourceId)) @@ -88,4 +102,29 @@ public class AlarmItemServiceImpl extends ServiceImpl allItems(String sourceType, String sourceId) { + List itemDtos = new ArrayList<>(); + SourceType type = SourceType.typeOf(sourceType); + if (ObjectUtil.isNull(type)) + return itemDtos; + switch (type){ + case SERVER: + itemDtos = alarmItems(sourceId).stream() + .map(ItemDto::new).collect(Collectors.toList()); + break; + case DATABASE: + case EMAIL: + itemDtos = alarmItemDeService.alarmItemDes(sourceType).stream() + .map(ItemDto::new).collect(Collectors.toList()); + break; + default: + break; + } + return itemDtos; + } } diff --git a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/SysDatabaseServiceImpl.java b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/SysDatabaseServiceImpl.java index 65584f86..6badd46f 100644 --- a/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/SysDatabaseServiceImpl.java +++ b/jeecg-module-abnormal-alarm/src/main/java/org/jeecg/modules/service/impl/SysDatabaseServiceImpl.java @@ -19,11 +19,13 @@ import org.jeecg.config.mybatis.DSSwitcher; import org.jeecg.modules.base.dto.DBInfo; import org.jeecg.modules.base.dto.DatabaseDto; import org.jeecg.modules.base.dto.SourceDto; +import org.jeecg.modules.base.dto.SpaceInfo; import org.jeecg.modules.base.entity.postgre.SysDatabase; import org.jeecg.modules.base.bizVo.SourceVo; import org.jeecg.modules.entity.AlarmHistory; import org.jeecg.modules.feignclient.SystemClient; import org.jeecg.modules.mapper.DBRowMapper; +import org.jeecg.modules.mapper.SpaceRowMapper; import org.jeecg.modules.mapper.SysDatabaseMapper; import org.jeecg.modules.service.ISysDatabaseService; import org.springframework.beans.factory.annotation.Autowired; @@ -242,6 +244,8 @@ public class SysDatabaseServiceImpl extends ServiceImpl spaceInfo(String id) { + List spaceInfos = new ArrayList<>(); + SysDatabase sysDatabase = getById(id); + if (ObjectUtil.isNull(sysDatabase)) + return spaceInfos; + String dbType = sysDatabase.getDbType(); + if (StrUtil.equals(dbType, ORACLE.getType())){ + String dbUrl = sysDatabase.getDbUrl(); + String dbDriver = sysDatabase.getDbDriver(); + String dbUsername = sysDatabase.getDbUsername(); + String dbPassword = sysDatabase.getDbPassword(); + RowMapper mapper = new SpaceRowMapper(); + JdbcTemplate template = JDBCUtil.template(dbUrl, dbDriver, dbUsername, dbPassword); + spaceInfos = template.query(DBSQL.SPACE_OR, mapper); + } + return spaceInfos; + } + private List dbInfoPG(SysDatabase sysDatabase, String dbName, RowMapper mapper){ String dbUrl = sysDatabase.getDbUrl(); String dbDriver = sysDatabase.getDbDriver(); diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SysInfoJob.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/ServerJob.java similarity index 94% rename from jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SysInfoJob.java rename to jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/ServerJob.java index ad939483..3bbd3c8a 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SysInfoJob.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/ServerJob.java @@ -9,7 +9,6 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.api.vo.Result; import org.jeecg.common.config.mqtoken.UserTokenContext; -import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.DateConstant; import org.jeecg.common.constant.RedisConstant; import org.jeecg.common.util.RedisStreamUtil; @@ -28,12 +27,13 @@ import java.time.format.DateTimeFormatter; import java.util.Set; import static org.jeecg.modules.base.enums.Op.*; +import static org.jeecg.modules.base.enums.SourceType.SERVER; @Data @Slf4j @PersistJobDataAfterExecution @DisallowConcurrentExecution -public class SysInfoJob implements Job { +public class ServerJob implements Job { private String parameter; @@ -52,12 +52,10 @@ public class SysInfoJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { init(); - // 查询所有报警规则,根据报警规则查询监控项数据 - String pattern = RedisConstant.PREFIX_RULE; + // 查询所有Server的报警规则,根据报警规则查询监控项数据 + String pattern = RedisConstant.PREFIX_RULE + SERVER.getType(); Set keys = redisStreamUtil.keys(pattern); - if (CollUtil.isEmpty(keys)) { - return; - } + if (CollUtil.isEmpty(keys)) return; // 时间间隔为每分钟 LocalDateTime now = LocalDateTime.now() @@ -73,8 +71,6 @@ public class SysInfoJob implements Job { String operator = null; for (String ruleKey : keys) { try { - if (StrUtil.equals(RedisConstant.ANALYSIS_RULE, ruleKey)) - continue; AlarmRule alarmRule = (AlarmRule) redisStreamUtil.get(ruleKey); // 如果报警规则为空,或者在沉默周期内,跳过当前规则 operator = alarmRule.getOperator();