一文搞懂得物前端监控

一、背景

得物的服务端监控是比较全面和有效的,除了上报原始日志数据,还通过数据分析制定线上告警机制,调用链路分析,而针对前端项目这一块,还是不够全面的。对前端线上问题感应不及时,靠人肉发现,没有告警机制等问题,所以就有个前端监控这个项目。前端监控也确实很有必要,我们需要对线上的页面有个全面的把控,而至于怎么做监控,做数据上报,以及数据分析,如何针对监控数据分析出有用的核心链路的告警等也能有个全面的认识。本文主要是介绍得物针对监控做了哪些事情以及对前端底层监控手段做个总结。

二、监控类型

前端监控的范围很广,如监控性能,监控异常,监控告警等一系列的维度来确保我们的页面和功能是正常的,在出现问题时研发可以及时做出响应,及时追踪,定位问题。

性能监控

目前前端平台在性能监控和异常监控是分开的,性能监控有专门 SDK,去做上报和分析,联合得物 App 端上一起做了性能优化和数据分析,这块是独立的。主要包括性能的上报,以及性能的优化手段。下图是前端性能监控方面的数据展示效果。

7.png

总体来说性能监控是做的比较大的,而且监控对提高页面的秒开是有实际优化指导意义的,离线包、预请求等都是优化手段。

异常告警监控

针对异常监控也有单独的平台和 SDK 去承接和上报,下图来展示收集一些异常信息,对异常信息进行分类,再通过设置告警机制来通知开发人员及时发现问题:

8.png

这些错误类的信息不一定是我们都需要关注的,有些疑难杂症,但是有不影响页面展示和功能的报错,也是可以忽略的,要知道不是所有的错误都能被解决的,这个时候我们可以只关注那些影响我们页面核心功能的部分,针对这部分做一个告警配置,例如:

9.png

针对告警信息,再进一步对错误进行分析,找到能解决的问题,达到对页面稳定性的把控。

日常巡检监控

还有一种比较特殊的场景,针对运营活动做的营销会场,在各个配置的坑位去做巡检,提前发现会场是否正常,有没有白屏、API 异常等提前发现,然后联系相应的人去人工处理。这种监控模式对于要投放出去的页面做提前检查是很有效果的,事实证明也确实如此,提前避免了很多线上问题,很厉害。

5.png

三、监控知识梳理

上面几个大类型的监控都是前端同学在监控方面做的努力和成果,涉及到的知识点也很多,同样对于业务的把控和理解也很深入,很值得学习并了解,后面的内容就是针对监控做个梳理总结,了解下大致的实现方式。

前端监控的必要性

用户在访问页面的时候大致会经历下面的阶段:

  • 向服务端请求获取静态资源;
  • 浏览器加载资源;
  • 资源加载成功之后页面渲染继续运行。

这些阶段都有报错的可能,而前端要做的就是监控后面这阶段:资源加载和页面交互。

做前端监控也有很多其他好处, 例如:

  • 第一时间上报异常,解决问题;
  • 能够比较完整的重现问题用户的操作全流程路径,方便开发者复现问题,定位问题;
  • 针对页面的 PV、UV 等信息可以为产品和运营做推广决策提供数据依据。

前端监控是很有必要的,通过监控,我们能在线上应用异常时,第一时间收到反馈,并及时止损。对业务的发展是有正向作用的。

前端监控目标

保证稳定性(错误监控)

错误监控包括 JavaScript 代码错误、Promsie 错误、接口(XHR,Fetch)错误、资源加载错误(Script,Link等)等,这些错误大多会导致页面功能异常甚至白屏。

提升用户体验(性能监控)

性能监控包括页面的加载时间、接口响应时间等,侧面反应了用户体验的好坏。

  • 加载时间:页面运行时各个阶段的加载时间;
  • TTFB(Time To First Byte)(首字节时间):浏览器发起第一个请求到数据返回第一个字节所消耗的时间,这个时间包含了网络请求时间、后端处理时间;
  • FP(First Paint)(首次绘制):首次绘制包括了任何用户自定义的背景绘制,它是将第一个像素点绘制到屏幕的时刻;
  • FCP(First Content Paint)(首次内容绘制):首次内容绘制是浏览器将第一个 DOM 渲染到屏幕的时间,可以是任何文本、图像、SVG 等的时间;
  • FMP(First Meaningful paint)(首次有意义绘制):首次有意义绘制是页面可用性的量度标准;
  • LCP(Largest Contentful Paint):视窗内最大的图片或者文本渲染的时间,当最大的内容块渲染完的时候,基本上主内容都加载完了,与现有的页面加载指标相比,与用户体验的相关性更好;
  • FID(First Input Delay)(首次输入延迟):用户首次和页面交互到页面响应交互的时间;
  • 卡顿:指超过 50ms 的长任务,具体的指标可以根据页面的内容进行调节,一般 50ms 人眼就能感觉到卡顿。

