Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
brandkbs2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
shenjunjie
brandkbs2
Commits
9cd45bc3
Commit
9cd45bc3
authored
Nov 27, 2024
by
陈健智
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
企业微信机器人自主版数据用量预警
parent
b3219858
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
332 additions
and
0 deletions
+332
-0
src/main/java/com/zhiwei/brandkbs2/service/TaskService.java
+5
-0
src/main/java/com/zhiwei/brandkbs2/service/impl/ProjectServiceImpl.java
+7
-0
src/main/java/com/zhiwei/brandkbs2/service/impl/TaskServiceImpl.java
+96
-0
src/main/java/com/zhiwei/brandkbs2/task/ControlCenter.java
+13
-0
src/main/java/com/zhiwei/brandkbs2/util/RobotPushUtils.java
+211
-0
No files found.
src/main/java/com/zhiwei/brandkbs2/service/TaskService.java
View file @
9cd45bc3
...
...
@@ -82,4 +82,9 @@ public interface TaskService{
* 生成ai搜索参考提问缓存
*/
void
cacheAIQuestion
();
/**
* 非人工项目企业微信机器人数据用量预警
*/
void
wechatRobotWarnPush
();
}
src/main/java/com/zhiwei/brandkbs2/service/impl/ProjectServiceImpl.java
View file @
9cd45bc3
...
...
@@ -19,6 +19,7 @@ import com.zhiwei.brandkbs2.service.MarkDataService;
import
com.zhiwei.brandkbs2.service.ProjectService
;
import
com.zhiwei.brandkbs2.service.UserService
;
import
com.zhiwei.brandkbs2.util.MongoUtil
;
import
com.zhiwei.brandkbs2.util.RobotPushUtils
;
import
com.zhiwei.brandkbs2.util.Tools
;
import
com.zhiwei.middleware.auth.util.JwtUtil
;
import
com.zhiwei.middleware.event.pojo.dto.EventTagRelatedDTO
;
...
...
@@ -40,6 +41,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletRequest
;
import
java.text.MessageFormat
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -649,6 +651,11 @@ public class ProjectServiceImpl implements ProjectService {
projectDao
.
updateOneByIdWithField
(
projectId
,
update
);
NonManualProjectDataUpdateRecord
record
=
new
NonManualProjectDataUpdateRecord
(
projectId
,
project
.
getDataBalance
(),
currentCount
,
UserThreadLocal
.
getNickname
());
nonManualProjectDataUpdateRecordDao
.
insertOne
(
record
);
String
message
=
"预警项目:{0}-数据额度调整"
+
"\n"
+
"调整前额度:{1}"
+
"\n"
+
"调整后额度:{2}"
+
"\n"
+
"调整人员:{3}"
;
RobotPushUtils
.
pushCommonMessage
(
MessageFormat
.
format
(
message
,
project
.
getProjectName
(),
project
.
getDataBalance
(),
currentCount
,
UserThreadLocal
.
getNickname
()));
}
@Override
...
...
src/main/java/com/zhiwei/brandkbs2/service/impl/TaskServiceImpl.java
View file @
9cd45bc3
...
...
@@ -8,6 +8,7 @@ import com.zhiwei.brandkbs2.common.RedisKeyPrefix;
import
com.zhiwei.brandkbs2.config.Constant
;
import
com.zhiwei.brandkbs2.dao.*
;
import
com.zhiwei.brandkbs2.enmus.ReportTypeEnum
;
import
com.zhiwei.brandkbs2.enmus.RoleEnum
;
import
com.zhiwei.brandkbs2.es.ChannelEsDao
;
import
com.zhiwei.brandkbs2.es.EsClientDao
;
import
com.zhiwei.brandkbs2.es.EsQueryTools
;
...
...
@@ -17,9 +18,11 @@ import com.zhiwei.brandkbs2.model.CommonCodeEnum;
import
com.zhiwei.brandkbs2.pojo.*
;
import
com.zhiwei.brandkbs2.service.*
;
import
com.zhiwei.brandkbs2.util.RedisUtil
;
import
com.zhiwei.brandkbs2.util.RobotPushUtils
;
import
com.zhiwei.brandkbs2.util.Tools
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.collections4.ListUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.tuple.Pair
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
...
...
@@ -35,6 +38,7 @@ import org.springframework.stereotype.Service;
import
javax.annotation.Resource
;
import
java.io.IOException
;
import
java.text.MessageFormat
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.ConcurrentHashMap
;
...
...
@@ -83,6 +87,9 @@ public class TaskServiceImpl implements TaskService {
@Resource
(
name
=
"xiaohongshuRecordDao"
)
private
XiaohongshuRecordDao
xiaohongshuRecordDao
;
@Resource
(
name
=
"userDao"
)
private
UserDao
userDao
;
@Resource
(
name
=
"customInteractionUpdateRecordDao"
)
private
CustomInteractionUpdateRecordDao
customInteractionUpdateRecordDao
;
...
...
@@ -513,6 +520,95 @@ public class TaskServiceImpl implements TaskService {
},
cacheServiceExecutor
)).
toArray
(
CompletableFuture
[]::
new
)).
join
();
}
@Override
public
void
wechatRobotWarnPush
()
{
CompletableFuture
.
allOf
(
GlobalPojo
.
PROJECT_MAP
.
values
().
stream
().
filter
(
project
->
project
.
isStart
()
&&
!
project
.
isManual
()).
map
(
project
->
CompletableFuture
.
supplyAsync
(()
->
{
try
{
long
yestConsume
=
getYesterdayProjectPlanConsume
(
project
.
getId
(),
null
);
double
balanceCanUsedDay
=
0
>=
project
.
getDataBalance
()
?
0
:
0
==
yestConsume
?
project
.
getDataBalance
()
:
(
double
)
project
.
getDataBalance
()
/
yestConsume
;
// 项目管理员
Criteria
criteria
=
Criteria
.
where
(
"roles.projectId"
).
is
(
project
.
getId
()).
and
(
"superAdmin"
).
is
(
false
);
criteria
.
andOperator
(
Criteria
.
where
(
"roles.key"
).
is
(
Tools
.
concat
(
project
.
getId
(),
RoleEnum
.
ADMIN
.
getState
())));
List
<
String
>
adminList
=
userDao
.
findList
(
new
Query
(
criteria
)).
stream
().
map
(
User:
:
getNickname
).
collect
(
Collectors
.
toList
());
// 大数据量方案预警
if
(
yestConsume
>
10000
){
largeDataWarn
(
project
);
}
// 数据额度不足方案停用预警
if
(
0
==
balanceCanUsedDay
){
pushWarn
(
"数据额度不足方案停用"
,
project
,
yestConsume
,
adminList
);
return
null
;
}
// 数据额度不足7天预警
if
(
balanceCanUsedDay
<
7
){
pushWarn
(
"数据额度不足7天预警"
,
project
,
yestConsume
,
adminList
);
return
null
;
}
// 数据额度不足15天预警
if
(
balanceCanUsedDay
<
15
){
pushWarn
(
"数据额度不足15天预警"
,
project
,
yestConsume
,
adminList
);
return
null
;
}
// 数据额度不足30天预警
if
(
balanceCanUsedDay
<
30
){
pushWarn
(
"数据额度不足30天预警"
,
project
,
yestConsume
,
adminList
);
return
null
;
}
}
catch
(
Exception
e
){
log
.
error
(
"非人工项目:{}-{}-企业微信机器人预警出错-"
,
project
.
getProjectName
(),
project
.
getId
(),
e
);
}
return
null
;
},
cacheServiceExecutor
)).
toArray
(
CompletableFuture
[]::
new
)).
join
();
}
private
void
largeDataWarn
(
Project
project
)
throws
IOException
{
List
<
NonManualProjectPlan
>
plans
=
nonManualProjectPlanDao
.
findList
(
new
Query
(
Criteria
.
where
(
"projectId"
).
is
(
project
.
getId
())));
if
(
CollectionUtils
.
isEmpty
(
plans
)){
return
;
}
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
MessageFormat
.
format
(
"项目:{0}-{1}"
,
project
.
getProjectName
(),
"大数据量方案预警"
)).
append
(
"\n"
);
for
(
int
i
=
0
;
i
<
plans
.
size
();
i
++)
{
NonManualProjectPlan
plan
=
plans
.
get
(
i
);
long
count
=
getYesterdayProjectPlanConsume
(
project
.
getId
(),
plan
.
getId
());
String
message
=
MessageFormat
.
format
(
"方案{0}:{1}({2}),数据量:{3}"
,
i
+
1
,
plan
.
getName
(),
project
.
getProjectName
(),
count
);
sb
.
append
(
message
);
if
(
i
+
1
!=
plans
.
size
()){
sb
.
append
(
"\n"
);
}
}
RobotPushUtils
.
pushCommonMessage
(
sb
.
toString
());
}
private
void
pushWarn
(
String
warnType
,
Project
project
,
long
yestConsume
,
List
<
String
>
admins
){
String
template
=
"项目:{0}-{1}"
+
"\n"
+
"剩余额度:{2}"
+
"\n"
+
"昨日消耗:{3}"
+
"\n"
+
"项目管理员:{4}"
;
String
message
=
MessageFormat
.
format
(
template
,
project
.
getProjectName
(),
warnType
,
project
.
getDataBalance
(),
yestConsume
,
StringUtils
.
join
(
admins
,
","
));
RobotPushUtils
.
pushCommonMessage
(
message
);
}
private
long
getYesterdayProjectPlanConsume
(
String
projectId
,
String
planId
)
throws
IOException
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
add
(
Calendar
.
DAY_OF_YEAR
,
-
1
);
calendar
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
MILLISECOND
,
0
);
long
yesterdayStartTime
=
calendar
.
getTimeInMillis
();
calendar
.
add
(
Calendar
.
DAY_OF_YEAR
,
1
);
long
yesterdayEndTime
=
calendar
.
getTimeInMillis
();
BoolQueryBuilder
query
=
EsQueryTools
.
assembleCacheMapsQuery
(
projectId
,
Constant
.
PRIMARY_CONTEND_ID
);
if
(
Objects
.
nonNull
(
planId
)){
query
=
EsQueryTools
.
assembleCacheMapsPlanQuery
(
projectId
,
planId
);
}
// stime
query
.
must
(
QueryBuilders
.
rangeQuery
(
"stime"
).
gte
(
yesterdayStartTime
).
lt
(
yesterdayEndTime
));
return
esClientDao
.
count
(
query
);
}
private
void
updateRefreshTask
(
String
id
,
String
status
){
Update
update
=
new
Update
();
update
.
set
(
"status"
,
status
);
...
...
src/main/java/com/zhiwei/brandkbs2/task/ControlCenter.java
View file @
9cd45bc3
...
...
@@ -146,4 +146,17 @@ public class ControlCenter {
log
.
info
(
"每十分钟拉取并进行渠道库更新任务-结束"
);
}
}
@Async
(
"scheduledExecutor"
)
@Scheduled
(
cron
=
"0 0 6 * * ?"
)
public
void
wechatRobotWarnPush
()
{
log
.
info
(
"每天六点非人工项目企业微信机器人数据用量预警-启动"
);
try
{
taskService
.
wechatRobotWarnPush
();
}
catch
(
Exception
e
)
{
log
.
error
(
"每天六点非人工项目企业微信机器人数据用量预警-出错"
,
e
);
}
finally
{
log
.
info
(
"每天六点非人工项目企业微信机器人数据用量预警-结束"
);
}
}
}
src/main/java/com/zhiwei/brandkbs2/util/RobotPushUtils.java
0 → 100644
View file @
9cd45bc3
package
com
.
zhiwei
.
brandkbs2
.
util
;
import
com.alibaba.fastjson.JSONObject
;
import
com.github.benmanes.caffeine.cache.Cache
;
import
com.github.benmanes.caffeine.cache.Caffeine
;
import
com.zhiwei.pushlog.config.LogConfig
;
import
com.zhiwei.pushlog.pojo.CountExpireValue
;
import
com.zhiwei.pushlog.tools.HttpClientUtils
;
import
com.zhiwei.pushlog.tools.Tools
;
import
org.springframework.beans.factory.annotation.Value
;
import
java.net.Inet4Address
;
import
java.net.InetAddress
;
import
java.util.Objects
;
import
java.util.concurrent.TimeUnit
;
/**
* Description:
*
* @author LiuMingHuan
* @classname RobotPushUtils
* @date 2020/3/13
*/
public
class
RobotPushUtils
{
private
static
final
String
[]
MENTION_MOBILE_LIST
=
new
String
[]{};
private
static
final
int
STAGE
=
50
;
private
static
final
String
WECHAT_ROBOT_ADDRESS
=
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=664bf154-5da9-4615-8043-a396c43301ac"
;
private
static
Cache
<
String
,
CountExpireValue
>
COUNT_RECORDS_CACHE
=
Caffeine
.
newBuilder
()
.
expireAfterWrite
(
1
,
TimeUnit
.
DAYS
)
.
maximumSize
(
1000
)
.
build
();
/**
* 错误消息推送
*
* @param message
* @param throwable
* @return
*/
public
static
String
pushErrorMessage
(
String
message
,
Throwable
throwable
)
{
// if (com.zhiwei.pushlog.tools.Tools.isEmpty(LogConfig.getAddress()) && LogConfig.loadProperties()) {
// throw new IllegalArgumentException("push.robot.address is null");
// }
if
(!
LogConfig
.
getEnable
()){
return
null
;
}
if
(
Objects
.
nonNull
(
throwable
)
&&
!
timeFilter
(
throwable
.
getClass
().
getName
()))
{
return
null
;
}
JSONObject
data
=
new
JSONObject
();
JSONObject
markdown
=
new
JSONObject
();
markdown
.
put
(
"content"
,
getMarkDownMessage
(
message
,
throwable
));
markdown
.
put
(
"mentioned_mobile_list"
,
MENTION_MOBILE_LIST
);
data
.
put
(
"msgtype"
,
"markdown"
);
data
.
put
(
"markdown"
,
markdown
);
// 缓存超时信息清除
if
(
Objects
.
nonNull
(
throwable
))
{
invalidate
(
throwable
.
getClass
().
getName
());
}
return
HttpClientUtils
.
httpPostJson
(
WECHAT_ROBOT_ADDRESS
,
data
.
toJSONString
());
}
/**
* pushCommonMessage
*
* @param message
* @return
*/
public
static
String
pushCommonMessage
(
String
message
)
{
// if (com.zhiwei.pushlog.tools.Tools.isEmpty(LogConfig.getAddress()) && LogConfig.loadProperties()) {
// throw new IllegalArgumentException("push.robot.address is null");
// }
if
(!
LogConfig
.
getEnable
()){
return
null
;
}
if
(
Objects
.
isNull
(
message
)
||
!
timeFilter
(
message
))
{
return
null
;
}
JSONObject
data
=
new
JSONObject
();
JSONObject
markdown
=
new
JSONObject
();
markdown
.
put
(
"content"
,
getMarkDownMessageCommon
(
message
));
markdown
.
put
(
"mentioned_mobile_list"
,
MENTION_MOBILE_LIST
);
data
.
put
(
"msgtype"
,
"markdown"
);
data
.
put
(
"markdown"
,
markdown
);
// 缓存超时信息清除
invalidate
(
message
);
return
HttpClientUtils
.
httpPostJson
(
WECHAT_ROBOT_ADDRESS
,
data
.
toJSONString
());
}
/**
* timeFilter
*
* @param exceptionName
* @return
*/
private
static
boolean
timeFilter
(
String
exceptionName
)
{
boolean
b
=
Objects
.
isNull
(
COUNT_RECORDS_CACHE
.
getIfPresent
(
exceptionName
));
if
(
b
)
{
// time 数值
CountExpireValue
value
=
new
CountExpireValue
(
System
.
currentTimeMillis
(),
LogConfig
.
getInterval
(),
1
);
COUNT_RECORDS_CACHE
.
put
(
exceptionName
,
value
);
}
else
{
CountExpireValue
value
=
COUNT_RECORDS_CACHE
.
getIfPresent
(
exceptionName
);
// 判断过期
if
(
Objects
.
nonNull
(
value
))
{
if
(
value
.
getTime
()
+
value
.
getExpire
()
<
System
.
currentTimeMillis
())
{
// 过期
return
true
;
}
else
{
// 累计
value
=
new
CountExpireValue
(
value
.
getTime
(),
value
.
getExpire
(),
value
.
getValue
()
+
1
);
COUNT_RECORDS_CACHE
.
put
(
exceptionName
,
value
);
}
}
}
return
b
;
}
/**
* timeoutCache invalidate
*
* @param exceptionName
*/
private
static
void
invalidate
(
String
exceptionName
)
{
CountExpireValue
value
=
COUNT_RECORDS_CACHE
.
getIfPresent
(
exceptionName
);
if
(
Objects
.
nonNull
(
value
)
&&
(
value
.
getTime
()
+
value
.
getExpire
()
<
System
.
currentTimeMillis
()))
{
COUNT_RECORDS_CACHE
.
invalidate
(
exceptionName
);
}
}
/**
* getMarkDownMessage
*
* @param message
* @param throwable
* @return
*/
public
static
String
getMarkDownMessage
(
String
message
,
Throwable
throwable
)
{
StringBuilder
stringBuilder
=
getPushHeader
(
"error"
);
String
stackTrace
=
!
com
.
zhiwei
.
pushlog
.
tools
.
Tools
.
isEmpty
(
throwable
)
?
getStackTrace
(
throwable
.
getStackTrace
())
:
"无"
;
String
exceptionType
=
!
com
.
zhiwei
.
pushlog
.
tools
.
Tools
.
isEmpty
(
throwable
)
?
throwable
.
getClass
().
getName
()
:
"无"
;
String
localizedMessage
=
!
com
.
zhiwei
.
pushlog
.
tools
.
Tools
.
isEmpty
(
throwable
)
?
throwable
.
getLocalizedMessage
()
:
"无"
;
stringBuilder
.
append
(
">"
).
append
(
"异常类型:"
).
append
(
"**"
).
append
(
exceptionType
).
append
(
"**\n"
);
stringBuilder
.
append
(
">"
).
append
(
"错误信息:"
).
append
(
"**"
).
append
(
message
).
append
(
"**\n"
);
stringBuilder
.
append
(
">"
).
append
(
"异常信息:"
).
append
(
localizedMessage
).
append
(
"\n"
);
CountExpireValue
countExpireValue
=
!
com
.
zhiwei
.
pushlog
.
tools
.
Tools
.
isEmpty
(
throwable
)
?
COUNT_RECORDS_CACHE
.
getIfPresent
(
throwable
.
getClass
().
getName
())
:
null
;
if
(!
Tools
.
isEmpty
(
countExpireValue
)
&&
countExpireValue
.
getValue
()
>
1
)
{
stringBuilder
.
append
(
">"
).
append
(
"相同异常统计过期前,累计出现次数:"
).
append
(
countExpireValue
.
getValue
()).
append
(
"\n"
);
}
stringBuilder
.
append
(
">"
).
append
(
"堆栈信息:\n"
).
append
(
"<font color=\"comment\">"
).
append
(
stackTrace
).
append
(
"</font>\n"
);
return
stringBuilder
.
toString
();
}
/**
* getMarkDownMessageCommon
*
* @param message
* @return
*/
private
static
String
getMarkDownMessageCommon
(
String
message
)
{
StringBuilder
stringBuilder
=
getPushHeader
(
"common"
);
stringBuilder
.
append
(
">"
).
append
(
"预警信息:"
).
append
(
"**"
).
append
(
message
).
append
(
"**\n"
);
return
stringBuilder
.
toString
();
}
/**
* getPushHeader
*
* @param type
* @return
*/
public
static
StringBuilder
getPushHeader
(
String
type
)
{
StringBuilder
stringBuilder
=
new
StringBuilder
(
"本机信息:"
);
try
{
String
header
=
"error"
.
equals
(
type
)
?
"异常推送预警\n"
:
"日常预警推送\n"
;
InetAddress
localHost
=
Inet4Address
.
getLocalHost
();
stringBuilder
.
append
(
localHost
.
getHostAddress
()).
append
(
"\n"
).
append
(
LogConfig
.
getAppName
()).
append
(
" "
).
append
(
header
);
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"推送出错"
);
e
.
printStackTrace
();
}
return
stringBuilder
;
}
/**
* getStackTrace
*
* @param stackTraceElements
* @return
*/
private
static
String
getStackTrace
(
StackTraceElement
[]
stackTraceElements
)
{
StringBuilder
stringBuilder
=
new
StringBuilder
();
if
(
stackTraceElements
.
length
>
0
)
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
stringBuilder
.
append
(
stackTraceElements
[
i
].
toString
());
if
(
i
!=
4
)
{
stringBuilder
.
append
(
"\n"
);
}
}
}
return
stringBuilder
.
toString
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment