<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Apache SkyWalking – WeChat</title>
    <link>/tags/wechat/</link>
    <description>Recent content in WeChat on Apache SkyWalking</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 30 Apr 2026 00:00:00 +0000</lastBuildDate>
    
	  <atom:link href="/tags/wechat/feed.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Blog: Monitoring WeChat and Alipay Mini Programs with SkyWalking</title>
      <link>/blog/2026-04-30-mini-program-monitoring-with-skywalking/</link>
      <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
      <guid>/blog/2026-04-30-mini-program-monitoring-with-skywalking/</guid>
      <description>
        
        
        &lt;p&gt;Mini programs are a major part of the mobile experience in China, but the open-source observability ecosystem has long focused on web browsers and native apps. SkyWalking already covers browser (client-js), iOS, and the server side; mini programs and Android were the remaining gaps. With &lt;a href=&#34;https://github.com/SkyAPM/mini-program-monitor&#34;&gt;SkyAPM/mini-program-monitor&lt;/a&gt; joining the SkyWalking ecosystem, the mini-program half of that gap is closed — one SDK supports both WeChat and Alipay, and the matching OAP-side component IDs, MAL rules, and UI templates are merged on &lt;code&gt;main&lt;/code&gt; and will ship with 10.5.0.&lt;/p&gt;