针对业务进行统计

  • PV:Page View 即页面浏览量或点击量;
  • UV:指访问某个站点的不同 IP 地址的人数;
  • 页面的停留时间:用户在每一个页面的停留时间。

前端监控的流程

  • 前端埋点(通过 SDK 给页面的 DOM 都加上标记)
  • 数据上报(收集,存储)
  • 分析和计算(将采集到的数据进行加工汇总)
  • 可视化展示(按照纬度将数据展示)
  • 监控报警(发现异常后按一定的条件触发报警)

前端埋点方案

代码埋点

代码埋点,就是项目中引入埋点 SDK,手动在业务代码中标记,触发埋点事件进行上报。比如页面中的某一个模块的点击事件,会在点击事件的监听中加入触发埋点的代码 this.$track('事件名', { 需要上传的业务数据 }),将数据上报到服务器端。

  • 优点:能够在任何时刻,更精确的发送需要的数据信息,上报数据更灵活;
  • 缺点:工作量大,代码侵入太强,过于耦合业务代码,一次埋点的更改就要引起发版之类的操作。

这个方案也是我们实际项目中现有的方案。

可视化埋点

通过可视化交互的手段,代替代码埋点,可以新建、编辑、修改埋点。在组件和页面的维度进行埋点的设计。

将业务代码和埋点代码分离,提供一个可视化交互的页面,输入为业务代码,通过这个可视化系统,可以在业务代码中自定义的增加埋点事件,最后输出的代码耦合了业务代码和埋点代码。

这个方案是可以解决第一种代码埋点的痛点,也是我们目前正准备做的方案。

无痕埋点

前端的任意一个事件都被绑定一个标识,所有的事件都被记录下来,通过定期上传记录文件,配合文件解析,解析出来我们想要的数据,并生成可视化报告。

无痕埋点的优点是采集全量数据,不会出现漏埋和误埋等现象。缺点是给数据传输和服务器增加压力,也无法灵活定制数据结构。针对业务数据的准确性不高。

监控脚本

日志存储

前端的埋点上报需要存储起来,这个可以使用阿里云的日志服务,不需要投入开发就可以采集。

新建一个项目比如:xxx-monitor

新建一个存储日志,根据阿里云的要求发起请求,携带需要上报的数据:

http://${project}.${host}/logstores/${logStore}/track

1.png

代码中调用 Track 上报日志:

日志的上报可以封装成公共的调用方式, monitor/utils/里面放所有的工具方法;

tracker.js 的实现就是按照阿里云的上报格式发送请求,并带上处理好的需要上报的业务数据即可,下面的都是固定的,在日志服务建好:

2.jpeg

实现一个 Tracker 类导出类的实例即可,这样在监控的核心代码中直接调用 tracker.send(data),核心实现代码如下:

// monitor/utils/get/track.js
...
class SendTrackLoger {
  constructor() {
    this.url = `http://${project}.${host}/logstores/${logStore}/track`
    this.xhr = new XMLHttpRequest()
  }

  send(data = {}, callback) {
    const logData = {...logData}
    for(let key in logs) {
      if (typeof logs[key] === 'number') {
        logs[key] = `${logs[key]}` // 这是阿里云的要求,字段不能是数字类型
      }
    }

    let body = JSON.stringify({
      __logs__: [logs]
    })
    this.xhr.open('POST', this.url, true)
    this.xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
    this.xhr.setRequestHeader('x-log-apiversion', '0.6.0')
    this.xhr.setRequestHeader('x-log-bodyrawsize', body.length)
    this.xhr.onload = function() {
      if (this.status >= 200 && this.status <= 300 || this.status === 304) {
        callback && callback()
      }
    }
    this.xhr.onerror = function(error) {
      console.log(error)
    }
    this.xhr.send(body)
  }
}

