wxworkwarn.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package timetask
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/donnie4w/go-logger/logger"
  6. "math"
  7. "net/http"
  8. qu "qfw/util"
  9. "strings"
  10. "sync"
  11. "time"
  12. "util"
  13. )
  14. var UserMap map[string]map[string]string
  15. var PythonModifyUserInfoMap map[string]*UserInfo //开发人员信息集合
  16. var LuaModifyUserInfoMap map[string]*UserInfo //开发人员信息集合
  17. var LuaAuditorInfoMap map[string]*UserInfo //审核人员信息集合
  18. //lua
  19. type LuaUserTextInfo struct {
  20. Username string
  21. FailedTaskCount int
  22. FailedTaskOverdueDay int
  23. HeartErrCount int
  24. NoCollectDataDay int
  25. }
  26. //python
  27. type PythonUserTextInfo struct {
  28. Username string
  29. ToBeCompleted int //待完成爬虫个数
  30. Failed int //未通过爬虫个数
  31. }
  32. type UserInfo struct {
  33. Username string
  34. UserID string
  35. Email string
  36. Mobile string
  37. Auth string
  38. }
  39. //
  40. var LuaTitleContentModel = `
  41. 截止目前,爬虫共有未通过任务<font color=\"warning\">%d个</font>,异常心跳爬虫<font color=\"warning\">%d个</font>。请及时处理!\n
  42. `
  43. var PythonTitleContentModel = `
  44. 截止目前,共有待完成爬虫<font color=\"warning\">%d个</font>,未通过爬虫<font color=\"warning\">%d个</font>,待审核爬虫<font color=\"warning\">%d个</font>。请及时处理!\n
  45. `
  46. var LuaUserContentModel = `
  47. >人员:<font color=\"warning\">%s</font>
  48. >未通过任务:<font color=\"warning\">%d个</font><font color=\"info\">(最早任务已逾期%d天)</font>
  49. >异常心跳爬虫:<font color=\"warning\">%d个</font><font color=\"info\">(已有爬虫%d天未采集数据)</font>\n
  50. `
  51. var PythonUserContentModel = `
  52. >人员:<font color=\"warning\">%s</font>
  53. >待完成爬虫:<font color=\"warning\">%d个</font><font color=\"info\"></font>
  54. >未通过爬虫:<font color=\"warning\">%d个</font><font color=\"info\"></font>\n
  55. `
  56. var MarkdownModel = `{
  57. "msgtype": "markdown",
  58. "markdown": {
  59. "content": "%s"
  60. }
  61. }`
  62. var TextModel = `{
  63. "msgtype": "text",
  64. "text": {
  65. "content": "%s",
  66. "mentioned_mobile_list":[%s]
  67. }
  68. }`
  69. //初始化人员信息
  70. func GetLuaUserInfo() {
  71. LuaModifyUserInfoMap = map[string]*UserInfo{}
  72. LuaAuditorInfoMap = map[string]*UserInfo{}
  73. PythonModifyUserInfoMap = map[string]*UserInfo{}
  74. for eu, info := range UserMap {
  75. role := info["role"]
  76. auth := info["auth"]
  77. if role == "lua" {
  78. if auth == "1" { //开发人员
  79. LuaModifyUserInfoMap[eu] = &UserInfo{
  80. Username: info["username"],
  81. UserID: info["userid"],
  82. Email: info["email"],
  83. Mobile: info["mobile"],
  84. Auth: auth,
  85. }
  86. }
  87. if auth == "3" || eu == "ssc" { //审核人员
  88. LuaAuditorInfoMap[eu] = &UserInfo{
  89. Username: info["username"],
  90. Mobile: info["mobile"],
  91. Auth: auth,
  92. }
  93. }
  94. } else {
  95. if auth == "1" {
  96. PythonModifyUserInfoMap[eu] = &UserInfo{
  97. Username: info["username"],
  98. Mobile: info["mobile"],
  99. Auth: auth,
  100. }
  101. }
  102. }
  103. }
  104. //
  105. index := 0
  106. for name, _ := range LuaModifyUserInfoMap {
  107. LuaUserIndexMap[index] = name
  108. index++
  109. }
  110. LuaUserNum = index
  111. qu.Debug(LuaModifyUserInfoMap)
  112. qu.Debug(LuaAuditorInfoMap)
  113. qu.Debug(PythonModifyUserInfoMap)
  114. qu.Debug(LuaUserIndexMap, LuaUserNum)
  115. }
  116. // 统计爬虫开发人员未完成爬虫和任务
  117. func SendInfoToWxWork_Tomodifyuser() {
  118. SendLuaInfo()
  119. SendPythonInfo()
  120. SendPrivateInfo()
  121. }
  122. func SendLuaInfo() {
  123. defer qu.Catch()
  124. qu.Debug("lua企业微信发送提示信息")
  125. failedTaskCount, heartCodeCount := 0, 0 //总未通过任务个数,总待处理心跳异常爬虫个数
  126. luaUserTextMap := map[string]*LuaUserTextInfo{} //key:mobile
  127. for user, userInfo := range LuaModifyUserInfoMap {
  128. textInfo := &LuaUserTextInfo{}
  129. textInfo.Username = userInfo.Username
  130. //1、未通过任务信息
  131. list_task, _ := util.MgoEB.Find("task",
  132. map[string]interface{}{"s_modify": user, "i_state": 5},
  133. map[string]interface{}{"l_complete": 1},
  134. map[string]interface{}{"l_complete": 1},
  135. false, -1, -1)
  136. taskLen := len(*list_task)
  137. textInfo.FailedTaskCount = taskLen //个人未通过任务个数赋值
  138. failedTaskCount += taskLen //总未通过个数++
  139. if taskLen > 0 {
  140. complete := qu.Int64All((*list_task)[0]["l_complete"]) //未通过任务中最迟完成时间最早的任务
  141. odDay := int(math.Floor(float64(time.Now().Unix()-complete) / float64(86400)))
  142. textInfo.FailedTaskOverdueDay = odDay //个人未通过任务最早逾期天数赋值
  143. }
  144. //2、爬虫心跳信息
  145. query := map[string]interface{}{
  146. "modifyuser": user,
  147. "del": false,
  148. //"list": map[string]interface{}{
  149. // "$lte": util.GetTime(0),
  150. //},
  151. "$or": []interface{}{
  152. map[string]interface{}{
  153. "event": map[string]interface{}{
  154. "$nin": []int{7000, 7520},
  155. //"$nin": []int{7500, 7510},
  156. },
  157. "list": map[string]interface{}{
  158. "$lte": util.GetTime(0),
  159. },
  160. },
  161. map[string]interface{}{
  162. "event": 7520,
  163. //"event": map[string]interface{}{
  164. // "$in": []int{7500, 7510},
  165. //},
  166. "list": map[string]interface{}{
  167. "$lte": util.GetTime(-1),
  168. },
  169. },
  170. },
  171. }
  172. qu.Debug("heart query:", query)
  173. list_code, _ := util.MgoS.Find("spider_heart",
  174. query,
  175. map[string]interface{}{"list": 1},
  176. map[string]interface{}{"list": 1},
  177. false, -1, -1)
  178. codeLen := len(*list_code)
  179. textInfo.HeartErrCount = codeLen //个人异常心跳爬虫个数赋值
  180. heartCodeCount += codeLen //总异常心跳爬虫个数++
  181. if codeLen > 0 {
  182. listTime := qu.Int64All((*list_code)[0]["list"]) //未通过任务中最迟完成时间最早的任务
  183. ncDay := int(math.Floor(float64(time.Now().Unix()-listTime) / float64(86400)))
  184. textInfo.NoCollectDataDay = ncDay //个人未通过任务最早逾期天数赋值
  185. }
  186. luaUserTextMap[userInfo.Mobile] = textInfo
  187. }
  188. //拼接content
  189. resultContent := fmt.Sprintf(LuaTitleContentModel, failedTaskCount, heartCodeCount)
  190. mobileArr := []string{}
  191. for mobile, t := range luaUserTextMap {
  192. mobileArr = append(mobileArr, "\""+mobile+"\"")
  193. resultContent += fmt.Sprintf(LuaUserContentModel, t.Username, t.FailedTaskCount, t.FailedTaskOverdueDay, t.HeartErrCount, t.NoCollectDataDay)
  194. }
  195. msg := fmt.Sprintf(MarkdownModel, resultContent)
  196. qu.Debug("msg", msg)
  197. toUserMsg := fmt.Sprintf(TextModel, "", strings.Join(mobileArr, ","))
  198. qu.Debug("toUserMsg", toUserMsg)
  199. resp1, err := http.Post(
  200. "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=97850772-88d0-4544-a2c3-6201aeddff9e",
  201. "application/json",
  202. bytes.NewBuffer([]byte(toUserMsg)),
  203. )
  204. if err != nil {
  205. fmt.Println("request error:", err)
  206. return
  207. }
  208. defer resp1.Body.Close()
  209. resp2, err := http.Post(
  210. "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=97850772-88d0-4544-a2c3-6201aeddff9e",
  211. "application/json",
  212. bytes.NewBuffer([]byte(msg)),
  213. )
  214. if err != nil {
  215. fmt.Println("request error:", err)
  216. return
  217. }
  218. defer resp2.Body.Close()
  219. }
  220. func SendPythonInfo() {
  221. defer qu.Catch()
  222. qu.Debug("python企业微信发送提示信息")
  223. toBeCompletedAllCount, failedAllCount := 0, 0
  224. toBeReviewedAllCount := util.MgoEB.Count("luaconfig", map[string]interface{}{"state": 1, "platform": "python"})
  225. pythonUserTextMap := map[string]*PythonUserTextInfo{} //key:mobile
  226. for user, userInfo := range PythonModifyUserInfoMap {
  227. textInfo := &PythonUserTextInfo{}
  228. textInfo.Username = userInfo.Username
  229. //1、待完成爬虫个数
  230. textInfo.ToBeCompleted = util.MgoEB.Count("luaconfig", map[string]interface{}{"state": 0, "modifyuser": user})
  231. toBeCompletedAllCount += textInfo.ToBeCompleted
  232. //2、未通过爬虫个数
  233. textInfo.Failed = util.MgoEB.Count("luaconfig", map[string]interface{}{"state": 2, "modifyuser": user})
  234. failedAllCount += textInfo.Failed
  235. pythonUserTextMap[userInfo.Mobile] = textInfo
  236. }
  237. //拼接content
  238. resultContent := fmt.Sprintf(PythonTitleContentModel, toBeCompletedAllCount, failedAllCount, toBeReviewedAllCount)
  239. mobileArr := []string{}
  240. for mobile, t := range pythonUserTextMap {
  241. mobileArr = append(mobileArr, "\""+mobile+"\"")
  242. resultContent += fmt.Sprintf(PythonUserContentModel, t.Username, t.ToBeCompleted, t.Failed)
  243. }
  244. msg := fmt.Sprintf(MarkdownModel, resultContent)
  245. qu.Debug("msg", msg)
  246. toUserMsg := fmt.Sprintf(TextModel, "", strings.Join(mobileArr, ","))
  247. qu.Debug("toUserMsg", toUserMsg)
  248. resp1, err := http.Post(
  249. "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=97850772-88d0-4544-a2c3-6201aeddff9e",
  250. "application/json",
  251. bytes.NewBuffer([]byte(toUserMsg)),
  252. )
  253. if err != nil {
  254. fmt.Println("request error:", err)
  255. return
  256. }
  257. defer resp1.Body.Close()
  258. resp2, err := http.Post(
  259. "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=97850772-88d0-4544-a2c3-6201aeddff9e",
  260. "application/json",
  261. bytes.NewBuffer([]byte(msg)),
  262. )
  263. if err != nil {
  264. fmt.Println("request error:", err)
  265. return
  266. }
  267. defer resp2.Body.Close()
  268. }
  269. //每日统计列表页、详情页分开采集模式节点爬虫详情页采集心跳异常信息
  270. func SendPrivateInfo() {
  271. defer qu.Catch()
  272. var eventArr []int //节点集合
  273. eventNumMap := map[int]int{}
  274. for event, model := range util.CodeEventModel {
  275. if model == 1 {
  276. eventArr = append(eventArr, event)
  277. }
  278. }
  279. query := map[string]interface{}{
  280. "event": map[string]interface{}{
  281. "$in": eventArr,
  282. },
  283. "del": false,
  284. }
  285. fields := map[string]interface{}{
  286. "event": 1,
  287. "detail": 1,
  288. }
  289. logger.Info("query:", query)
  290. lock := &sync.Mutex{}
  291. wg := &sync.WaitGroup{}
  292. ch := make(chan bool, 2)
  293. sess := util.MgoS.GetMgoConn()
  294. defer util.MgoS.DestoryMongoConn(sess)
  295. it := sess.DB(util.MgoS.DbName).C("spider_heart").Find(&query).Select(&fields).Iter()
  296. n := 0
  297. for tmp := make(map[string]interface{}); it.Next(tmp); n++ {
  298. wg.Add(1)
  299. ch <- true
  300. go func(tmp map[string]interface{}) {
  301. defer func() {
  302. <-ch
  303. wg.Done()
  304. }()
  305. detailTime := qu.Int64All(tmp["detail"])
  306. if time.Now().Unix()-detailTime > 3600*3 { //统计超过3小时前爬虫个数
  307. event := qu.IntAll(tmp["event"])
  308. lock.Lock()
  309. eventNumMap[event] += 1
  310. lock.Unlock()
  311. }
  312. }(tmp)
  313. if n%100 == 0 {
  314. logger.Debug(n)
  315. }
  316. tmp = map[string]interface{}{}
  317. }
  318. wg.Wait()
  319. logger.Info(eventNumMap)
  320. content := ""
  321. for event, num := range eventNumMap {
  322. if num >= 10 {
  323. content += "节点:" + fmt.Sprint(event) + "详情页执行心跳异常个数:" + fmt.Sprint(num) + ";"
  324. }
  325. }
  326. if content != "" {
  327. toMyself := fmt.Sprintf(TextModel, content, "15637845493")
  328. logger.Info("toMyself", toMyself)
  329. resp, err := http.Post(
  330. "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=97850772-88d0-4544-a2c3-6201aeddff9e",
  331. "application/json",
  332. bytes.NewBuffer([]byte(toMyself)),
  333. )
  334. if err != nil {
  335. fmt.Println("request error:", err)
  336. return
  337. }
  338. defer resp.Body.Close()
  339. }
  340. }
  341. // 统计爬虫审核人员待审核爬虫
  342. func SendInfoToWxWork_ToAuditor() {
  343. defer qu.Catch()
  344. qu.Debug("企业微信发送提示信息")
  345. tmpContent := "当前"
  346. tmpModifyList := []string{}
  347. qu.Debug(LuaAuditorInfoMap)
  348. for eu, userInfo := range LuaAuditorInfoMap {
  349. query := map[string]interface{}{
  350. "state": 1,
  351. "platform": "golua平台",
  352. }
  353. if eu == "niehaiyang" { //王丹婷审核的施顺才的爬虫
  354. query["modifyuser"] = map[string]interface{}{
  355. "$eq": "ssc",
  356. }
  357. } else {
  358. query["modifyuser"] = map[string]interface{}{
  359. "$ne": "ssc",
  360. }
  361. }
  362. count := util.MgoEB.Count("luaconfig", query)
  363. tmpContent += userInfo.Username + "需审核的爬虫有:" + fmt.Sprint(count) + "个;"
  364. tmpModifyList = append(tmpModifyList, userInfo.Mobile)
  365. }
  366. msg := fmt.Sprintf(TextModel, tmpContent+"请及时处理!", strings.Join(tmpModifyList, ","))
  367. qu.Debug("msg", msg)
  368. resp1, err := http.Post(
  369. "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=97850772-88d0-4544-a2c3-6201aeddff9e",
  370. "application/json",
  371. bytes.NewBuffer([]byte(msg)),
  372. )
  373. if err != nil {
  374. fmt.Println("request error:", err)
  375. return
  376. }
  377. defer resp1.Body.Close()
  378. }