&lt;p&gt;This post is for teams that already run a SkyWalking backend and want to bring their mini programs into the same observability stack. The interesting parts aren&amp;rsquo;t &lt;em&gt;that&lt;/em&gt; the project exists — they are how the data flows from a mini program to a SkyWalking dashboard, how the two platforms coexist, and what design trade-offs you should know about before rolling this out.&lt;/p&gt;
&lt;h2 id=&#34;data-path&#34;&gt;Data path&lt;/h2&gt;
&lt;p&gt;The SDK uses two protocols:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OTLP HTTP&lt;/strong&gt; (error logs, performance metrics, request metrics) → OAP &lt;code&gt;/v1/logs&lt;/code&gt;, &lt;code&gt;/v1/metrics&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SkyWalking native&lt;/strong&gt; (distributed tracing segments, optional) → OAP &lt;code&gt;/v3/segments&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why not a single protocol? OTLP already covers logs and metrics, so there&amp;rsquo;s no point reinventing native endpoints for those. But for tracing, OAP&amp;rsquo;s native &lt;code&gt;SegmentObject&lt;/code&gt; maps more cleanly onto SkyWalking&amp;rsquo;s trace model, and &lt;code&gt;sw8&lt;/code&gt; header propagation to the backend works without any conversion. So traces go native, everything else goes OTLP, and neither side has to translate.&lt;/p&gt;
&lt;p&gt;OTLP defaults to protobuf; JSON is available for debugging. The SDK has zero runtime dependencies.&lt;/p&gt;
&lt;h2 id=&#34;two-platforms-two-independent-layers-and-dashboards&#34;&gt;Two platforms, two independent Layers and dashboards&lt;/h2&gt;
&lt;p&gt;Many teams maintain a WeChat mini program and an Alipay mini program against a shared backend. Rather than collapsing them into a single tagged service, the design promotes each platform to its own Layer — &lt;code&gt;WECHAT_MINI_PROGRAM&lt;/code&gt; and &lt;code&gt;ALIPAY_MINI_PROGRAM&lt;/code&gt; — with its own dashboard set. The SDK tags every signal with a resource attribute &lt;code&gt;miniprogram.platform = wechat | alipay&lt;/code&gt; and assigns each platform its own component ID (WeChat = 10002, Alipay = 10003).&lt;/p&gt;
&lt;p&gt;On the OAP side, the MAL rule&amp;rsquo;s &lt;code&gt;filter&lt;/code&gt; routes data into the right Layer at ingest:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;metricPrefix&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;meter_wechat_mp&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;filter&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;{ tags -&amp;gt; tags.miniprogram_platform == &amp;#39;wechat&amp;#39; }&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Alipay rule mirrors this with &lt;code&gt;&#39;alipay&#39;&lt;/code&gt;. The two rules are mutually exclusive — no double counting — and produce distinct metric prefixes (&lt;code&gt;meter_wechat_mp_*&lt;/code&gt; vs &lt;code&gt;meter_alipay_mp_*&lt;/code&gt;) that feed each Layer&amp;rsquo;s dashboards. Even when both platforms use the same &lt;code&gt;service.name&lt;/code&gt; (e.g. &lt;code&gt;mini-program-demo&lt;/code&gt;), the UI exposes two completely separate entry points.&lt;/p&gt;
&lt;h2 id=&#34;asymmetric-metric-semantics&#34;&gt;Asymmetric metric semantics&lt;/h2&gt;
&lt;p&gt;This is the design choice I want to highlight. WeChat&amp;rsquo;s base library exposes &lt;code&gt;PerformanceObserver&lt;/code&gt;, which gives you renderer-authoritative timings: app launch, first render, route navigation, script execution, sub-package load — all real measurements. Alipay&amp;rsquo;s base library doesn&amp;rsquo;t offer an equivalent, so the SDK falls back to lifecycle hooks: the &lt;code&gt;App.onLaunch → App.onShow&lt;/code&gt; delta is used as an approximation of launch time, and renderer-level timings simply aren&amp;rsquo;t available.&lt;/p&gt;
&lt;p&gt;So the two MAL rule sets are deliberately not the same:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WeChat&lt;/strong&gt;: &lt;code&gt;app_launch_duration&lt;/code&gt;, &lt;code&gt;first_render_duration&lt;/code&gt;, &lt;code&gt;route_duration&lt;/code&gt;, &lt;code&gt;script_duration&lt;/code&gt;, &lt;code&gt;package_load_duration&lt;/code&gt;, &lt;code&gt;request_duration_percentile&lt;/code&gt;, &lt;code&gt;request_cpm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alipay&lt;/strong&gt;: &lt;code&gt;app_launch_duration&lt;/code&gt;, &lt;code&gt;first_render_duration&lt;/code&gt;, &lt;code&gt;request_duration_percentile&lt;/code&gt;, &lt;code&gt;request_cpm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Alipay &lt;code&gt;app_launch_duration&lt;/code&gt; is a lifecycle approximation and is not directly comparable to WeChat&amp;rsquo;s renderer timing — the dashboard tooltip says so explicitly. Putting the two numbers side by side is comparing two different measurement definitions.&lt;/p&gt;
&lt;h2 id=&#34;what-the-sdk-does&#34;&gt;What the SDK does&lt;/h2&gt;
&lt;p&gt;Four signals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Errors&lt;/strong&gt; — JS exceptions, unhandled promise rejections, and &lt;code&gt;pageNotFound&lt;/code&gt; go out as OTLP logs, following the OTel &lt;code&gt;exception.*&lt;/code&gt; semantic conventions (&lt;code&gt;exception.type&lt;/code&gt;, &lt;code&gt;exception.stacktrace&lt;/code&gt;). Anything downstream that speaks OTLP — SkyWalking, OTel Collector, Grafana — recognizes them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;/strong&gt; — the metrics listed above. OTLP gauge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Requests&lt;/strong&gt; — &lt;code&gt;wx.request&lt;/code&gt; / &lt;code&gt;my.request&lt;/code&gt; / &lt;code&gt;downloadFile&lt;/code&gt; / &lt;code&gt;uploadFile&lt;/code&gt; are reported as OTLP delta histograms, one batch per &lt;code&gt;flushInterval&lt;/code&gt; (default 5s). The &lt;code&gt;le&lt;/code&gt; bucket labels are already in milliseconds, and the MAL rule explicitly declares &lt;code&gt;MILLISECONDS&lt;/code&gt; to disable the default SECONDS→MS rescale. Failed requests (4xx / 5xx / timeout) additionally emit an error log so you can pivot from a dashboard to a concrete failure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tracing (opt-in)&lt;/strong&gt; — when enabled, outbound requests get &lt;code&gt;sw8&lt;/code&gt; header injection, and the resulting segments stitch together with backend traces into one end-to-end view. Trace data goes out as SkyWalking &lt;code&gt;SegmentObject&lt;/code&gt;, not OTLP traces.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two reliability and cardinality details worth calling out:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Persisting events on app hide.&lt;/strong&gt; Mini programs get killed by the framework after some time in background, and weak networks make in-flight events easy to lose. The SDK writes unsent events to &lt;code&gt;wx.setStorage&lt;/code&gt; / &lt;code&gt;my.setStorage&lt;/code&gt; on &lt;code&gt;onAppHide&lt;/code&gt; and restores them on the next launch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoiding cardinality explosions.&lt;/strong&gt; Set &lt;code&gt;serviceInstance&lt;/code&gt; to the app version (e.g. &lt;code&gt;1.4.2&lt;/code&gt;), not a device ID — at a million DAU the device-ID dimension blows up the OAP instance index. For request paths, the SDK exposes &lt;code&gt;urlGroupRules&lt;/code&gt; regex patterns to fold parameterized URLs like &lt;code&gt;/api/user/12345&lt;/code&gt; into &lt;code&gt;/api/user/{id}&lt;/code&gt; so the endpoint dimension doesn&amp;rsquo;t blow up either.&lt;/p&gt;
&lt;h2 id=&#34;what-oap-needs&#34;&gt;What OAP needs&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re on &lt;code&gt;main&lt;/code&gt; or a release ≥ 10.5.0, the following are already shipped:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config/component-libraries.yml&lt;/code&gt; registers &lt;code&gt;WeChat-MiniProgram: 10002&lt;/code&gt; and &lt;code&gt;AliPay-MiniProgram: 10003&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/otel-rules/miniprogram/&lt;/code&gt; holds four MAL rules — service-scoped and instance-scoped for each platform&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/ui-initialized-templates/wechat_mini_program/&lt;/code&gt; and &lt;code&gt;alipay_mini_program/&lt;/code&gt; carry root / service / instance / endpoint dashboards&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/ui-initialized-templates/menu.yaml&lt;/code&gt; registers both layers under the Mobile menu group&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only thing left is enabling the OTel receiver and giving the SDK an OTLP HTTP port it can reach. SkyWalking OAP binds its OTLP HTTP handler onto the receiver-sharing-server port, and that port defaults to &lt;code&gt;0&lt;/code&gt; — meaning it&amp;rsquo;s folded into the core REST port (12800). If you want the SDK to use the standard OTLP HTTP port 4318, set the sharing port to 4318:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d --name sw-oap &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -p 11800:11800 -p 12800:12800 -p 4318:4318 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_STORAGE&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;banyandb &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_STORAGE_BANYANDB_TARGETS&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;banyandb:17912 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_OTEL_RECEIVER&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;default &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_RECEIVER_SHARING_REST_PORT&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;4318&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  apache/skywalking-oap-server:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All receivers (OTLP, native segment, browser perf, log report) move to 4318 together, while GraphQL stays on 12800 for the UI.&lt;/p&gt;
&lt;p&gt;Minimal SDK config:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cf222e&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;MiniProgramMonitor&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;mini-program-monitor&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;MiniProgramMonitor&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;init&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;service&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;mini-program-demo&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;serviceInstance&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;1.4.2&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;          &lt;span style=&#34;color:#57606a&#34;&gt;// Recommended: app version
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;collector&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;http://your-oap:4318&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;enable&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;error&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;perf&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;request&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;tracing&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;false&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;                  &lt;span style=&#34;color:#57606a&#34;&gt;// Off by default; enable as needed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;WeChat and Alipay use the same config — the SDK detects the platform at runtime and tags the data accordingly.&lt;/p&gt;
&lt;h2 id=&#34;compatibility&#34;&gt;Compatibility&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;WeChat base library ≥ 2.11&lt;/li&gt;
&lt;li&gt;Alipay base library ≥ 2.0&lt;/li&gt;
&lt;li&gt;Apache SkyWalking OAP &lt;code&gt;main&lt;/code&gt; or ≥ 10.5.0, with the OTLP HTTP receiver enabled&lt;/li&gt;
&lt;li&gt;Any other OTLP-compatible backend (OpenTelemetry Collector, Grafana, etc.) also works, but you won&amp;rsquo;t get the SkyWalking-specific cross-platform dashboards&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next&lt;/h2&gt;
&lt;p&gt;To get involved, head over to &lt;a href=&#34;https://github.com/SkyAPM/mini-program-monitor&#34;&gt;SkyAPM/mini-program-monitor&lt;/a&gt; and open an issue or PR. The repo also ships a &lt;code&gt;make preview&lt;/code&gt; target that boots OAP, the UI, and both platform simulators locally — handy if you want to play with it end-to-end.&lt;/p&gt;
&lt;p&gt;Android end-user experience monitoring is still a gap in the SkyWalking ecosystem; contributors interested in closing that one are very welcome.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Zh: 用 SkyWalking 监控微信和支付宝小程序</title>
      <link>/zh/2026-04-30-mini-program-monitoring-with-skywalking/</link>
      <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
      <guid>/zh/2026-04-30-mini-program-monitoring-with-skywalking/</guid>
      <description>
        
        
        &lt;p&gt;小程序是国内移动端体验里绕不过去的一块，但开源监控生态长期偏向 Web 浏览器和原生 App。SkyWalking 自身已经覆盖了浏览器（client-js）、iOS、服务端，缺口主要在小程序和 Android。&lt;a href=&#34;https://github.com/SkyAPM/mini-program-monitor&#34;&gt;SkyAPM/mini-program-monitor&lt;/a&gt; 加入 SkyWalking 生态后，把这块缺口的小程序部分补上了 —— 一份 SDK 同时支持微信和支付宝，OAP 端的 component、MAL 规则、UI 模板已经合进 main 分支，会随 10.5.0 一起发布。&lt;/p&gt;
&lt;p&gt;这篇博客面向已经跑着 SkyWalking 后端、希望把小程序也接进来的团队。重点不是&amp;quot;项目存在&amp;quot;这件事，而是数据从小程序到 SkyWalking dashboard 走的是哪条路、双平台是怎么共存的、以及上线之前需要知道哪些设计取舍。&lt;/p&gt;
&lt;h2 id=&#34;数据通路&#34;&gt;数据通路&lt;/h2&gt;
&lt;p&gt;SDK 走两条腿：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OTLP HTTP&lt;/strong&gt;（错误日志、性能指标、请求指标）→ OAP 的 &lt;code&gt;/v1/logs&lt;/code&gt;、&lt;code&gt;/v1/metrics&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SkyWalking 原生协议&lt;/strong&gt;（链路追踪 segment，可选）→ OAP 的 &lt;code&gt;/v3/segments&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为什么不是单协议？OTLP 已经覆盖了 logs 和 metrics 两类信号，没必要再造一份原生 endpoint；但分布式追踪上 OAP 的原生 &lt;code&gt;SegmentObject&lt;/code&gt; 比 OTLP traces 表达力更贴 SkyWalking 自己的 trace 模型，且与服务端通过 &lt;code&gt;sw8&lt;/code&gt; header 透传时无需任何转换。所以追踪走原生，其它走 OTLP，两边都不绕路。&lt;/p&gt;
&lt;p&gt;OTLP 默认用 protobuf，调试时可切成 JSON。SDK 没有任何运行时依赖。&lt;/p&gt;
&lt;h2 id=&#34;双平台对应两个独立的-layer-与监控面板&#34;&gt;双平台对应两个独立的 Layer 与监控面板&lt;/h2&gt;
&lt;p&gt;很多团队会同时维护一个微信小程序和一个支付宝小程序，业务逻辑共享一个后端。这套设计没有把它们塞进同一个 service 用 tag 区分，而是直接做成两个独立的 Layer：&lt;code&gt;WECHAT_MINI_PROGRAM&lt;/code&gt; 和 &lt;code&gt;ALIPAY_MINI_PROGRAM&lt;/code&gt;，对应两套独立的监控面板。SDK 在每个信号上打 resource 属性 &lt;code&gt;miniprogram.platform = wechat | alipay&lt;/code&gt;，并给两端各分配独立的 component ID（微信 10002、支付宝 10003）。&lt;/p&gt;
&lt;p&gt;OAP 这一头是用 MAL 规则的 &lt;code&gt;filter&lt;/code&gt; 把数据在 ingest 阶段就分流到对应 Layer 的：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;metricPrefix&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;meter_wechat_mp&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;filter&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;{ tags -&amp;gt; tags.miniprogram_platform == &amp;#39;wechat&amp;#39; }&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;支付宝那份规则同理过滤 &lt;code&gt;alipay&lt;/code&gt;。两份规则互斥，不会重复计数；输出的 metric 前缀也不一样（&lt;code&gt;meter_wechat_mp_*&lt;/code&gt; vs &lt;code&gt;meter_alipay_mp_*&lt;/code&gt;），各自落在对应 Layer 的 dashboard 上。即使两端用同一个 &lt;code&gt;service.name&lt;/code&gt;（比如都叫 &lt;code&gt;mini-program-demo&lt;/code&gt;），UI 里也是两套完全独立的入口。&lt;/p&gt;
&lt;h2 id=&#34;不对等的指标语义&#34;&gt;不对等的指标语义&lt;/h2&gt;
&lt;p&gt;这是这套设计里我特别想强调的一处诚实选择。微信的基础库提供 &lt;code&gt;PerformanceObserver&lt;/code&gt;，能拿到来自渲染层的权威时序：app launch、first render、route navigation、script execution、sub-package load 都是真实指标。支付宝的基础库不提供等价 API，SDK 只能用生命周期回退做近似：&lt;code&gt;App.onLaunch → App.onShow&lt;/code&gt; 的 delta 当作启动时间，渲染相关的拿不到。&lt;/p&gt;
&lt;p&gt;所以两份 OAP 规则里的 metric 集合不对等：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;微信：&lt;code&gt;app_launch_duration&lt;/code&gt;、&lt;code&gt;first_render_duration&lt;/code&gt;、&lt;code&gt;route_duration&lt;/code&gt;、&lt;code&gt;script_duration&lt;/code&gt;、&lt;code&gt;package_load_duration&lt;/code&gt;、&lt;code&gt;request_duration_percentile&lt;/code&gt;、&lt;code&gt;request_cpm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;支付宝：&lt;code&gt;app_launch_duration&lt;/code&gt;、&lt;code&gt;first_render_duration&lt;/code&gt;、&lt;code&gt;request_duration_percentile&lt;/code&gt;、&lt;code&gt;request_cpm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;支付宝侧的 &lt;code&gt;app_launch_duration&lt;/code&gt; 是生命周期近似值，与微信的渲染层数值不可直接对比，这一点在 dashboard 的字段提示里也写明了。把两个数字放一起做横评等于在比较两种不同测量定义。&lt;/p&gt;
&lt;h2 id=&#34;sdk-端做了什么&#34;&gt;SDK 端做了什么&lt;/h2&gt;
&lt;p&gt;四类信号：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;错误&lt;/strong&gt;：JS 异常 / unhandled promise rejection / pageNotFound 走 OTLP logs，按 OTel &lt;code&gt;exception.*&lt;/code&gt; 语义约定（&lt;code&gt;exception.type&lt;/code&gt;、&lt;code&gt;exception.stacktrace&lt;/code&gt;），下游不光 SkyWalking，OTel Collector / Grafana 也都认。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能&lt;/strong&gt;：上面那张表里那些。OTLP gauge。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;请求&lt;/strong&gt;：&lt;code&gt;wx.request&lt;/code&gt; / &lt;code&gt;my.request&lt;/code&gt; / &lt;code&gt;downloadFile&lt;/code&gt; / &lt;code&gt;uploadFile&lt;/code&gt; 都走 OTLP delta histogram，每个 flush 间隔（默认 5s）发一次增量。&lt;code&gt;le&lt;/code&gt; 桶标签直接用 ms，OAP MAL 里显式声明 &lt;code&gt;MILLISECONDS&lt;/code&gt; 阻止默认的 SECONDS→MS 缩放。失败请求（4xx/5xx/超时）额外发一条错误日志，方便从 dashboard 跳到具体错误。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;追踪（可选）&lt;/strong&gt;：开启后给出站请求注入 &lt;code&gt;sw8&lt;/code&gt; 头，落到 OAP 后能与服务端 trace 拼成一条完整链路。trace 段以 SkyWalking &lt;code&gt;SegmentObject&lt;/code&gt; 形式发出，不走 OTLP traces。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可靠性和基数控制的两个细节值得一提：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;App hide 时落本地存储&lt;/strong&gt;。小程序后台一段时间会被框架杀掉，弱网时也容易丢包。SDK 在 &lt;code&gt;onAppHide&lt;/code&gt; 时把未发送的事件写到 &lt;code&gt;wx.setStorage&lt;/code&gt; / &lt;code&gt;my.setStorage&lt;/code&gt;，下次启动恢复并继续上报。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;反基数膨胀&lt;/strong&gt;。强烈建议把 &lt;code&gt;serviceInstance&lt;/code&gt; 设成应用版本号（如 &lt;code&gt;1.4.2&lt;/code&gt;），不要用设备 ID —— 小程序日活百万级时设备 ID 维度直接把 OAP 的 instance 索引打爆。请求路径方面 SDK 提供 &lt;code&gt;urlGroupRules&lt;/code&gt; 正则把 &lt;code&gt;/api/user/12345&lt;/code&gt; 这类参数化路径归并到 &lt;code&gt;/api/user/{id}&lt;/code&gt;，避免 endpoint 维度也膨胀。&lt;/p&gt;
&lt;h2 id=&#34;oap-端要做什么&#34;&gt;OAP 端要做什么&lt;/h2&gt;
&lt;p&gt;如果你用的是 main 分支或者 10.5.0 之后的发布版，下面这些已经内置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config/component-libraries.yml&lt;/code&gt;：注册了 &lt;code&gt;WeChat-MiniProgram: 10002&lt;/code&gt; 和 &lt;code&gt;AliPay-MiniProgram: 10003&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/otel-rules/miniprogram/&lt;/code&gt;：四份 MAL 规则，按 service / instance 维度分别定义&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/ui-initialized-templates/wechat_mini_program/&lt;/code&gt; 和 &lt;code&gt;alipay_mini_program/&lt;/code&gt;：root / service / instance / endpoint 四张 dashboard&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/ui-initialized-templates/menu.yaml&lt;/code&gt;：把两个 layer 注册到 Mobile 菜单组下&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;唯一需要做的就是确认 OTel receiver 启用、给 OTLP HTTP 一个 SDK 能直连的端口。SkyWalking OAP 的 OTLP HTTP handler 默认绑在 receiver-sharing-server 的端口上，而该端口默认值是 0（即复用 core REST 端口 12800）。如果想让 SDK 用标准 OTLP HTTP 端口 4318，把 sharing 端口设到 4318：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d --name sw-oap &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -p 11800:11800 -p 12800:12800 -p 4318:4318 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_STORAGE&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;banyandb &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_STORAGE_BANYANDB_TARGETS&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;banyandb:17912 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_OTEL_RECEIVER&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;default &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -e &lt;span style=&#34;color:#953800&#34;&gt;SW_RECEIVER_SHARING_REST_PORT&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;4318&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  apache/skywalking-oap-server:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样所有 receiver（OTLP + native segment + browser perf + log report）一起搬到 4318，GraphQL 仍在 12800 给 UI 用。&lt;/p&gt;
&lt;p&gt;SDK 端配置最小集：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cf222e&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;MiniProgramMonitor&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;mini-program-monitor&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;MiniProgramMonitor&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;init&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;service&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;mini-program-demo&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;serviceInstance&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;1.4.2&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;          &lt;span style=&#34;color:#57606a&#34;&gt;// 推荐：应用版本号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;collector&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;http://your-oap:4318&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;enable&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;error&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;perf&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;request&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;tracing&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cf222e&#34;&gt;false&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;                  &lt;span style=&#34;color:#57606a&#34;&gt;// 默认关，按需开
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#1f2328&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;微信和支付宝两端配置一模一样，平台标签由 SDK 在运行时自动判定。&lt;/p&gt;
&lt;h2 id=&#34;兼容性&#34;&gt;兼容性&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;微信基础库 ≥ 2.11&lt;/li&gt;
&lt;li&gt;支付宝基础库 ≥ 2.0&lt;/li&gt;
&lt;li&gt;Apache SkyWalking OAP main 分支或 ≥ 10.5.0；OTLP HTTP receiver 启用即可&lt;/li&gt;
&lt;li&gt;也可对接任意 OTLP 后端（OpenTelemetry Collector、Grafana 等），但那条路上拿不到 SkyWalking 专属的双平台 dashboard&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;后续&#34;&gt;后续&lt;/h2&gt;
&lt;p&gt;参与方式直接去 &lt;a href=&#34;https://github.com/SkyAPM/mini-program-monitor&#34;&gt;SkyAPM/mini-program-monitor&lt;/a&gt; 提 issue / PR。仓库里有一个 &lt;code&gt;make preview&lt;/code&gt; 一键拉起 OAP、UI、两端模拟器的本地 demo 环境，想看效果可以直接跑。&lt;/p&gt;
&lt;p&gt;Android 端的端用户体验监控目前还是 SkyWalking 生态的空白，欢迎对这块感兴趣的同学一起补齐。&lt;/p&gt;

      </description>
    </item>
    
  </channel>
</rss>