export default new SendTrackLoger()

这里展示的是自定义要上报的数据字段:

14.png

监控错误

前端需要监控的错误有两类:

  • Javascript 错误(JS 错误,Promise 异常)
  • 监听 Error 错误(资源加载错误)

脚本实现

新建一个 fronend-monitor 项目,这个项目就相当于我们的工程项目,监控的核心实现可以写到项目里面,也可以抽成 SDK 的形式 Import 引入进来,这里先写到项目中。

webpack.config.js 用来打包项目,做接口数据 Mock,测试 XHR 请求监控接口错误等。

const path = require('path')
const HtmlWebpackPlugin = xxx

module.exports = {
  mode: 'development',
  context: process.cwd(),
  entry:'./src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'monitor.js'
  },
  devServer: {
    contentBase: path.resolve(__dirname, 'dist'),
    before(router) {
      router.get('/success', function(req, res) {
        res.json({ id: 1 })
      })
      router.post('/error', function(req, res) {
        res.sendStatus(500)
      })
    },
  },
  module: {},
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      inject: "head"
    })
  ]
}

新建一个 src/index.html 在这个里面写一些问题代码,然后测试监控的错误捕获。

// src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>monitor</title>
</head>
<body>
  <input id="jsErrorBtn" type="button" value="js 代码错误" onclick="btnClick()" />
  <input id="promiseErrorBtn" type="button" value="promise 错误" onclick="promiseClick()" />
  <input id="successBtn" type="button" value="成功 ajax 请求" onclick="successAjax()" />
  <input id="errorBtn" type="button" value="失败 ajax 请求" onclick="errorAjax()" />
  <script>
    function btnClick() {
      window.goods.type = 2
    }

    function promiseClick() {
      new Promise((resolve, reject) => {
        resolve(1)
      }, () => {
        console.log(123)
      })
    }

    function successAjax() {
      var xhr = new XMLHttpRequest()
      xhr.open('GET', '/success',  true)
      xhr.responseType = 'json'
      xhr.onload = function () {
        console.log(xhr.response)
      }
      xhr.send()
    }

    function errorAjax() {
      var xhr = new XMLHttpRequest()
      xhr.open('POST', '/error',  true)
      xhr.responseType = 'json'
      xhr.onload = function() {
        console.log(xhr.response)
      }
      xhr.onerror = function(err) {
        console.log(err)
      }
      xhr.send('name=123')
    }
</script>
</body>
</html>

上报未捕获的 Javascript 错误

Javascript 错误分为 2 种:语法错误,资源家加载错误,这些错误都会被window.addEventListener('error', function(event) {})捕获,来判断是否是资源加载错误。

window.addEventListener('error', function(event) {

    // 如果 target 是script link 等资源
    if (event.target && (event.target.src || event.target.href)) {
      const element = getElement(event.target || event.path)
      tracker.send({
        ...
        title: document.title,
        url: location.href,
        timestamp: event.timeStamp,
        userAgent: navigator.userAgent,
        type: 'resourceError',
        ...
      })
    } else {
      tracker.send({
        ...
        title: document.title,
        url: location.href,
        timestamp: event.timeStamp,
        userAgent: navigator.userAgent,
        type: 'jsError',
        ...
      })
    }
  }, true)

代码中未被捕获的 Promise 错误,要监听 unhandledrejection 事件 window.addEventListener('unhandledrejection', function(event) {})。

// 监听未捕获的 promise 错误
  window.addEventListener('unhandledrejection', function(event) {
    // PromiseRejectionEvent
    let message = ''
    let stack = ''
    const reason =  event.reason
    let filename = ''
    let lineno = ''
    let colno = ''
    if (reason) {
      message = reason.message
      stack = reason.stack
      const match = stack.match(/\s+at\s+(.+):(\d+):(\d+).+/)
      filename = match[1]
      lineno = match[2]
      colno = match[3]
    }

    tracker.send({
      ...
      title: document.title,
      url: location.href,
      timestamp: event.timeStamp,
      userAgent: navigator.userAgent,
      type: 'promiseError',
      ...
    })
  }, true)

接口异常上报

接口异常上报主要是拦截请求,拦截 XMLHttpRequest 对象,改写 XHR 的 Open 和 Send 方法,将需要上报的数据发到阿里云存储,监听 Load,Error,Abort 事件,上报数据:

// src/monitor/lib/xhr.js
import tracker from '../utils/tracker'

export default function injectXHR() {
  // 获取 window 上的 XMLHttpRequest 对象
  const XMLHttpRequest = window.XMLHttpRequest
  // 保存旧的open, send函数
  const prevOpen = XMLHttpRequest.prototype.open
  const prevSend = XMLHttpRequest.prototype.send

  // 不可使用箭头函数,不然会找不到 this 实例
  XMLHttpRequest.prototype.open = function (method, url, async, username, password) {
    // 重写open,拦截请求
    // 不拦截 track 本身以及 socket, 直接放行
    if (!url.match(/logstores/) && !url.match(/sockjs/)) {
      this.logData = { method, url, async, username, password }
    }
    return prevOpen.apply(this, arguments)
  }

  XMLHttpRequest.prototype.send = function (body) {
    // 重写 send,拦截有 logData 的请求,获取 body 参数
    if (this.logData) {
      this.logData.body = body
      let startTime = Date.now()
      function handler(type) {
        return function (event) {
          // event: ProgressEvent
          let duration = Date.now() - startTime
          let status = this.status
          let statusText = this.statusText
          console.log(event)

          tracker.send({
            type: 'xhr',
            eventType: type,
            pathname: this.logData.url,
            status: `${status} ${statusText}`,
            duration: `${duration}`, // 接口响应时长
            response: this.response ? JSON.stringify(this.response) : '',
            params: body || '',
          })
        }
      }
      this.addEventListener('load', handler('load'), false)
      this.addEventListener('error', handler('error'), false)
      this.addEventListener('abort', handler('abort'), false)
    }

    return prevSend.apply(this, arguments)
  }
}

监控白屏

白屏就是页面上什么东西也没有,在页面加载完成之后,如果页面上的空白点很多,就说明页面是白屏的,需要上报,这个上报的时机是:document.readyState === 'complete' 表示文档和所有的子资源已完成加载,表示load(window.addEventListener('load')状态事件即将被触发。

document.readyState 有三个值:loading(document正在加载),interactive(可交互,表示正在加载的状态结束,但是图像,样式和框架之类的子资源仍在加载),complete 就是完成,所以监控白屏需要在文档都加载完成的情况下触发。

// src/monitor/utils/onload.js
export function onload(callback) {
  if (document.readyState === 'complete') {
    callback()
  } else {
    window.addEventListener('onload', callback)
  }
}

监控白屏的思路主要是:可以将可视区域中心点作为坐标轴的中心,在X、Y轴上各分 10 个点,找出这个 20 个坐标点上最上层的 DOM 元素,如过这些元素是包裹元素,空白点数就加一,包裹元素可以自定义比如 Html Body App Root Container Content 等,空白点数大于 0 就上报白屏日志。

export default function computedBlankScreen() {
  // 包裹玉元素列表
  const wrapperSelectors = ['body', 'html', '#root', '#App']
  // 空白节点的个数
  let emptyPoints = 0
  // 判断20个点处的元素是否是包裹元素
  function isWrapper(element) {
    const selector = getSelector(element)
    console.log(selector)
    if (wrapperSelectors.indexOf(selector) >= 0) { // 表示是在包裹元素里面,空白点就要加一
      emptyPoints++
    }
  }
  onload(function() {
    let xElements, yElements
    for (let i = 0; i <=9; i++) {
      xElements = document.elementFromPoint(window.innerWidth * i / 10, window.innerHeight / 2)
      yElements = document.elementFromPoint(window.innerHeight * i / 10, window.innerWidth / 2)
      // document.elementFromPoint 返回的是某一个坐标点的由到外的html元素的集合
      isWrapper(xElements[0])
      isWrapper(yElements[0])
    }
    if (emptyPoints >= 0) {
      let centerPoint = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2)
      tracker.send()
    }
  })
}

监控卡顿

用户交互的响应时间如果大于某一个时间,用户就会感觉卡顿。可以定一个时间比如 100 毫秒,就代表响应时间长,会卡顿。

PerformanceObserver 构造函数使用给定的观察者 Callback 生成新的PerformanceObserver 对象,当通过 Observe() 方法注册条目类型(需要监控的类型)的性能条目被记录下来时,会调用该观察者回调。

所以可以 new PerformanceObserver 来监控 longTask,监控的资源加载如果超过 100 毫秒就表示卡顿,可以浏览器空闲(requestIdleCallback)的时候上报数据。

