Greasy Fork is available in English.

Airflow log hightlight library

A library of airflow log highlight for airflow helper

Dette script skal ikke installes direkte. Det er et API for andre scripts der skal inkluderes med meta direktiv // @require https://update.greasyfork.org/scripts/460424/1152786/Airflow%20log%20hightlight%20library.js

// ==UserScript==
// @name           Airflow log hightlight library
// @namespace      https://greasyfork.org/zh-CN/scripts/430272-airflow-log-hightlight-lib
// @description    A library of airflow log highlight for airflow helper
// @include        http://airflow.yimian.com.cn/*
// @include        http://airflow.onework.yimian.com.cn/*
// @include        http://172.16.24.11:18080/*
// @grant          GM_log
// @grant          GM_xmlhttpRequest
// @grant          GM_getValue
// @grant          GM_setValue
// @grant          GM_openInTab
// @grant          GM_registerMenuCommand
// @version        0.1.4
// ==/UserScript==
;(function () {
	var isOpera = !!this.opera,
		isChromium = !!this.chromium;
	var STYLE_COLOR = ['#FFFF80','#99ccff','#ff99cc','#66cc66','#cc99ff','#ffcc66','#66aaaa','#dd9966','#aaaaaa','#dd6699'];
	var BORDER_COLOR = ['#aaaa20','#4477aa','#aa4477','#117711','#7744aa','#aa7711','#115555','#884411','#555555','#881144'];
	var but_c = '#99cc99', but_ca = '#FFD000', but_cd = '#999999', but_cb = '#669966'; // button normal/active/disable background color/border color.
 
	// Initialize value
	var PRE = 'wordhighlight', ID_PRE = PRE + '_id';
	var STYLE_CLASS = '0123456789'.split('').map(function(a,i){return PRE + '_word'+i;});

	var keyword = "AnalysisException|ValueError|TypeError|ProgrammingError|JSONDecodeError|AnalysisException|NameError|IndentationError|KeyError|IndexError|AttributeError|FileNotFoundError|\
ConnectionError|HTTPError|Received SIGTERM|SyntaxError|OutOfMemory|Container killed by YARN for exceeding memory limits|Failed to get minimum memory|\
Permission denied|Memory limit exceeded|Could not resolve table reference|Could not resolve column/field reference|File does not exist|RemoteException|\
TExecuteStatementResp|object has no attribute|InternalError|NullPointerException|ConnectionError|Failed to close HDFS|cannot be null|IntegrityError|\
ArrayIndexOutOfBoundsException|has more columns|Unknown column|No such file or directory|Out Of Memory|RuntimeError|Traceback|AirflowTaskTimeout|AssertionError|\
Check 'stl_load_errors' system table for details|OperationalError|Lost connection to MySQL server during query|AirflowTaskTimeout|files cols number not match target file cols number, check it|\
Data too long for column|DataError|Initial job has not accepted any resources|/tmp/oneflow_|http://oneflow.yimian.com.cn/dag|num_dumped_rows|com.yimian.etl"
  var words = [];
	var words_off = [];

	// 创建一个观察器实例并传入回调函数
  const observer1 = new MutationObserver(setup);
  const observer2 = new MutationObserver(setup);

	if (window.location.href.includes('log')) {	
		init_keyword()
		observeTargetDOM()
	}

	function observeTargetDOM() {
    const logMenu = document.querySelectorAll('.nav.nav-pills')[3]
		const logContent = document.querySelector('.tab-content').lastChild.previousSibling
    const config = { childList: true, subtree: true, attributes: true };
    // 以上述配置开始观察目标节点
    observer1.observe(logMenu, config);
    observer2.observe(logContent, config);
  }

	function init_keyword() {
		keyword = trim(keyword);
		window.name = PRE + '::' + encodeURIComponent(keyword);
		words = init_words(keyword);
	}

	function setup() {
		addsheet();
		highlight(document.body)
		observer2.disconnect()
	}
 
	function highlight(doc) {
		const _words = words.filter((w,i) => !words_off[i]);
		if (_words.length <= 0) return;
		let exd_words, xw;
		if (_words.length === 1 && _words[0].exp) {
			exd_words = _words.map((e) => e.exp);
			xw = '';
		} else {
			exd_words = _words.map(function(w){return w.test ? w : new RegExp('(' + w.replace(/\W/g,'\\$&') + ')(?!##)', 'ig');});
			xw = ' and (' + _words.map(function(w){return ' contains(translate(self::text(),"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ"),'+escapeXPathExpr(w.toUpperCase())+') ';}).join(' or ') + ') ';
		}
		$X('descendant::text()[string-length(normalize-space(self::text())) > 0 ' + xw +' and not(ancestor::textarea or ancestor::script or ancestor::style or ancestor::aside)]', doc)
			.forEach(function(text_node) {
				let parent = text_node.parentNode;
				// 关键词父元素标签为span 说明已经被高亮过
				if (parent.tagName.toUpperCase() === 'SPAN') return;
				let df,
				text = text_node.nodeValue,
				id_index = 0,
				range = document.createRange(),
				replace_strings = [],
				new_text = reduce(exd_words, (text,ew,i) => {
					return text.replace(ew,($0,$1) => {
						replace_strings[id_index] = '<span id="' + ID_PRE + id_index + '" class="' + STYLE_CLASS[i%10] + '" name="'+PRE+'_word'+i+'">' + $1 + '</span>';
						return '##'+(id_index++)+'##';
					});
				}, text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/##(\d+)##/g, ($0,$1) => replace_strings[$1] || '');
				if (replace_strings.length) {
					try {
						if (isChromium) {
							const htmlDoc = document.implementation.createHTMLDocument('hogehoge');
							range.selectNodeContents(htmlDoc.documentElement);
						} else {
							range.selectNode(text_node);
						}
						df = range.createContextualFragment(new_text);
						console.log('df', df);
						if (df.firstChild) parent.replaceChild(df, text_node);
						range.detach();
					} catch (e) {
						error(e);
					}
				}
			});
	}
 
	function addsheet() {
		const hilistyles = STYLE_COLOR.map((rgb,i) => {
			return 'span.' + PRE + '_word'+i+',.' + PRE + '_item'+i+'{background:'+rgb+'!important;}';
			});
		const borderstyles = BORDER_COLOR.map((rgb,i) => {
			return 'li.' + PRE + '_item'+i+'{outline:1px solid '+rgb+'!important;}';
			});
		const panel_pos_arr = ['right:-1px;','bottom:-1px;'];
		sheet = addCSS([
			//Additional Style
			'span[class^="' + PRE + '_word"]{color:black!important;font:inherit!important;display:inline!important;margin:0!important;padding:0!important;text-align:inherit!important;float:none!important;position:static!important;}', //vertical-align:inherit !important;
			'#' + PRE + '_words, #' + PRE + '_words *{font-family: Arial ;}',
			'#' + PRE + '_words{line-height:1;position:fixed;z-index:60000;opacity:0.8;list-style-type:none;margin:0;padding:0;width:auto;max-width:100%;' + panel_pos_arr[0] + panel_pos_arr[1] +'}',
			'#' + PRE + '_words > section{clear:right;line-height:1;border:1px solid #666;/*border-left-width:10px;*/background:#fff;display:block;position:relative;}',
			'#' + PRE + '_words * {margin:0;padding:0;width:auto;height:auto;}',
			'#' + PRE + '_words:hover{opacity:1;}',
			'#' + PRE + '_words:hover > section{opacity:1;border-color:#333;}',
			'#' + PRE + '_words #_ewh_handle{background:#666;width:10px;cursor:move;}',
			'#' + PRE + '_words:hover #_ewh_handle{background:#333;}',
			'#' + PRE + '_words.ewh_hide #_ewh_handle{cursor:pointer;}',
//			'#' + PRE + '_words.ewh_hide:hover #_ewh_handle{width:10px;}',
//			'#' + PRE + '_words.ewh_hide > section form.' + PRE + '_ctrl > input.c_b{display:none;}',
			'#' + PRE + '_words > nav{display:none;width:100%;padding:3px;position:relative;}',
			'#' + PRE + '_words > nav > canvas.backport{background:rgba(0,0,0,0.5);cursor:pointer;position:absolute;right:6px;z-index:3;}',
			'#' + PRE + '_words > nav > canvas.viewport{background:rgba(79,168,255,0.7);cursor:default;position:absolute;bottom:0px;right:6px;}',//outline:6px solid rgba(79,168,255,0.7);
//			'#' + PRE + '_words > nav:hover > canvas.backport{background:rgba(0,0,0,0.5);}',
			'#' + PRE + '_words:hover > nav{display:block;}',
			'#' + PRE + '_words > nav._locked{display:block;}',
			'#' + PRE + '_words:hover > nav > canvas.backport{bottom:0px;}',
			'#' + PRE + '_words > nav._locked > canvas.backport{bottom:0px;}',
			'#' + PRE + '_words.ewh_edit{opacity:1;}',
			'#' + PRE + '_words.ewh_edit #' + PRE + '_word_inputs_list{display:none;}',
			'#' + PRE + '_words form.' + PRE + '_editor{display:none;}',
			'#' + PRE + '_words.ewh_edit form.' + PRE + '_editor{display:inline-block;}',
			'#' + PRE + '_words.ewh_edit form.' + PRE + '_editor input{min-width:80px;}',
			'#' + PRE + '_words li{display:inline-block;margin:0.1em 0.2em;line-height:1.3em;font-size:medium;}',
			'#' + PRE + '_words > section > * {vertical-align:middle;}',
			'#' + PRE + '_words > section td {border:none;}',
			'#' + PRE + '_words > section > h3.' + PRE + '_title{display:inline-block;background:#333;color:#fff;padding:0.1em 0.3em;border:none;margin:0 0.2em;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl{display:inline-block;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input{display:inline;width:1.3em;margin:0.1em 0.1em;background:'+ but_c +';border:1px solid '+ but_cb +';cursor:pointer;font-size:10pt;color:black;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input._active{background:'+ but_ca +';}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input._disable{background:'+ but_cd +' !important;cursor:default;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input:hover{outline:1px solid '+ but_cb +'!important;}',
			'#' + PRE + '_word_inputs_list {padding:0!important;margin:0.2em!important;display:inline-block;border:none!important;}',
			'#' + PRE + '_word_inputs_list > li{position:relative;padding:0 4px;}',
			'#' + PRE + '_word_inputs_list > li.ewh_disable{background:white!important;outline:1px solid #999!important;}',
			'#' + PRE + '_word_inputs_list > li > label{cursor:pointer;color:black!important;}',
			'#' + PRE + '_word_inputs_list > li > input{cursor:pointer;}',
//			'#' + PRE + '_word_inputs_list > li > label > input[type=image]{vertical-align:top;padding:0;height:12px;}',
			'#' + PRE + '_word_inputs_list > li > input[type=checkbox]{display:none;position:absolute;right:0px;top:0px;opacity:0.7;}',
			'#' + PRE + '_word_inputs_list > li:hover{outline-width:2px!important;}',
			'#' + PRE + '_word_inputs_list > li:hover > input[type=checkbox]{display:block;}',
			'#' + PRE + '_word_inputs_list > li > input[type=checkbox]:hover{opacity:1;}',
			'#' + PRE + '_words > section td+td+td > input {display:inline;width:1.3em;margin:0.1em 0.1em;background:#FAFAFA;border:1px solid #aaaaaa;cursor:pointer;font-size:10pt;color:black;}',
		].concat(hilistyles, borderstyles).join('\n'));
	}
 
	function trim(str) {
		return str.replace(/[\n\r]+/g,' ').replace(/^\s+|\s+$/g,'').replace(/\.+\s|\.+$/g,'');
	}
 
	function uniq(arr) {
		var a = [], o = {}, i, v, len = arr.length;
		if (len < 2) {return arr;}
		for (i = 0; i < len; i++) {
			v = arr[i];
			if (o[v] !== 1) {
				a.push(v);
				o[v] = 1;
			}
		}
		return a;
	};
 
	function init_words(word) {
		var erg = word.match(new RegExp("^ ?/(.+)/([gim]+)?$"));
		if (erg) {
			var ew = erg[1], flag = erg[2] || '';
			var word_s = [{exp:new RegExp('(' + ew + ')(?!##)', flag), text:ew, toString:function(){return ew;}}];
		} else if (word) {
			var ret=[], eword = word.replace(/"([^"]+)"/g,function($0,$1){$1 && ret.push($1);return '';});
			var word_s = eword.split(/[\+\|#]/).filter(function(w){return !!w;}).concat(ret);
			word_s = uniq(word_s);
			for (var i in word_s) {
				if (/^[a-z0-9]$/i.test(word_s[i]))
					words_off[i] = true;
				else words_off[i] = false;
			}
		}
		return word_s;
	}
 
	// http://d.hatena.ne.jp/amachang/20090917/1253179486
	function escapeXPathExpr(text) {
		var matches = text.match(/[^"]+|"/g);
		function esc(t) {
			return t == '"' ? ('\'' + t + '\'') : ('"' + t + '"');
		}
		if (matches) {
			if (matches.length == 1) {
				return esc(matches[0]);
			} else {
				var results = [];
				for (var i = 0, len = matches.length; i < len; i ++) {
					results.push(esc(matches[i]));
				}
				return 'concat(' + results.join(', ') + ')';
			}
		} else {
			return '""';
		}
	}
 
	function $X(exp, context, resolver, result_type) {
		context || (context = document);
		var Doc = context.ownerDocument || context;
		var result = Doc.evaluate(exp, context, resolver, result_type || XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		if (result_type) return result;
		for (var i = 0, len = result.snapshotLength, res = new Array(len); i < len; i++) {
			res[i] = result.snapshotItem(i);
		}
		return res;
	}
 
	// reduce https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce#Compatibility
	function reduce(arr, fun) {
		var len = arr.length, i = 0, rv;
		if (arguments.length >= 3) rv = arguments[2];
		else {do {
			if (i in arr) {
				rv = arr[i++];break;
			}
			if (++i >= len) throw new TypeError();
		} while (true)};
		for (; i < len; i++) if (i in arr) rv = fun.call(null, rv, arr[i], i, arr);
		return rv;
	}
 
	function error(e) {
		if (isOpera) {
			opera.postError(e);
		} else if (window.console) {
			console.error(e);
		}
	}
 
	function addCSS(css) {
		var sheet, self = arguments.callee;
		if (document.createStyleSheet) { // for IE
			sheet = document.createStyleSheet();
			sheet.cssText = css;
			return sheet;
		} else if (!self.__style || !self.__root) {
			sheet = document.createElement('style');
			sheet.type = 'text/css';
			self.__style = sheet;
			self.__root = document.getElementsByTagName('head')[0] || document.documentElement;
		}
		sheet = self.__style.cloneNode(false);
		sheet.textContent = css;
		return self.__root.appendChild(sheet).sheet;
	}

})();