探针部署
部署说明
探针部署可采用两种方式:手工嵌码和自动嵌码。
手工嵌码
手工嵌码是通过研发人员手工将浏览器探针(JS 代码)添加到页面中,或运维通过Nginx、Apache将探针注入到页面中,采集页面性能数据。
优势:
- 可自定义嵌入需要监控的应用和页面。
- 多对多的前后端应用Ajax与事务关联,跨应用追踪。
- 浏览器探针可放到CDN加速,提高探针下载速度。
自动嵌码
自动嵌码是借助系统应用将浏览器探针(JS代码)自动注入到系统应用的Web页面中,并在基调听云Web应用列表中自动生成系统应用所对应的Web应用,当应用页面被访问时,浏览器探针将采集的性能数据传输到数据中心处理,在基调听云Web应用列表选择所属应用,即可对该应用进行数据分析。
优势
- 操作简单,无需手工更改程序代码。
- 一对一的前后端Ajax与事务关联,Ajax请求可以关联追踪到系统应用对应的事务和慢事务,定位前后端关联问题,同时页面主HTML可以追踪到server事务。
注意事项
- 前后端分离应用(例如:React, Angular, Vue 等前端框架)不支持自动嵌码,可采用手工嵌码方式,同样支持全栈溯源功能。
部署流程
手工嵌码
-
在左侧导航栏中选择Web>概览,进入应用列表页面。点击页面右上角的添加应用按钮。
-
新建应用名称,名称不可重复。
-
自定义阈值。
-
获取探针。
点启用,选择下载探针或获取JS外链。
-
部署探针。
将JS文件tingyun-rum.js部署在可以访问的环境,例如Nginx、Apache的静态资源文档目录或通过CDN部署,后续嵌码引用的探针地址也要改为此地址。
若使用“JS外链”方式使用探针,直接使用生成的JS外链地址即可。
-
部署探针的位置。
将在需要监控的页面或者应用的head中引入探针到如下图位置。
-
查看报表。
嵌码成功部署到生产环境后,等待5分钟,即可在基调听云Web控制台的应用列表中看到对应的Web应用。
补充说明:注入探针方法。
注入探针方式有三种,任意一种都可以。
-
手工写入
将代码段拷贝,直接添加在对应的位置中即可。
-
Nginx
通过ngx_http_sub_module模块进行替换,ngx_http_sub_module模块的安装及配置文档请参考 官方文档 。
示例如下:
Location / {
sub_filter '</head>' '<script type="text/javascript">var TINGYUN_COOKIE_VALUE=document.cookie;document.cookie="TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";document.cookie="TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/";(function(d,s,id){if(/(MSIE [0-8].\d+)/.test(navigator.userAgent)){return;}"use strict";var __TINGYUN=function(t){function e(t){return function(e){return"Array"===t&&Array.isArray?Array.isArray(e):Object.prototype.toString.call(e)==="[object "+t+"]"}}function n(t,e,n){if(t&&n&&b(n)){var r=t[e];if(!r||!r._wrapped){var i=n(r,e);return i&&(i._wrapped=!0),t[e]=i,i}}}function r(e,n){return function(r){if(t[h].hook&&t[h].hook.eventCb&&f(r)){var i={originalCallback:e,eventHandlerType:n};return t[h].hook.eventCb.call(this,arguments,i)}return e.apply(this,arguments)}}function i(t,e,n){return n===k?r(t,e):(t.handleEvent=r(t.handleEvent,e),t)}function o(t){return b(t)}function a(t){return L(t)&&b(t.handleEvent)}function u(t){var e;return o(t)?e=k:a(t)&&(e=j),{isValid:t&&e,listenerType:e}}function s(t){return function(){var e=arguments[0],n=arguments[1],r=arguments[2],o=!0;r&&L(r)&&r[y]&&(o=!1);var a=u(n),s=a.isValid,l=a.listenerType;if(o&&O.indexOf(e)>-1&&s){var c;if(n[_]&&n[_][this])c=n[_][this];else{var p=i(n,E,l);l===k&&(n[_]||(n[_]={},n[_][T]=0),n[_][this]={listener:p,options:arguments[2]},n[_][T]++,c=n[_][this])}c&&(c.listener&&(arguments[1]=c.listener),c.options&&(arguments[2]=c.options))}return t&&t.apply(this,arguments)}}function l(t){return function(e,n){var r;try{r=t&&t.apply(this,arguments)}finally{try{if(n&&O.indexOf(e)>-1){var i=n[_];i&&i[this]&&i[this].listener&&(null!=i[this].options?this.removeEventListener(e,i[this].listener,i[this].options):this.removeEventListener(e,i[this].listener),i[this]=null,i[T]--,i[T]<=0&&(n[_]=null,delete n[_]))}}catch(o){}}return r}}function c(){t.EventTarget&&(n(t.EventTarget.prototype,"addEventListener",function(t){return s(t)}),n(t.EventTarget.prototype,"removeEventListener",function(t){return l(t)}))}function p(){Object.getOwnPropertyDescriptor&&Object.defineProperty&&O.forEach(function(e){var n="on"+e,r=Object.getOwnPropertyDescriptor(t.HTMLElement.prototype,n),o=r.get,a=r.set;Object.defineProperty(t.HTMLElement.prototype,n,{get:function(){return o.apply(this,arguments)},set:function(){var t=arguments[0];return t&&(arguments[0]=i(t,d,k)),a&&a.apply(this,arguments)},configurable:!0,enumerable:!0})})}function f(e){return e&&e.target instanceof t.HTMLElement&&e.currentTarget instanceof t.HTMLElement}function v(){return t.HTMLElement&&(c(),p()),t[h].listenerHooked=!0,t[h]}var h="__TINGYUN",y="__ty_event_patch_disable",g="click",m="submit",E="addEventListener",d="onProperty",_="__TY_ELEMENT_CB",T="__TY_CB_COUNTER",b=e("Function"),L=e("Object"),O=[g,m],k=1,j=2;t[h]||(t[h]={}),t[h].hook||(t[h].hook={}),t[h].hook.eventCb=null;var C=v();return C}(window);var js,tjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return;}js=d.createElement(s);js.id=id;js.async=true;js.src="//wkbrs1.tingyun.com/js/XG5y_j9ehF4.js";tjs.parentNode.insertBefore(js,tjs);})(document,"script","tingyun_agent");</script></head>';
sub_filter_once on;
} -
Apache
使用Apache作为Web容器进行内容替换需要使用 mod_substitute 和 mod_filter 两个模块。Apache要求 2.4 以及以上版本。 示例使用 Apache 2.4:
<Location />
AddOutputFilterByType SUBSTITUTE text/html
Substitute 's%<head>%<head><script type="text/javascript">var TINGYUN_COOKIE_VALUE=document.cookie;document.cookie="TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";document.cookie="TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/";(function(d,s,id){if(/(MSIE [0-8].\d+)/.test(navigator.userAgent)){return;}"use strict";var __TINGYUN=function(t){function e(t){return function(e){return"Array"===t&&Array.isArray?Array.isArray(e):Object.prototype.toString.call(e)==="[object "+t+"]"}}function n(t,e,n){if(t&&n&&b(n)){var r=t[e];if(!r||!r._wrapped){var i=n(r,e);return i&&(i._wrapped=!0),t[e]=i,i}}}function r(e,n){return function(r){if(t[h].hook&&t[h].hook.eventCb&&f(r)){var i={originalCallback:e,eventHandlerType:n};return t[h].hook.eventCb.call(this,arguments,i)}return e.apply(this,arguments)}}function i(t,e,n){return n===k?r(t,e):(t.handleEvent=r(t.handleEvent,e),t)}function o(t){return b(t)}function a(t){return L(t)&&b(t.handleEvent)}function u(t){var e;return o(t)?e=k:a(t)&&(e=j),{isValid:t&&e,listenerType:e}}function s(t){return function(){var e=arguments[0],n=arguments[1],r=arguments[2],o=!0;r&&L(r)&&r[y]&&(o=!1);var a=u(n),s=a.isValid,l=a.listenerType;if(o&&O.indexOf(e)>-1&&s){var c;if(n[_]&&n[_][this])c=n[_][this];else{var p=i(n,E,l);l===k&&(n[_]||(n[_]={},n[_][T]=0),n[_][this]={listener:p,options:arguments[2]},n[_][T]++,c=n[_][this])}c&&(c.listener&&(arguments[1]=c.listener),c.options&&(arguments[2]=c.options))}return t&&t.apply(this,arguments)}}function l(t){return function(e,n){var r;try{r=t&&t.apply(this,arguments)}finally{try{if(n&&O.indexOf(e)>-1){var i=n[_];i&&i[this]&&i[this].listener&&(null!=i[this].options?this.removeEventListener(e,i[this].listener,i[this].options):this.removeEventListener(e,i[this].listener),i[this]=null,i[T]--,i[T]<=0&&(n[_]=null,delete n[_]))}}catch(o){}}return r}}function c(){t.EventTarget&&(n(t.EventTarget.prototype,"addEventListener",function(t){return s(t)}),n(t.EventTarget.prototype,"removeEventListener",function(t){return l(t)}))}function p(){Object.getOwnPropertyDescriptor&&Object.defineProperty&&O.forEach(function(e){var n="on"+e,r=Object.getOwnPropertyDescriptor(t.HTMLElement.prototype,n),o=r.get,a=r.set;Object.defineProperty(t.HTMLElement.prototype,n,{get:function(){return o.apply(this,arguments)},set:function(){var t=arguments[0];return t&&(arguments[0]=i(t,d,k)),a&&a.apply(this,arguments)},configurable:!0,enumerable:!0})})}function f(e){return e&&e.target instanceof t.HTMLElement&&e.currentTarget instanceof t.HTMLElement}function v(){return t.HTMLElement&&(c(),p()),t[h].listenerHooked=!0,t[h]}var h="__TINGYUN",y="__ty_event_patch_disable",g="click",m="submit",E="addEventListener",d="onProperty",_="__TY_ELEMENT_CB",T="__TY_CB_COUNTER",b=e("Function"),L=e("Object"),O=[g,m],k=1,j=2;t[h]||(t[h]={}),t[h].hook||(t[h].hook={}),t[h].hook.eventCb=null;var C=v();return C}(window);var js,tjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return;}js=d.createElement(s);js.id=id;js.async=true;js.src="//10.128.2.24:8588/js/lNXvexXCq6I.js";tjs.parentNode.insertBefore(js,tjs);})(document,"script","tingyun_agent");</script>%in'
</Location>注意:
- 如果您的HTML中使用了
<meta>
标签来指定了编码,应该将<meta>
标签紧接在<head>
标签之后,并且将浏览器探针紧接在最后一个<meta>
标签之后。 - 请勿直接使用文档js.src的地址,请到新建应用后拷贝代码和地址,若使用CDN或相对路径,也请自行更改地址。
Nginx示例:
Location / {
sub_filter '<meta content="text/html;charset=utf-8">' '<meta content="text/html;charset=utf-8"><script type="text/javascript"> var TINGYUN_COOKIE_VALUE = document.cookie; document.cookie = "TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"; document.cookie = "TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/"; (function (d, s, id) { if(/(MSIE [0-8].\d+)/.test(navigator.userAgent)){return ;} "use strict";var __TINGYUN=function(){function n(n){return function(t){return"Array"===n&&Array.isArray?Array.isArray(t):Object.prototype.toString.call(t)==="[object "+n+"]"}}function t(n,t,e){if(n&&e&&f(e)){var r=n[t];if(!r||!r._wrapped){var o=e(r,t);return o&&(o._wrapped=!0),n[t]=o,o}}}function e(n,t){return function(){if(window[a].hook&&window[a].hook.eventCb){var e={originalCallback:n,eventHandlerType:t};return window[a].hook.eventCb.call(this,arguments,e)}return n.apply(this,arguments)}}function r(n){return function(){var t=arguments[0],r=arguments[1],o=arguments[2],i=!0;return o&&l(o)&&o[c]&&(i=!1),i&&y.indexOf(t)>-1&&r&&(arguments[1]=e(r,w)),n&&n.apply(this,arguments)}}function o(){t(HTMLElement.prototype,"addEventListener",function(n){return r(n)})}function i(){Object.getOwnPropertyDescriptor&&Object.defineProperty&&y.forEach(function(n){var t="on"+n,r=Object.getOwnPropertyDescriptor(HTMLElement.prototype,t),o=r.get,i=r.set;Object.defineProperty(HTMLElement.prototype,t,{get:function(){return o.apply(this,arguments)},set:function(){var n=arguments[0];return n&&(arguments[0]=e(n,d)),i&&i.apply(this,arguments)},configurable:!0,enumerable:!0})})}function u(){return window.HTMLElement&&(o(),i()),window[a].listenerHooked=!0,window[a]}var a="__TINGYUN",c="__ty_event_patch_disable",p="click",s="submit",w="addEventListener",d="onProperty",f=n("Function"),l=n("Object"),y=[p,s];window[a]||(window[a]={}),window[a].hook||(window[a].hook={}),window[a].hook.eventCb=null;var g=u();return g}(); var js, tjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) {return;} js = d.createElement(s); js.id = id; js.async = true; js.src = "//10.128.5.248:8588/js/jVR5d0mH9fQ.js"; tjs.parentNode.insertBefore(js, tjs); })(document, "script", "tingyun_agent"); </script>';
sub_filter_once on;
}Apache示例:
<Location />
AddOutputFilterByType SUBSTITUTE text/html
Substitute 's%<meta content="text/html;charset=utf-8">%<meta content="text/html;charset=utf-8"><script type="text/javascript">var TINGYUN_COOKIE_VALUE=document.cookie;document.cookie="TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";document.cookie="TINGYUN_DATA=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/";(function(d,s,id){if(/(MSIE [0-8].\d+)/.test(navigator.userAgent)){return;}"use strict";var __TINGYUN=function(t){function e(t){return function(e){return"Array"===t&&Array.isArray?Array.isArray(e):Object.prototype.toString.call(e)==="[object "+t+"]"}}function n(t,e,n){if(t&&n&&b(n)){var r=t[e];if(!r||!r._wrapped){var i=n(r,e);return i&&(i._wrapped=!0),t[e]=i,i}}}function r(e,n){return function(r){if(t[h].hook&&t[h].hook.eventCb&&f(r)){var i={originalCallback:e,eventHandlerType:n};return t[h].hook.eventCb.call(this,arguments,i)}return e.apply(this,arguments)}}function i(t,e,n){return n===k?r(t,e):(t.handleEvent=r(t.handleEvent,e),t)}function o(t){return b(t)}function a(t){return L(t)&&b(t.handleEvent)}function u(t){var e;return o(t)?e=k:a(t)&&(e=j),{isValid:t&&e,listenerType:e}}function s(t){return function(){var e=arguments[0],n=arguments[1],r=arguments[2],o=!0;r&&L(r)&&r[y]&&(o=!1);var a=u(n),s=a.isValid,l=a.listenerType;if(o&&O.indexOf(e)>-1&&s){var c;if(n[_]&&n[_][this])c=n[_][this];else{var p=i(n,E,l);l===k&&(n[_]||(n[_]={},n[_][T]=0),n[_][this]={listener:p,options:arguments[2]},n[_][T]++,c=n[_][this])}c&&(c.listener&&(arguments[1]=c.listener),c.options&&(arguments[2]=c.options))}return t&&t.apply(this,arguments)}}function l(t){return function(e,n){var r;try{r=t&&t.apply(this,arguments)}finally{try{if(n&&O.indexOf(e)>-1){var i=n[_];i&&i[this]&&i[this].listener&&(null!=i[this].options?this.removeEventListener(e,i[this].listener,i[this].options):this.removeEventListener(e,i[this].listener),i[this]=null,i[T]--,i[T]<=0&&(n[_]=null,delete n[_]))}}catch(o){}}return r}}function c(){t.EventTarget&&(n(t.EventTarget.prototype,"addEventListener",function(t){return s(t)}),n(t.EventTarget.prototype,"removeEventListener",function(t){return l(t)}))}function p(){Object.getOwnPropertyDescriptor&&Object.defineProperty&&O.forEach(function(e){var n="on"+e,r=Object.getOwnPropertyDescriptor(t.HTMLElement.prototype,n),o=r.get,a=r.set;Object.defineProperty(t.HTMLElement.prototype,n,{get:function(){return o.apply(this,arguments)},set:function(){var t=arguments[0];return t&&(arguments[0]=i(t,d,k)),a&&a.apply(this,arguments)},configurable:!0,enumerable:!0})})}function f(e){return e&&e.target instanceof t.HTMLElement&&e.currentTarget instanceof t.HTMLElement}function v(){return t.HTMLElement&&(c(),p()),t[h].listenerHooked=!0,t[h]}var h="__TINGYUN",y="__ty_event_patch_disable",g="click",m="submit",E="addEventListener",d="onProperty",_="__TY_ELEMENT_CB",T="__TY_CB_COUNTER",b=e("Function"),L=e("Object"),O=[g,m],k=1,j=2;t[h]||(t[h]={}),t[h].hook||(t[h].hook={}),t[h].hook.eventCb=null;var C=v();return C}(window);var js,tjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return;}js=d.createElement(s);js.id=id;js.async=true;js.src="//10.128.2.24:8588/js/lNXvexXCq6I.js";tjs.parentNode.insertBefore(js,tjs);})(document,"script","tingyun_agent");</script>%in'
</Location> - 如果您的HTML中使用了
自动嵌码
选择Server应用 ,注入浏览器探针,点击启用即可。
目前支持Java、.NET两种语言。
验证探针部署成功
通过Chrome浏览器访问嵌码页面,按F12,然后在network中搜索 “action”,若有action接口数据,即为嵌码成功。
action接口为嵌码成功后上传性能数据。