....
export default function longTask() {
  new PerformanceObserver(function(list) {
    list.getEntries().forEach(function(entry) {
      if (entry.duration > 100) {
        // 浏览器空闲的时候上报
        requestIdleCallback(() => {
          tracker.send({
            type: 'longTask',
            eventType: lastEvent.type,
            startTime: formatTime(entry.startTime),
            duration: formatTime(entry.duration),
          });
        });
      }
    })
  }).observe({ entryTypes: ['longtask']})
}

性能指标

PerformanceObserver.observe 方法用于观察传入的参数中指定的性能条目类型的集合。当记录一个指定类型的性能条目时,性能监测对象的回调函数将会被调用。performance.timing 记录了从输入 URL 到页面加载完成的所有的时间,从这些字段中可以提取对对页面性能的监控,通过分析这些指标来优化页面的体验,比如统计 FMP、LCP 等,具体可以查看 MDN。

统计pv (页面的停留时间)

navigator.connection 对象获取网络连接的信息:effectiveType(网络类型),RTT(估算饿往返时间)等,还能通过监听 window.addEventListener('unload')事件计算用户在页面的停留时间。

import tracker from '../util/tracker';
export function pv() {
    var connection = navigator.connection;
    tracker.send({
        type: 'pv',
        networkType: connection.effectiveType,  // 网络类型
        rtt: connection.rtt, // 往返时间
        screen: `${window.screen.width}x${window.screen.height}` // 设备分辨率
    });
    let startTime = Date.now();
    window.addEventListener('unload', () => {
        let stayTime = Date.now() - startTime; // 页面停留时间
        tracker.send({
            type: 'stayTime',
            stayTime
        });
    }, false);
}

四、总结

前端监控是一个成熟业务线的标配,目前最多的场景是监控 JS 错误,接口请求和性能优化,然后根据日志信息进行分析分类的可视化展示,在发生异常的时候通知到相应的业务开发,监控的性能指标给页面的体验优化提供数据对比和优化的方向。

参考文章:

https://juejin.cn/post/6939703198739333127

https://wicg.github.io/largest-contentful-paint/

https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceObserver/PerformanceObserver

https://developer.mozilla.org/zh-CN/docs/Web/API/Long_Tasks_API

https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceTiming

https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator

*文/Zyqy

本文属得物技术原创,更多精彩文章请看:得物技术官网

未经得物技术许可严禁转载,否则依法追究法律责任!

相关推荐

压测AI Agent 治理与评测调优实践|得物技术

本文介绍智能分析Agent在压测调试中上线后的治理闭环建设:通过Langfuse记录完整执行链路,结合用户反馈与Trace还原问题根因;利用CLI Mock固化证据数据集,实现相同场景下的回测验证。基于固定案例与五档评分机制,持续评估方案质量、延迟与成本,确保修复有效且无新问题引入,推动Agent能力迭代优化。

SmartCodeTech的博客 310

从中心调度到自驱协作多 Agent 架构的三次反转|得物技术

本文探讨多Agent系统中的控制权分配问题,提出三大协作架构:Master Agent(中心调度)、任务看板(共享状态)与Advisor(轻量咨询)。通过划清上下文边界与模型边界,强调应以信息相关性而非职业标签划分Agent。三种模式分别将决策权集中于中心、下放至共享状态、再下沉至执行者,形成控制权逐步下沉的演进路径。案例显示,合理设计可提升复杂任务的并行性、弹性与可维护性。

SmartCodeTech的博客 420

Jev 实战:为AI工作流引入轻量决策层 x10倍提速|得物技术

完成这三个场景后,我对适用边界有了更明确的认识:它们都可以先定义答案范围,再根据判断结果驱动下一步操作。接入时,我会优先明确输入、选项、采纳条件和兜底路径,再评估Jev是否适合承担这一环节。结合这些实践,我更容易理解Jev(TypeSafe System One)作为专用结构化决策模型不生成自然语言,而是返回带概率的判断结果。后续接入时,我会继续从脚本中边界明确的判断任务开始,分别验证准确性、耗时和费用,再决定是否扩大使用范围。下面整理了相关能力、限制和接入要点,便于查阅。

SmartCodeTech的博客 345

国产算力·昇腾 910C 大模型推理优化(下):源码修改与算子优化,提速30%|得物技术

