SLSshit

none

  1. // ==UserScript==
  2. // @name SLSshit
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2.1
  5. // @description none
  6. // @author BQsummer
  7. // @include https://sls.console.aliyun.com/lognext/project/*/logsearch/spring-syslog?*
  8. // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. $(document).ready(function(){
  15. hide_row_log();
  16. add_css();
  17.  
  18. // 查询按钮点击后移除之前的日志
  19. // $("span[class^='SqlRow__style__search-words']").eq(0).click( function () {
  20. // $(".log_context").remove();
  21. // });
  22. // // 页面跳转移除之前日志
  23. // $(document).on('click','.next-pagination-item',function(){
  24. // $(".log_context").remove();
  25. // });
  26. // $(document).on('click','.next-select-menu-item',function(){
  27. // $(".log_context").remove();
  28. // // FIXME 回到顶部不生效
  29. // $("div[class^='BackTop__style__back-top-btn']").click();
  30. // });
  31. // 拦截日志查询接口
  32. const originFetch = fetch;
  33. unsafeWindow.fetch = async (url, request) => {
  34. const response = await originFetch(url, request)
  35. if (url.indexOf('logstoreindex/getLogs.json') > -1) {
  36. try {
  37. const text = await response.clone().text()
  38. response.text = () => { return new Promise((resolve) => { resolve(text) }) }
  39. const res = JSON.parse(text);
  40. // 清除上一次日志
  41. $(".log_context").remove();
  42. show_log(res);
  43. } catch (e) {
  44. console.error(e)
  45. }
  46. }
  47. return response;
  48. }
  49.  
  50.  
  51. });
  52.  
  53. // 自定义日志展示
  54. function show_log(res) {
  55. let table = "";
  56. let logs = res.data.logs;
  57. // 处理terms
  58. let terms = mapTerms(res.data.terms);
  59. for(let log in logs){
  60. let summary_div = create_summary(logs[log]);
  61. let message_div = create_div(text_format(logs[log], terms), 'message_div_style');
  62. let detail_div = create_div(create_detail(logs[log], terms), 'detail_div_style');
  63. table += "<div class='blur_hide_150 log_context'>" + summary_div + message_div + detail_div + "</div>";
  64. }
  65. // 加载所有日志
  66. $("div[class^='RawLog__style__data-content']").children().eq(1).append(table);
  67. // 箭头添加监听器
  68. if($("div[class='arrow']") != undefined) {
  69. $("div[class='arrow']").click(function(){
  70. arrow_click($(this));
  71. return false;
  72. });
  73. }
  74. // 日志详情隐藏
  75. $(".detail_div_style").hide();
  76. }
  77.  
  78. // 检索的关键字,倒换valu和key
  79. function mapTerms(terms) {
  80. if(terms.length >0) {
  81. let keyValueMap = new Map();
  82. for (let term of terms) {
  83. keyValueMap.set(term[1], term[0]);
  84. }
  85. return keyValueMap;
  86. }
  87. return new Map();
  88. }
  89.  
  90. // 隐藏sls原始日志(不能remove,原生代码会报错)
  91. function hide_row_log() {
  92. $("div[class^='RawLog__style__loglist-content']").eq(0).css({"display":"none" });
  93. }
  94.  
  95. // 添加自定义样式
  96. function add_css() {
  97. $('body').append("<style>" + style + "</style>");
  98. }
  99.  
  100. // 创建div
  101. function create_div(message, ...clazzs) {
  102. let clazzTxt = "";
  103. clazzs.forEach((clazz) => {
  104. clazzTxt = clazzTxt + clazz + " ";
  105. })
  106. return "<div class='"+ clazzTxt + "'>" + message + "</div>";
  107. }
  108.  
  109. //
  110. function text_format(log, terms) {
  111. let text = log.message;
  112. // normal日志,错误堆栈信息做换行处理
  113. if (text !== undefined) {
  114. //text = line_wrap(text);
  115. } else {
  116. // 非normal日志
  117. let logBuilder = log.logtime + " [" + log.context + "|" + log.nodeIp + "|" + log.port + "] [" + log.thread + "] [" + log.className + "] [" + log.level + "] [" + log.line + "] - {";
  118. for (let val in log) {
  119. if(val.startsWith("message_json") && !val.includes('commonRequestParameters')) {
  120. logBuilder = logBuilder + '"' + val.substring(13) + '" : "' + log[val] + '",'
  121. }
  122. }
  123. if (logBuilder.endsWith(",")) {
  124. logBuilder = logBuilder.substr(0, logBuilder.length-1);
  125. }
  126. text = logBuilder + "}";
  127. //text = line_wrap(text);
  128. }
  129. // 搜索关键字加粗加红
  130. if(terms.size >0) {
  131. for (let [key, value] of terms) {
  132. let key_word = value.replace('\*', '');
  133. if (key_word != '') {
  134. text = blod_keys(text, key_word);
  135. }
  136. }
  137. }
  138. return text;
  139. }
  140.  
  141. // 换行符替换
  142. function line_wrap(text) {
  143. // console.log("wrap");
  144. text = text.replace(/(\n)/g, '<br />');
  145. text = text.replace(/(\t)/g,'&nbsp;&nbsp;&nbsp;&nbsp;');
  146. return text;
  147. }
  148.  
  149. // 检索关键字加粗加红(预览的日志是替换,不准确),忽略大小写
  150. function blod_keys(text, key) {
  151. let reg_str = '(' + key + ')';
  152. return text.replace(new RegExp(reg_str, 'ig'), "<b style='color:red'>" + key + "</b>");
  153. }
  154.  
  155. // 日志详情展开
  156. function arrow_click(navice_dom) {
  157. let arrow_dom = $(navice_dom).children().eq(0);
  158. if(arrow_dom.hasClass('down_arrow')) {
  159. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).removeClass('blur_hide_150');
  160. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).children().eq(1).addClass('blur_hide_120');
  161. arrow_dom.removeClass('down_arrow');
  162. arrow_dom.addClass('up_arrow');
  163. arrow_dom.addClass('arrow_reverse');
  164. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).children().eq(2).show();
  165. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).addClass('group_msg');
  166. } else {
  167. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).addClass('blur_hide_150');
  168. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).children().eq(1).removeClass('blur_hide_120');
  169. arrow_dom.removeClass('up_arrow');
  170. arrow_dom.addClass('down_arrow');
  171. arrow_dom.removeClass('arrow_reverse');
  172. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).children().eq(2).hide();
  173. arrow_dom.parent().eq(0).parent().eq(0).parent().eq(0).removeClass('group_msg');
  174. }
  175. }
  176.  
  177. // 日志概览
  178. function create_summary(log) {
  179. let down = "<div class='arrow'><svg viewBox='0 0 2700 2500' preserveAspectRatio='xMinYMin' class='down_arrow' width='15px' height='15px'><path d='M1995.591408 0c11.518934 0 22.525916 3.583669 31.485087 9.983077a46.075738 46.075738 0 0 1 17.918343 53.755027l-7.67929 13.822722-971.942095 927.146239a55.546862 55.546862 0 0 1-70.905441 10.751005l-12.030887-10.751005L10.751006 77.560826A46.075738 46.075738 0 0 1 0 48.635501C0 26.109585 16.126508 7.423313 38.396448 1.791834L52.21917 0h1943.372238z'></path></svg></div>"
  180. let logtime_div = create_div(log.logtime, 'summary_ele_div_style');
  181. let host_div = create_div(log.host, 'summary_ele_div_style');
  182. let topic_div = create_div(log.topic, 'summary_ele_div_style');
  183. let context_div = create_div(log.context, 'summary_ele_div_style');
  184. let summary_div = create_div(down + logtime_div + host_div + topic_div, 'summary_div_style');
  185. return summary_div;
  186. }
  187.  
  188. // 日志详情
  189. function create_detail(log, terms) {
  190. let detail = "";
  191. for (let val in log) {
  192. if(!val.startsWith("__")) {
  193. let log_detail = log[val];
  194. if (terms.get(val) != undefined) {
  195. let key = terms.get(val).replace('\*', '');
  196. if (key != '') {
  197. let reg_str = '(' + key + ')';
  198. log_detail = log_detail.replace(new RegExp(reg_str, 'ig'), "<b style='color:red'>" + key + "</b>");
  199. }
  200. }
  201. let col = create_div(val, 'col_style');
  202. let value = create_div(line_wrap(log_detail), 'col_value_style');
  203. detail += create_div(col + " : " + line_wrap(value), 'col_and_value_style');
  204. }
  205. }
  206. return detail;
  207. }
  208.  
  209.  
  210.  
  211. var style = `
  212. .log_context {
  213. border-color:#dbe3d9;
  214. border-bottom-style:solid;
  215. border-bottom-width:1px;
  216.  
  217. padding-bottom:10px;
  218. padding-left:13px;
  219. padding-right:13px;
  220. padding-top:10px;
  221. font-size:12px;
  222.  
  223. word-break: break-all;
  224. }
  225. .blur_hide_150 {
  226. max-height:150px;
  227. overflow-y:hidden;
  228. text-overflow:ellipsis;
  229. background:linear-gradient(180deg, rgba(255,255,255,0) 110px, #f5f5f6 125px, #cccccc 150px);
  230. }
  231. .blur_hide_120 {
  232. max-height:120px;
  233. overflow-y:hidden;
  234. text-overflow:ellipsis;
  235. background:linear-gradient(180deg, rgba(255,255,255,0) 90px, #f5f5f6 100px, #cccccc 120px);
  236. }
  237. .max_height_150 {
  238. max-height:150px;
  239. }
  240. .summary_div_style{
  241. display:flex;
  242. justify-content:flex-start;
  243. font-weight:bold;
  244. margin-bottom:7px;
  245. }
  246. .message_div_style{
  247. }
  248. .summary_ele_div_style{
  249. display:flex;
  250. flex-grow:1;
  251. margin-left:30px;
  252. margin-right:30px;
  253. }
  254. .arrow {
  255. width:15px;
  256. height:15px;
  257. }
  258. .down_arrow {
  259.  
  260. }
  261. .up_arrow {
  262.  
  263. }
  264. .col_style {
  265. display: inline;
  266. background:rgba(0,86,144,.1);
  267. padding: 1px 3px!important;
  268. margin: 2px 0;
  269. line-height: 19px;
  270. }
  271. .col_value_style {
  272. display: inline;
  273. padding: 1px 3px!important;
  274. margin: 2px 0;
  275. line-height: 19px;
  276. }
  277. .col_and_value_style {
  278.  
  279. }
  280. .arrow_reverse {
  281. transform: rotate(180deg);
  282. }
  283. .group_msg {
  284. border-left-width:5px;
  285. border-left-color:#cccccc;
  286. border-left-style:solid;
  287. }
  288. `;
  289.  
  290. })();