如何用elastic APM实现用户行为轨迹监控(User Journey Monitoring)

文章目录

      • 思路
      • 单页应用VS多页应用
      • 前端框架的组件生命周期
      • 解决方案
        • package.json
        • main.js
      • 展示

对于各大APM厂商来说,通过用户轨迹监控(User Journey Monitoring)来获取用户访问网站或者APP时的轨迹已经成为了标配,通过该功能,我们可以了解用户的轨迹信息,比如:哪个页面最吸引用户访问,用户在哪个页面上停留的时间最长,哪个页面客户点击最少,停留的时间最少,一般是从哪个页面到哪个页面等等。

elastic APM 目前只提供了一个RUM功能(Real User Monitoring),并没有完整的推出User Journey Monitoring,那基于目前的工具,我们该如何实现User Journey Monitoring呢?

这篇文章,我们以Vue为例子,讲解一下该如何做到UJM功能。

思路

要实现用户的轨迹追踪,必须实现几个基本的要素:

  • 知晓用户发生轨迹切换的事件 - 登录,跳转,离开等
  • 当事件发生后,需要记录相关的指标 - 用户名,停留时间,跳转前的页面地址等
  • 页面需能与后端服务器通信,以记录各种用户行为轨迹相关的数据

当然,还有其他要求,比如能够远程打开关闭监控,监控接口防火墙,不能影响用户真实体验等,我们在这里不做讨论。

因为我们讨论的是elastic APM,自然,它就承担了记录用户行为轨迹相关的数据的责任,通过javascript agent,我们可以将用户的轨迹映射为APM中的transaction,然后发送到APM server。

在实现剩余的两个要素之前,我们通常要先解决以下问题:

  • 你的应用是一个单页应用还是一个多页应用?
  • 你是否使用了web应用框架?是否了解web对应应用框架的组件生命周期?

单页应用VS多页应用

为什么我们要讨论单页应用和多页应用的问题,最主要的区别在于:

  • 当你的应用是一个多页应用的时候,每个页面的跳转需要访问后端的浏览器获取html相关资源,即你的轨迹记录是可以从类似apache,nginx等日志中提取的,但日志数据是否能够完整包含轨迹数据,存疑;而且,对应的,因为页面之间缺乏直接的联系,页面跳转后,记录需要在页面间传递的轨迹相关数据会比较麻烦。
  • 当你的应用是一个单页应用时,页面的“跳转”实际上是浏览器重新渲染页面的一个过程,即用户的访问轨迹并不会出现在日志当中,也不会记录在浏览器的访问历史当中,但相对的,因为是一个整体内部的切换,通过页面上的数据治理,很容易在页面的“跳转”之间的数据传递。
    如何用elastic APM实现用户行为轨迹监控(User Journey Monitoring)_第1张图片
    结论,无论是多页应用还是单页应用,通过技术都是能够做到用户轨迹数据的提起的,只是在不同的场景下可能会有数据准确性的问题。在这里,我们以单页应用为例子,因为手机web大多是采用单页应用的方式提高用户体验,而用户体验和用户行为轨迹监控是更为相关的行为。

前端框架的组件生命周期

对于一个web应用,如果我们需要做用户行为轨迹监控,那么基本也意味着,我们会要求该web应用有一个好的设计。如果一个web应用连基本的前端web框架都没有使用,那么就不在我们的讨论范围之内。。。现在流行的web框架,比如,vue, angularJS, react等,都提供了组件生命周期管理的勾子函数,以Vue这个在中国最流行的框架来举例,每个页面都是一个vue的组件(当然,组件里面还有很多子组件),组件包含以下生命周期:
如何用elastic APM实现用户行为轨迹监控(User Journey Monitoring)_第2张图片
类似的,AngularJs和React里面也生命周期勾子函数。

解决方案

从上图可以看到,createdactivateddeactivateddestroyed等函数所代表的事件,是和我们需要记录的用户轨迹的事件,如:进入,离开等事件是吻合的。并且,作为一个勾子函数,我们可以在函数中访问框架提供的组件间通信数据以及公共数据,如此,我们可以在函数中得到如下信息:

  1. 登录的用户名,以及其他用户信息
  2. 进入组件的时间,离开组件的时间,组件停留时间
  3. 发生组件切换的前后关系

下面,是关键的代码实现。

package.json

在dependencies中增加:

"elastic-apm-js-base": "^3.0.0"

main.js

在VUE的初始化文件中,增加以下功能:

  • 启动APM
  • 新增transaction函数,打开和关闭APM的transaction,并在transaction中记录:用户名,组件名,进入时间,离开时间,停留时间
  • 使用mixin,将transaction函数挂载到勾子上

大家需要注意的是,这是一个POC的试验方案,真正的生产实现,需要大家继续优化

import {init as initApm} from 'elastic-apm-js-base'

const apm = initApm({

  // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)
  serviceName: 'qsa_smart_advisor',

  // Set custom APM Server URL (default: http://localhost:8200)
  serverUrl: 'http://localhost:8200',

  // Set service version (required for sourcemap feature)
  serviceVersion: '',

  pageLoadTransactionName: 'home'
})

// User Journey Monitoring


function startUJMTransaction(theVue) {
  var enableAPM = theVue.$options.enableAPM;
  if (enableAPM) {
    store.dispatch('getUserInfo').then(user => {
      apm.setUserContext({
        id: user.id,
        username: user.name
      })
    });
    if (theVue.$options.transaction) {
      endUJMTransaction(theVue);
    }
    theVue.$options.transaction = apm.startTransaction(theVue.$options.name, 'custom');
    let startTime = new Date().getTime();
    theVue.$options.transaction_start = startTime;
    apm.addTags({int_start: new Date().getTime()});
    console.log("create " + theVue.$options.transaction.name + " with tag: " + {start: startTime})
  }
}

function endUJMTransaction(theVue) {
  var enableAPM = theVue.$options.enableAPM;
  if (enableAPM && theVue.$options.transaction) {
    let endTime = new Date().getTime();

    apm.addTags({int_end: endTime});
    apm.addTags({int_duration: endTime - theVue.$options.transaction_start});

    theVue.$options.transaction.end();

    theVue.$options.transaction = null;
    theVue.$options.transaction_start = null;
  }
}

Vue.mixin({
  created: function () {
    startUJMTransaction(this)
  },

  activated: function () {
    let currentTrans = apm.getCurrentTransaction();
    if (currentTrans) {
      endUJMTransaction(this)
    }
    startUJMTransaction(this)
  },

  deactivated: function () {
    endUJMTransaction(this)
  },

  destroyed: function () {
    endUJMTransaction(this)
  }
});

展示


因为通过elastic我们可以做到地图热点,加载性能监控(RUM),最终是能够实现如下效果的dashboard的:
如何用elastic APM实现用户行为轨迹监控(User Journey Monitoring)_第3张图片

你可能感兴趣的:(ELK,前端开发,大数据,点火三周的Elastic,Stack专栏)