本文延续上篇,深入vllm-ascend源码优化:通过多流重叠实现MoE共享专家并行计算,消除冗余事件开销,并解除与FUSED_MC2的互斥限制,实现c=1下TPOT从8.2ms降至8.0ms;优化decode阶段host侧开销,引入状态跟踪跳过冗余拷贝;设计Block Table CPU快路径,规避小batch下NPU kernel启动延迟;针对GDN层融合L2Norm至recurrent kernel,减少算子调用与内存往返。综合优化后推理性能显著提升,形成可复用的昇腾910C大模型推理优化方法论。

SmartCodeTech的博客 245

国产算力·昇腾 910C 大模型推理优化(上):镜像更新与参数调优,提速 40%|得物技术

文中详细给出每一项优化的动机、实现(含具体源码改动路径与关键代码片段)、验证数据与踩坑记录(包括十余项实测无效或负向的尝试),希望为同样在国产算力上做推理优化的团队提供一份可直接复用的工程参考。

SmartCodeTech的博客 225

动态规则的 Agent 实践:用确定性工程驾驭 LLM 的资产智能验收

面对财务验收中规则多变、材料非结构化、核对复杂等痛点,传统规则引擎难以应对。系统采用“规则即配置”思路,由大语言模型(LLM)负责理解合同、扫描件等非结构化材料并执行语义比对,工程系统则保障流程编排与可追溯性。通过异步处理、幂等设计、三类流量隔离及双通道(文本/图像)处理,实现高效稳定运行。结合用户反馈构建自动标准答案,辅以试跑、回测与发布门禁机制,形成闭环质量体系。底层采用确定性工作流架构,确保行为可预期、可测试,真正实现灵活规则的快速迭代与安全上线。

SmartCodeTech的博客 344

发一张图,它居然“跃“出屏幕了?一文读懂得物 3D 空间图片技术实践

3D 空间图片功能的落地,涉及模型生成、内容分发、客户端渲染之间的一系列取舍。本文重点分享如何生产出高质量、小体积的模型,以及如何在手机上流畅运行。

SmartCodeTech的博客 555

别再只卷向量检索了,得物交易搜索如何用“生成式”实现召回范式跃迁?

你搜"af1",它得给你"空军一号"。这一年,得物交易搜索把召回从"做选择题"改成了"写答案"——不再从商品池里"找"最像的,而是让模型自己"生成"你真正想要的。从 LLM 语义索引到 HLLM、语义 ID,搜索是怎么从"检索"走向"生成"的?

SmartCodeTech的博客 594

指标平台:从语义底座到智能消费的实践路径|得物技术

这篇文章想做的,不是在本体化的宏大叙事上再叠加一层理论,而是把我们在真实落地中验证过的路径讲清楚:语义底座怎么从零建立起来、怎么保证质量不失控、怎么支撑 Text2SQL 和 AI Coding 两条消费主线,以及沿着这条路径往前走,下一步该往哪个方向发力。

SmartCodeTech的博客 317

企业级 MultiAgent 落地:Plan 模式与主子 Agent 协作|得物技术

基于 AgentScope Java 的企业级 MultiAgent 平台,为研发、数据分析和知识问答等场景提供统一的模型调用、工具接入、任务编排、流式输出与运行追踪能力。

SmartCodeTech的博客 302

得物小摊 AI Native 演进实录:用 Harness 构建可控 AI 交付

AI Coding 一个人用很顺手,进了团队就漏:指令没人审、经验难沉淀、过程看不见、链路不闭环。作者团队基于 Multica 做了 EP-Harness,把 Agent 当成员管,给它套一层可执行、可观察、可治理的 Harness,并让反馈闭环。成果:可追溯决策、多 Agent 协作,高频异常从每 4 小时 2400 多条降到个位数,对得物技术补上团队级 AI 协作关键一环。

SmartCodeTech的博客 543

企业级 MultiAgent 的记忆系统:短期上下文与四层记忆架构实现|得物技术

在 MultiAgent 平台中,Agent 的"记忆"能力是实现智能对话和个性化服务的核心资产。本文深入剖析 Agent 记忆系统的设计理念与实现细节,重点解析长期记忆架构的写入与加载流程,涵盖 LLM 智能判断、语义检索、Token 预算控制、冲突处理等关键技术,为开发者提供完整的技术实现参考。

SmartCodeTech的博客 502

EP-Harness:从个人 AI Coding 到团队级 Agent 工作流|得物技术

AI Coding 个人用得爽,一到团队就崩。EP-Harness 把 Agent 从聊天工具变成团队协作成员——可管理、可追溯、可闭环。落地后高频异常从 2400+/4h 收敛到个位数。

SmartCodeTech的博客 694

得物知识问答:复合检索 Agent 的系统设计实践

从"搜到什么用什么"到"搜→筛→挖→验"自主决策闭环——我们造了一个有判断力的 RAG Agent,不是套壳。

SmartCodeTech的博客 734

实战从零开始构建一个Coding Agent:Violin |得物技术

理解了 coding agent 的构建原理,也就掌握了理解其他 agent 的一把钥匙。笔者对每天都在使用的 agent 原理很感兴趣,于是决定自己写一个:violin。

SmartCodeTech的博客 927

AI Native 交易核心系统的研发范式|得物技术

如何改造旧研发流程适配 AI 编码?本文提出五道标准化关口治理思路,依托 Claude Code Spec-Driven 插件打通需求澄清、方案设计、TDD 落地、门禁管控与埋点监控,构建带人工确认门控的完整工作流,以五层自底向上架构实现 AI 编码规范化落地。

SmartCodeTech的博客 975

推荐系统体验的数字化突破:得物自动化评测平台的技术实践|AICon 文章整理

「得物推荐 AI Harness 工程化实践系列」的末篇内容,本系列共三篇连载。本篇(末篇)详解得物推荐评测平台的完整技术体系:从主观体验量化到大模型自动化评测流水线,涵盖多维度指标设计、人机协作提示词校验闭环、分布式任务调度与成本精控等核心工程实现,以及单周百万级审计需求下实现 91% 资源成本优化的工业级落地实战细节。

SmartCodeTech的博客 1494

RAG 核心概念与原理:Chunking、Embedding、相似度、HNSW 与多路召回|得物技术

决定 RAG 效果的关键不在大模型,而是文本切块、查询改写、多路召回与精排。合理切块存好知识库内容,向量匹配抓语义、BM25 匹配关键词互补。先优化用户提问,快速召回一批相关文档,再用精排模型精细筛选,整套检索流程配合到位,问答准确度才会明显提升。

SmartCodeTech的博客 1079

从“机械应答“到“服务伙伴“:得物高可控智能客服的 Agent 工程实践|AICon 演讲整理

本次分享围绕以下核心技术展开:客服 Agent 挑战与架构设计(Single-Agent→Multi-Agent→Harness);高可控性数据飞轮(PE 自动化 + DPO 训练);RL 策略训练和人工经验对齐;多轮半双工消息流控制。

SmartCodeTech的博客 750

得物推荐系统诊断 Agent:从 “调接口” 到 “会思考”|AICon 演讲整理

本文是得物技术专家在 AICon 上海演讲整理的技术实录。AICon上海2026_全球人工智能开发与应用大会暨大模型应用生态展_InfoQ技术大会「得物推荐 AI Harness 工程化实践系列」的中篇内容,本系列共三篇连载。本篇(中篇)进一步详解得物推荐复杂业务场景下,AI代码从生成、防护校验到安全上线的完整技术体系、自研AI Harness整体架构框架、全流程安全防护机制、混合智能体核心算法实现,以及工业级工程落地的实战细节。

SmartCodeTech的博客 1364

得物 OceanBase 落地实践

得物选型OceanBase多模数据库应对业务挑战,通过验证其高可用架构、存储压缩技术及混合负载处理能力。测试显示OceanBase在复杂查询场景性能较MySQL提升130-200倍,在高并发TP/AP混合场景表现优异,存储成本降低40%+。通过DBA内部报表业务试点验证其稳定性后,逐步推广至核心业务场景,优化数据库技术栈,实现性能与成本的双重收益。

SmartCodeTech的博客 1383

AI UITester:AI Native 的 UI 自动化测试新范式|得物技术

ai_uitester 代表了 AI Native 的 UI 自动化测试新范式:这不仅是工具的升级,而是测试范式的转变 ------ 从 "代码驱动" 转向 "视觉驱动",从 "人工调试" 转向 "AI 自愈",从 "三端分离" 转向 "统一抽象"。

SmartCodeTech的博客 779

从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理

本文是得物技术专家在 AICon 上海演讲整理的技术实录。「得物推荐 AI Harness 工程化实践系列」的开篇内容,本系列共三篇连载。将系统拆解得物推荐复杂业务场景下,AI 代码从生成、防护校验到安全上线的完整技术体系,逐一详解自研 AI Harness 整体架构框架、全流程安全防护机制、混合智能体核心算法实现,以及工业级工程落地的实战细节。本篇(上篇):将整体介绍团队自研的 AI Harness 体系,包括建设思路、全生命周期防护机制、混合智能体架构及落地效果。

SmartCodeTech的博客 1082

从表单到 Agent:得物社区活动搭建的 AI 实践之路

一场营销活动从策划到上线,运营要在三个系统间跳转 10 + 次、填写 40 + 个字段。我们用 AI 重新设计了这条链路 —— 从 “AI 帮你填表单” 到 “两阶段 Agent + 聚合工作台”。这篇文章记录的不是技术细节,而是这条路上的选择和反思。

SmartCodeTech的博客 744

从埋点需求到规则资产:Hermes Agent 重构得物数仓工作流

埋点和指标需求中,消耗数据承接方的不是生成答案,而是补齐证据链、对齐历史口径、识别下游影响,并在生产写入前留下可追溯的确认记录。本文数据承接方指承接业务需求的数据同学或业务合作伙伴;后文讨论内部研发、元数据、查询和门禁能力在流程中的角色。

SmartCodeTech的博客 657

让 Claude Code 拥有自我进化和记忆系统|得物技术

本文记录了为 Claude Code 构建的一套持久化记忆与自我学习系统的设计思路与实现细节。这套系统让 AI 助手能够跨越会话边界记住用户习惯,并在每次对话结束后自动提炼行为规律和系统信息,通过向量检索快速提取关键信息,下一次对话时主动应用,逐步进化为更懂你的编程伙伴。

SmartCodeTech的博客 994

用 LLM Agent 重构告警排查流程|得物技术

告警排查需频繁切换日志、APM、链路追踪等多个平台,耗时 10~30 分钟,且高度依赖个人经验。我们做了 Troubleshooter——用 LLM Agent 自动完成数据采集、根因分析和处置建议生成。上线后中位数排查耗时从 20 分钟降到 4.4 分钟,覆盖 11 个服务和 10+ 种告警类型。

SmartCodeTech的博客 1008

HorizonVault 技术深潜:如何在 HDD 上做出 100GB/s+ 级大吞吐分布式存储|得物技术

HorizonVault是一款面向Kafka远程存储的高吞吐分布式存储引擎,通过分布式并行写入和状态感知调度解决冷数据存储的三大核心问题:吞吐瓶颈、性能抖动和恢复能力。系统采用分层架构,Meta负责全局资源调度,Broker处理请求路由,Store实现本地磁盘管理,形成完整的写入治理链路。通过将HDD磁盘提升为一等资源,实现顺序追加写入、多盘并行和慢盘隔离,在保证高吞吐的同时控制延迟。存储结构采用DiskStore组织磁盘资源,LogSegment顺序写入数据,IndexSegment定位读取,Change

SmartCodeTech的博客 892

Claude Code Harness 工程:数仓侧落地方案|得物技术

Harness 工程通过职责分层实现研发流水线可靠性提升。Claude 负责需求理解与代码生成等语义层工作;hooks 负责规范检查等确定性执行;Subagents 隔离血缘查询、自测等高 token 操作;Memory 承载跨会话状态持久化。四层协同使数仓 AI 开发从"对话式辅助"转变为"规则驱动的自动化流程"。

SmartCodeTech的博客 1101

BP Claw 破解 AI 编码输入难题 ——FlinkSpec 需求智能化实践|得物技术

本文为 FlinkSpec 系列之开篇,亦是这场工程化变革的序章。BP Claw 所立之处,不过链路之源。FlinkSpec 所图,乃以 AI 之力,将实时数仓从需求落地至验收上线的全程工序,熔铸为一套精密自洽、生生不息的智能工程体系。宏图未竟,后续系列将逐章揭幕,敬请期待!

SmartCodeTech的博客 1039
上一篇: 虚拟线程原理及性能分析
下一篇: 得物商家域精准测试实践
得物技术
得物技术 得物技术官方账号 得物技术官方账号
博客等级 码龄6年 2492粉丝 408原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值