)]}'
{
  "log": [
    {
      "commit": "be0383a4fd87111a781175f2633c97c2fe9cca99",
      "tree": "2fd74b9b2b01a0162c1f7c1dee34bb9078726060",
      "parents": [
        "dddc3b51be9d027755d48e99f72b362e969ccecd"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Jul 29 07:51:39 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 29 07:51:39 2026 +0800"
      },
      "message": "Always send an explicit LIMIT on BanyanDB queries (#13961)\n\nBanyanDB applies its own default limit to any query that carries none --\n100 rows for measures, 20 for streams/traces -- and applies it after\nGROUP BY, so an over-long result set is silently truncated rather than\nrejected.\n\nOAP never sent a limit on several read paths, so an entity-scoped metrics\nquery returned at most 100 data points regardless of the requested range:\na 4-hour minute-step read rendered only its first 100 minutes and the rest\nshowed as empty, even though DurationUtils.MAX_TIME_RANGE allows up to 500\nsteps. The same cap silently shortened topology relation maps, instance\nand process metadata lists, profiling thread snapshots and eBPF task lists.\n\nEvery BydbQL query now leaves OAP with an explicit LIMIT:\n\n- the entity-scoped metrics read sends the exact number of assembled\n  duration points, the same row set the ES/JDBC DAOs fetch by explicit id;\n- ad-hoc SELECT TOP sends its own N;\n- anything that does not paginate itself falls back to the configured\n  resultWindowMaxSize (default 10000) via Conditions#limitIfAbsent, applied\n  in the stream/measure/trace query helpers that every DAO funnels through.\n\nThe fallback is spliced in at the start of the pagination tail rather than\nappended, so it lands ahead of an OFFSET that was set first and keeps\nWITH QUERY_TRACE positioned as the grammar requires.\n\nES and JDBC storage were never affected -- both fetch metrics rows by\nexplicit document id."
    },
    {
      "commit": "dddc3b51be9d027755d48e99f72b362e969ccecd",
      "tree": "dfa368cb1b273fb4019f5e2509d7dacb9125a973",
      "parents": [
        "2822f125ae3ec397c5339ba172aee9ca3a09245f"
      ],
      "author": {
        "name": "kezhenxu94",
        "email": "kezhenxu94@apache.org",
        "time": "Fri Jul 24 20:19:39 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 20:19:39 2026 +0800"
      },
      "message": "Support Elasticsearch 9.x as storage (#13957)\n\nThe ES client version gate capped at major \u003d\u003d 8, so a server reporting\nmajor 9 fell through to UnsupportedOperationException and OAP refused to\nstart against an Elasticsearch 9 cluster. ES 9 keeps the same REST\nsurface the ES 8 path already uses (typeless document writes and\ncomposable index templates), so admit major \u003e\u003d 8 to that path.\n\nAdd ES 9.3.0 to the module IT (ElasticSearchIT) and a new Storage ES\n9.3.0 e2e case alongside the existing 8.18.8 coverage; update the storage\ndocs and changelog."
    },
    {
      "commit": "2822f125ae3ec397c5339ba172aee9ca3a09245f",
      "tree": "c8d0c2b139571cd34d903f731123b6bd990ea0ad",
      "parents": [
        "f9edc58aef0b5eb50fd5dd477010f55156651858"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Tue Jul 21 14:17:03 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 21 14:17:03 2026 +0800"
      },
      "message": "Route LAL rules within a layer by input type; add envoy-als-tcp rule (#13955)"
    },
    {
      "commit": "f9edc58aef0b5eb50fd5dd477010f55156651858",
      "tree": "8895c82ca3e9a01f071c6a87988ac91e71a1aead",
      "parents": [
        "4fae3c6a65ce51d0c66d983244fc3b28de7ba311"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Thu Jul 16 14:38:51 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 14:38:51 2026 +0800"
      },
      "message": "Clear Go e2e test-fixture CVE Dependabot alerts (x/net + Go stdlib) (#13951)"
    },
    {
      "commit": "4fae3c6a65ce51d0c66d983244fc3b28de7ba311",
      "tree": "a5cbc6f412833fd2e4f35a7966eb99ccc18bbe0b",
      "parents": [
        "5f6496e72c9acab1ce6ef107f3a168f6eaff8f40"
      ],
      "author": {
        "name": "mrproliu",
        "email": "741550557@qq.com",
        "time": "Wed Jul 15 20:49:50 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 15 13:49:50 2026 +0100"
      },
      "message": "Some enhancement check for bydbQL (#13949)"
    },
    {
      "commit": "5f6496e72c9acab1ce6ef107f3a168f6eaff8f40",
      "tree": "e50b25091f33de51ef74a536561f5f0f8a028173",
      "parents": [
        "46129f18e815829ea14afce9a013bae7d8dfdc66"
      ],
      "author": {
        "name": "mrproliu",
        "email": "741550557@qq.com",
        "time": "Wed Jul 15 12:58:50 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 15 12:58:50 2026 +0800"
      },
      "message": "Migrate all BanyanDB storage read queries from the typed query-builder API to BydbQL (#13947)"
    },
    {
      "commit": "46129f18e815829ea14afce9a013bae7d8dfdc66",
      "tree": "6fa138d949f9975636e7c54a3ddf066cabe80a91",
      "parents": [
        "432d55f2a7de58d797a382e7df823edfdb745358"
      ],
      "author": {
        "name": "kezhenxu94",
        "email": "kezhenxu94@apache.org",
        "time": "Mon Jul 13 14:32:31 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 13 14:32:31 2026 +0800"
      },
      "message": "Bump netty/jackson/commons-codec to clear CVE alerts on shipped OAP jars (#13944)\n\n- netty 4.2.12.Final -\u003e 4.2.15.Final (root pom netty.version)\n- jackson 2.18.6 -\u003e 2.18.8 (oap-server-bom)\n- jackson-databind 2.16.0 -\u003e 2.18.8 (realign to the rest of the jackson\n  family, which had moved ahead while databind was left behind)\n- commons-codec 1.11 -\u003e 1.13 (oap-server-bom)\n\nAll versions are JDK 11 compatible (SkyWalking targets maven.compiler.release\u003d11).\n\nUpdate dist-material/release-docs/LICENSE and .licenserc.yaml to match the\nbumped dependency versions (the CI dependency-license check regenerates\nLICENSE and fails on any drift).\n\nSigned-off-by: kezhenxu94 \u003ckezhenxu94@apache.org\u003e"
    },
    {
      "commit": "432d55f2a7de58d797a382e7df823edfdb745358",
      "tree": "6c7131b8a87c5cb6ae347af8a3596522a9bb64ee",
      "parents": [
        "585d195e79b665ce58ac108d325fa2f267a550af"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jul 07 20:51:47 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 07 20:51:47 2026 +0800"
      },
      "message": "Fix MQE top_n raising a raw storage IO exception for an invalid attribute (#13940)\n\nAn MQE top_n(metric, N, order, attrX\u003d\u0027value\u0027) whose attribute is not a queryable\ncolumn of the metric reached the storage engine with a tag the measure does not\ndefine and failed there, surfacing the opaque \"Internal IO exception, query\nmetrics error.\". Attribute columns (attr0..attrN) exist only on decorated metrics\n(service_*/endpoint_*/kubernetes_service_*, set to the layer via OAL .decorator())\nand the MAL meter base; relations and database/cache/mq access carry none.\n\nMQEVisitor now validates each attribute key against the metric\u0027s registered\nqueryable columns before the storage call and raises IllegalExpressionException\n(naming the attribute and metric), which the existing catch turns into a\ndescriptive MQE error instead of the opaque storage exception."
    },
    {
      "commit": "585d195e79b665ce58ac108d325fa2f267a550af",
      "tree": "19ccefe21dd61818a695d1f1a82577e486fdb7f8",
      "parents": [
        "5884dc8bae32d7529b37e0ee788a107ed1348bf5"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Jul 03 15:50:06 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 03 15:50:06 2026 +0800"
      },
      "message": "Surface LAL drop reason in DSL live-debugging (#13937)"
    },
    {
      "commit": "5884dc8bae32d7529b37e0ee788a107ed1348bf5",
      "tree": "f497f70fa7fce05c3d6b07a6f5d50bdfdef5e7cc",
      "parents": [
        "1432e5eeb20ce93a16978200ace289949b94b947"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Jul 03 08:32:21 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 03 08:32:21 2026 +0800"
      },
      "message": "Support LAL json{} parsing JSON delivered in text log bodies; fix abortOnFailure wiring and leak-probe timing (#13936)\n\nThe OTLP log receiver delivers every string body as a text body, even JSON-shaped ones, while `json {}` read only the JSON body case — so `json {}` rules on OTLP-fed layers silently aborted. `json {}` now reads the JSON body first and, when it is empty, tries the text body as JSON. On a successful text-fallback parse the matching rule\u0027s context input is swapped to a copy with a JSON body, so that rule persists the log with content type `JSON`; the shared input is never mutated, and other rules analyzing the same log still see the original text body. Design discussion is summarized in the updated [`lal.md` `json` section](https://github.com/apache/skywalking/blob/feat/otlp-log-json-body/docs/en/concepts-and-designs/lal.md#json) and [`log-otlp.md`](https://github.com/apache/skywalking/blob/feat/otlp-log-json-body/docs/en/setup/backend/log-otlp.md).\n\nThe DSL flag was parsed into the rule model but never emitted into the generated code, so `json {}` / `yaml {}` / `text { regexp }` always used the built-in default and `abortOnFailure false` had no effect (for all three parsers, including the regexp case). The compiler now bakes each rule\u0027s flag into the generated parser call (default `true`, as documented, fixed from a latent `false` model default). A parse failure or regexp non-match that aborts the log is reported at WARN, rate-limited to one report per minute per parser with the suppressed count included in the next report; with `abortOnFailure false` the failure is DEBUG-only, the log continues, and `parsed.*` reads fall back to metadata fields instead of NPE-dropping the log. Typed-proto inputs (e.g. Envoy ALS entries hitting the MESH `json {}` routing guard) stay quiet as before."
    },
    {
      "commit": "1432e5eeb20ce93a16978200ace289949b94b947",
      "tree": "6da70b0eaa03b0926844f0e84ef715fc3ccccdd9",
      "parents": [
        "eec76bacbc029e5b9974099cc0d9693841222d56"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Jul 02 21:09:43 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 02 21:09:43 2026 +0800"
      },
      "message": "Fix false-positive DSL classloader leak warnings on idle heaps (#13935)"
    },
    {
      "commit": "eec76bacbc029e5b9974099cc0d9693841222d56",
      "tree": "9d12d22c4a357bb9e3139067fb688ec7baa10231",
      "parents": [
        "08b0804be0d41c61c6371383ec5b6e2bde363605"
      ],
      "author": {
        "name": "kezhenxu94",
        "email": "kezhenxu94@apache.org",
        "time": "Tue Jun 30 22:11:37 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 22:11:37 2026 +0800"
      },
      "message": "Add TLS support for OAP HTTP/REST servers with cert hot-reload (#13933)\n\nThe gRPC servers already supported TLS, mTLS, and cert reload on rotation.\nThis adds the equivalent for the Armeria-based HTTP/REST servers (core REST /\nGraphQL, sharing REST, admin, PromQL, LogQL, TraceQL, Zipkin query/receiver):\n\n- HTTPServer now reloads the key pair from disk via Armeria\n  TlsProvider.ofScheduled, so rotated certificates (e.g. a refreshed Kubernetes\n  secret) are picked up without restarting the OAP. Previously the cert/key were\n  read once at startup.\n- Every HTTP server exposes the same restSSLEnabled / restSSLKeyPath /\n  restSSLCertChainPath config structure, each with its own dedicated environment\n  variables: SW_CORE_REST_SSL_*, SW_RECEIVER_SHARING_REST_SSL_*,\n  SW_ADMIN_SERVER_REST_SSL_*, SW_PROMQL_REST_SSL_*, SW_LOGQL_REST_SSL_*,\n  SW_TRACEQL_REST_SSL_*, SW_QUERY_ZIPKIN_REST_SSL_*, SW_RECEIVER_ZIPKIN_REST_SSL_*.\n  Each server reads the settings from its own module config.\n- HTTP TLS is server-side only (no mTLS).\n\nAdds HTTPServerTLSTest covering disk load, rotation pickup, and missing files;\nupdates application.yml and the TLS / configuration-vocabulary / changelog docs."
    },
    {
      "commit": "08b0804be0d41c61c6371383ec5b6e2bde363605",
      "tree": "12284a31e8eb923c8a46cc0b8f4dd6b7c4e9aa55",
      "parents": [
        "62423e4dfa63c0dffad021a57c803bfb1c7c6e4f"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 30 16:41:46 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 16:41:46 2026 +0800"
      },
      "message": "Surface BanyanDB config in /debugging/config/dump via a ConfigDumpExtension SPI (#13932)\n\n* Surface BanyanDB config in /debugging/config/dump via ConfigDumpExtension SPI\n\nThe BanyanDB storage config moved to a separate bydb.yml / bydb-topn.yml in\n10.2.0, so a BanyanDB deployment showed an empty storage.banyandb block in the\n/debugging/config/dump admin API while ES/JDBC showed theirs.\n\nAdd a generic ConfigDumpExtension SPI on ServerStatusService that any module\nloading configuration from a secondary file can implement. BanyanDB registers\nan extension that flattens its already-loaded, environment-resolved config into\nstorage.banyandb.* (TopN rules under storage.banyandb.topN.*), merged into the\nsame dump and masked centrally by the existing secret-keyword list. The status\nmodule stays storage-agnostic (dependency arrow plugin -\u003e core); the Horizon UI\nneeds no change since it groups by the first dotted segment.\n\nAdds UTs for the core merge+mask and the flattener, plus a representative\nconfig-dump assertion on the banyandb storage e2e case."
    },
    {
      "commit": "62423e4dfa63c0dffad021a57c803bfb1c7c6e4f",
      "tree": "7be9503837db198e662496a72624ad587aaa932f",
      "parents": [
        "462423a0ca7e28c9e6204ec4ceba06753d77b615"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 30 11:18:56 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 11:18:56 2026 +0800"
      },
      "message": "Decode Istio metadata-exchange peer in Envoy ALS rendering; harden proto-to-JSON (#13931)\n\n**Why the bug exists.** Envoy `HTTPAccessLogEntry`/`TCPAccessLogEntry` carry the Istio metadata-exchange peer in `common_properties.filter_state_objects`, which is `map\u003cstring, google.protobuf.Any\u003e`. The LAL live-debugger serialized the input via a `JsonFormat` printer built **without** a `TypeRegistry` (`LalPayloadDebugDump`), so it threw `Cannot find type for url: …` and the INPUT sample showed an error envelope instead of the entry. Separately, the LAL output builder\u0027s `bindInput` (which the generated `execute()` calls eagerly, **before** the debug capture) serialized via the bare `ProtoBufJsonUtils.toJSON`; an unregistered injected `Any` there threw and **aborted the whole rule**, dropping the mesh log.\n\n**How it\u0027s fixed.**\n- `LalPayloadDebugDump` now uses a well-known-type `TypeRegistry` plus a sanitizer, so a single un-printable field can no longer blank the whole entry: an unresolvable / no-slash / corrupt-bytes `Any` degrades to an `@unresolved` placeholder, and a non-finite `Value` double (`NaN`/`Infinity`, which `JsonFormat` rejects) is rendered as a string.\n- The predictable Istio peer is decoded into readable metadata (pod / namespace / labels) — legacy Wasm `wasm.*_peer` (`Any{BytesValue}` → FlatBuffer, reusing the existing `ServiceMetaInfoAdapter`) and modern `*_peer` (`Any{Struct}`) — for both the live-debug INPUT sample and the persisted log `content`, covering HTTP **and** TCP access logs.\n- Decoding is wired through a new `LalInputDebugRenderer` SPI (`EnvoyAlsHttpDebugRenderer` / `EnvoyAlsTcpDebugRenderer`), so `log-analyzer` reaches the receiver-side decoders without depending on the Envoy receiver — mirroring the existing `LALSourceTypeProvider` seam."
    },
    {
      "commit": "462423a0ca7e28c9e6204ec4ceba06753d77b615",
      "tree": "d2f720d98f8eb30cbeed64d0a39e577554eddfc7",
      "parents": [
        "bb16533009a597dbb41ab6f013ac300509abbb3e"
      ],
      "author": {
        "name": "songzhendong",
        "email": "xiaodong12315@qq.com",
        "time": "Tue Jun 30 10:01:37 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 10:01:37 2026 +0800"
      },
      "message": "Add Node.js runtime meter support and e2e validation (#13930)\n\nAdd nodejs-runtime MAL rules, documentation, e2e assertions, and pin\nSW_AGENT_NODEJS_COMMIT to apache/skywalking-nodejs master @ 36df516\n(merged apache/skywalking-nodejs#139)."
    },
    {
      "commit": "bb16533009a597dbb41ab6f013ac300509abbb3e",
      "tree": "c8c08f4f9905713179614e6bad856fea07e13a64",
      "parents": [
        "4226f14e908462d92139ae0974164b5fb0ab52d0"
      ],
      "author": {
        "name": "songzhendong",
        "email": "xiaodong12315@qq.com",
        "time": "Thu Jun 25 10:34:00 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 25 10:34:00 2026 +0800"
      },
      "message": "Add PHP runtime PHM meter analyzer, e2e, and documentation. (#13928)\n\nIntroduce php-runtime.yaml MAL rules for six instance_php_* meters, MAL tests,\nPHP e2e meter assertions, and backend docs. Pin SW_AGENT_PHP_COMMIT to\napache/skywalking-php@de311c9 (PHM #145). Use metrics_report_period\u003d31 in e2e\nphp.ini so meter gRPC streams idle-close and OAP persists PHM data."
    },
    {
      "commit": "4226f14e908462d92139ae0974164b5fb0ab52d0",
      "tree": "dfc7b6cd7e3339e424230e2d250120b9bd57ee34",
      "parents": [
        "fe55b90bcf12b7962017ea64086121b8a07c7368"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Jun 24 23:36:38 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 23:36:38 2026 +0800"
      },
      "message": "Add POST /inspect/values admin API to read foreign metric values (#13927)\n\nA new admin-only POST /inspect/values reads the VALUES of a metric this OAP does not\ndefine locally (persisted by another OAP), by running the real MQE engine over\ncaller-supplied {valueColumn, valueType} — the value-reading companion to the merged\nGET /inspect/entities foreign path (#13926).\n\nA request-scoped InspectQueryContext ThreadLocal makes the foreign metric look\nregistered to every read path (provide-if-absent — the local catalog always wins):\nValueColumnMetadata resolves its value column / type / scope, and the storage location\nregistries resolve where it lives — MetadataRegistry synthesizes a BanyanDB measure\nschema, IndexController resolves the ES metrics-all index, TableHelper probes the JDBC\nfunction tables. The storage read paths need no per-DAO special-casing; the response is\nthe native MQE ExpressionResult. Verified end-to-end across banyandb/es/postgresql."
    },
    {
      "commit": "fe55b90bcf12b7962017ea64086121b8a07c7368",
      "tree": "d35a0e965e2f821333e28dd4068b44bb8f7fdc63",
      "parents": [
        "f409ed7be71f4c3477ce07681373029facbf3036"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Jun 24 09:19:23 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 09:19:23 2026 +0800"
      },
      "message": "Extend `GET /inspect/entities` to inspect foreign metrics persisted by any OAP (#13926)\n\n### Extend `GET /inspect/entities` to inspect a metric persisted by any OAP (foreign metric)\n\n`/inspect/entities` previously enumerated entities only for metrics **defined on the queried OAP**. This extends it so a metric persisted by *any* OAP — one this node never loaded the OAL/MAL/runtime-rule for — can be inspected when the caller supplies the metric\u0027s `valueColumn` + `valueType`.\n\n- The storage backend resolves the physical index/table/group from its **own running config** — no DB schema / table-metadata read:\n  - **Elasticsearch** — merged `metrics-all` index + `metric_table` discriminator.\n  - **JDBC** — probes the node\u0027s function tables by the `table_name` discriminator.\n  - **BanyanDB** — synthesizes a read-only measure schema.\n- `entity_id` is decoded **structurally** (service / 2nd-level / relations) with a generic `name` leaf; scope is no longer required for the foreign path.\n- Locally-defined metrics keep the **exact** field names, scope, and `mqeEntity` (behavior unchanged).\n- Reads are optimistic — errors surface to the caller; a metric unknown locally without `valueColumn`/`valueType` returns a clear `400` steering the caller to the foreign path.\n\n`swctl admin inspect entities` gains `--value-column` / `--value-type` (apache/skywalking-cli#230); `SW_CTL_COMMIT` is bumped to the cli commit that ships them, and a 2-OAP inspect e2e (aware + foreign) is wired across BanyanDB / ES / PostgreSQL."
    },
    {
      "commit": "f409ed7be71f4c3477ce07681373029facbf3036",
      "tree": "d8ac8f587469a336854e68c559ca00c750d321ad",
      "parents": [
        "799bb76c044dbfccdff473feb436021aefe07972"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 23 09:37:46 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 09:37:46 2026 +0800"
      },
      "message": "Remove the always-on alarm-to-event conversion (EventHookCallback) (#13925)\n\nA triggered alarm is no longer synthesized into the events pipeline as an\nAlarm/AlarmRecovery event; events now originate only from real event sources\n(agents, SkyWalking CLI, Kubernetes Event Exporter). Alarms remain available\nthrough the alarm store (getAlarm/queryAlarms) and the configured alarm hooks.\n\n- Delete EventHookCallback and its unconditional registration in NotifyHandler.\n- Delete EventHookCallbackTest.\n- Drop the now-dead event-analyzer dependency from server-alarm-plugin.\n- Remove the \u0027Alarm\u0027 Known-Event row from event.md; update the e2e guide recipe.\n- Update the alarm/baseline e2e expected files to assert \u0027events: []\u0027 — the\n  alarm now correlates no synthetic event (swctl \u0027alarm ls\u0027 still projects the\n  events field, so the expectation must assert the empty list).\n- Add a CHANGES entry."
    },
    {
      "commit": "799bb76c044dbfccdff473feb436021aefe07972",
      "tree": "f4aacfa7f487834c8c2cb6111d087450b8fc3722",
      "parents": [
        "e1acb44d1a939bc2155e1583f5d4d41fe9825907"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sat Jun 20 18:24:50 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 18:24:50 2026 +0800"
      },
      "message": "docs: list Java 25 in backend runtime requirement (#13922)"
    },
    {
      "commit": "e1acb44d1a939bc2155e1583f5d4d41fe9825907",
      "tree": "d1b8ea83c84d4edbba712ccc487cb918ae820de8",
      "parents": [
        "dcfb07014ea5b6813aed214ba34e6230678d37a3"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sat Jun 20 09:13:59 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 09:13:59 2026 +0800"
      },
      "message": "Clear 3 security alerts: protobuf e2e fixture CVE-2026-0994 + histogram count narrowing (#13921)\n\n* Clear 3 security alerts: protobuf e2e fixture CVE + histogram count narrowing\n\n- Dependabot CVE-2026-0994: bump the Airflow e2e mock\u0027s pinned protobuf\n  4.25.8 -\u003e 5.29.6 (no 4.x patch exists) and opentelemetry-proto 1.24.0 -\u003e 1.28.0\n  (its protobuf\u003c5.0 cap was the blocker). CI-only test fixture, never shipped;\n  grpcio/flask unchanged.\n- CodeQL java/implicit-cast-in-compound-assignment: widen the cumulative `count`\n  accumulator from int to long in Sum/AvgHistogramPercentileFunction. `count +\u003d\n  value` silently narrowed a long bucket-count sum back to int; `total` was\n  already long."
    },
    {
      "commit": "dcfb07014ea5b6813aed214ba34e6230678d37a3",
      "tree": "e10f404afb1c266512f7a761351defea14849a6a",
      "parents": [
        "6cf80750ed9fa23b42fc73524096030f953701c7"
      ],
      "author": {
        "name": "Marc Navarro",
        "email": "marcnavarro@tetrate.io",
        "time": "Fri Jun 19 08:36:22 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 14:36:22 2026 +0800"
      },
      "message": "Fix custom layers: MAL v2 Layer.NAME compilation + layer-extensions.yml jar shadowing (#13918)\n\n**Bug 1 — MAL v2 compiler cannot compile a custom-layer reference**\n\nA custom layer has no generated `Layer.*` static field — it lives only in the name registry — so referencing it in a MAL expression failed v2 code generation. The natural form `service([\u0027svc\u0027], Layer.IOT_FLEET)` parses as the static-field `enumRef` (`IDENTIFIER DOT IDENTIFIER`, exactly like `Layer.GENERAL`), and codegen emitted it verbatim as a `Layer.IOT_FLEET` field access — a field that does not exist on `Layer` — so Javassist failed to compile the generated source.\n\nFix: `MALMethodChainCodegen` now lowers every `Layer.NAME` static-field reference to a runtime `Layer.nameOf(\"NAME\")` registry lookup, scoped to `Layer` only (via `MALCodegenHelper.LAYER_ENUM_TYPE`). `Layer` is a registry-backed type, not a Java enum, and `Layer.nameOf` resolves both built-in and custom layers by name; for a built-in this is behavior-preserving, because `Layer.nameOf(\"GENERAL\")` returns the same instance as the `Layer.GENERAL` field. The other `ENUM_FQCN` types (`DetectPoint`, `DownsamplingType`, `TimeUnit`, `K8sRetagType`) are real Java enums with no `nameOf(String)` and keep their direct static-field reference. A custom layer is therefore referenced exactly like a built-in one, with no grammar / AST / parser change. `docs/.../mal.md` is updated to the `Layer.NAME` form.\n\nTests (`MALClassGeneratorTest`): a custom-layer field form lowers to `Layer.nameOf(\"...\")` and compiles; a built-in field form lowers identically; a non-`Layer` enum (`DetectPoint`) keeps its direct field access. All 1350 bundled-rule execution tests pass — every built-in `Layer.*` reference now routes through `nameOf` and resolves to the same layer (no rule used a custom layer before, which is why CI never caught it).\n\n\u003e _Note: an earlier revision of this PR fixed only the explicit `Layer.nameOf(\u0027NAME\u0027)` method form via a parser reinterpretation (`EnumStaticCallArgument`). That was superseded by the field-form lowering above — the field form is the natural, documented-as-built-in syntax and needs no grammar/AST special-casing. Neither form had shipped, so there is no compatibility concern._\n\n**Bug 2 — `layer-extensions.yml` bundled in the jar shadows the operator\u0027s `config/` copy**\n\n`layer-extensions.yml` (operator-managed, documented as living in `config/`) was packaged inside `skywalking-oap.jar` and not shipped to the distribution `config/`. The launch script (`dist-material/bin/oapService.sh:38-41`) prepends every `oap-libs/*.jar` to `CLASSPATH`, leaving `config/` last, so `ResourceUtils.read(\"layer-extensions.yml\")` → `getClassLoader().getResource(...)` deterministically resolved the empty jar-bundled template (`layers: []`) and silently ignored the operator\u0027s file — custom layers declared there never registered.\n\nFix: add `layer-extensions.yml` to the `maven-jar-plugin` `\u003cexcludes\u003e` (`oap-server/server-starter/pom.xml`) and to the assembly `\u003cincludes\u003e` (`apm-dist/src/main/assembly/binary.xml`), so it follows the same exclude-from-jar + copy-to-`config/` packaging as every other operator-editable config. Verified by rebuilding `skywalking-oap.jar` and confirming the file is no longer present."
    },
    {
      "commit": "6cf80750ed9fa23b42fc73524096030f953701c7",
      "tree": "d4b5c62aae06c90ad736f4144d4ac3810565e31f",
      "parents": [
        "95a296e2c810e6280b16975dd411e9c595a16836"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Jun 19 13:40:19 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 13:40:19 2026 +0800"
      },
      "message": "Migrate Consul client to kiwiproject fork to clear okhttp CVE-2021-0341 (#13920)\n\n* Migrate Consul client to maintained kiwiproject fork (0.9.0) to clear okhttp CVE\n\nMigrate the Consul cluster and configuration plugins from the abandoned\ncom.orbitz.consul:consul-client 1.5.3 to the maintained fork\norg.kiwiproject:consul-client 0.9.0 to clear CVE-2021-0341 (okhttp 3.14.9).\n\n- Pin to 0.9.0: the newest fork release still built for JDK 11 bytecode\n  (1.0.0+ is Java 17, which SkyWalking still targets via maven.compiler.release\u003d11).\n- BOM: bump okhttp 3.14.9 -\u003e 4.12.0 (clears the CVE, Java-8/11 safe); pin\n  jackson-datatype-jdk8/guava to the managed jackson 2.18.6 so the client\n  cannot drag in an off-version.\n- Source change is a package rename (com.orbitz.consul -\u003e org.kiwiproject.consul);\n  plugins use only stable Consul APIs.\n- ITs stay on consul:0.9. Regenerated LICENSE and added .licenserc.yaml mappings."
    },
    {
      "commit": "95a296e2c810e6280b16975dd411e9c595a16836",
      "tree": "b01cfcc066737cb53b08b99f630e2ce2ddf503ea",
      "parents": [
        "277f19bcce913c7aed66c13178d7b29f252ed729"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Jun 19 11:24:25 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 11:24:25 2026 +0800"
      },
      "message": "Let Spring Boot manage logback (matched) - clears 4 logback-core CVE alerts (#13916)\n\n#13913 pinned logback-classic to 1.2.13 while Spring Boot kept logback-core at\n1.2.6 (mismatch -\u003e NoSuchMethodError -\u003e lua e2e hang). #13915 fixed the hang by\nadding an explicit logback-core 1.2.13 dep, but that made Dependabot flag\nlogback-core (4 CVEs patched only in logback 1.3.x/1.5.x, which need SLF4J 2.0 /\nJava 17 - unreachable on this Java-8 / Spring Boot 2.5 fixture).\n\nDrop the explicit logback pins entirely and let spring-boot-dependencies manage\nboth logback-classic and logback-core to the same version (1.2.6). Matched\nversions never trigger the NoSuchMethodError, and a BOM-managed (not declared)\nlogback-core is not flagged by Dependabot - so the 4 alerts clear without\nshipping a vulnerable declared dependency, and the lua fix is preserved."
    },
    {
      "commit": "277f19bcce913c7aed66c13178d7b29f252ed729",
      "tree": "196c34512b5a227d4a0b37adf4796ef0eb4fcfad",
      "parents": [
        "7d10e221a243cb3417b08748e6266948db4a8975"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Jun 18 17:07:58 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 18 17:07:58 2026 +0800"
      },
      "message": "Clear test-fixture CVE Dependabot alerts: drop log4j 1.x + modernize Go fixtures (#13915)\n\n### Clear test-scope CVE Dependabot alerts (log4j 1.x + Go e2e fixtures)\n\nFollow-up to #13913. Clears ~18 of the remaining open Dependabot alerts, all in e2e **test fixtures** (no production code).\n\n**log4j 1.x** — `e2e-service-provider` (2 alerts; log4j 1.x is EOL, one CVE has no patched release):\n- Removed `log4j:log4j` 1.2.17 + `apm-toolkit-log4j-1.x` and `log4j.properties`. The provider already exercises log-to-OAP through **log4j2** (`apm-toolkit-log4j-2.x`, grpc appender) and **logback** in parallel, so log-reporting coverage is preserved. The log4j2 loggers now use the imported `org.apache.logging.log4j.Logger` (no inline FQCN). Dropped the log4j-1.x `fileLogger` items from the filebeat/fluentd expected files.\n\n**Go fixtures** — `grpc`/`golang.org/x/net`/`x/crypto`/`protobuf` (~16 alerts; the patched releases require Go ≥ 1.23):\n- `cases/go/service`: `go 1.24`; x/crypto 0.46, x/net 0.48, grpc 1.79.3, protobuf 1.36.10; Dockerfile base `-go1.19` → `-go1.24`. `SW_AGENT_GO_COMMIT` → `19a9fa9` (the skywalking-go commit that ships the go1.24 images; go1.19 images were dropped). All 5 shared go cases (go/service, profiling/trace/go, pprof/{mysql,es,banyandb}) build from this one Dockerfile.\n- `cases/profiling/ebpf/network`: **migrated off the legacy go2sky SDK to the skywalking-go toolchain agent** (auto-instruments net/http server+client). The app exit span is now auto-instrumented (`GET:/provider`, `GoHttpClient`, layer `Http`, peer `proxy`, http tags, spanid 1/parent 0) — `expected/skywalking-trace.yml` updated, derived from the skywalking-go net/http plugin. The eBPF sampled-record name (`skywalking-\u003cpath\u003e`) is network-derived and unchanged, so the verify query and the 4xx/5xx expectations are untouched."
    },
    {
      "commit": "7d10e221a243cb3417b08748e6266948db4a8975",
      "tree": "d935675f16d46d8f17fc43fbfa6d751d0336edc0",
      "parents": [
        "fe6f04e0ea0d5b7af0fe2be6cc6cad7486815d81"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Jun 18 11:34:51 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 18 11:34:51 2026 +0800"
      },
      "message": "Clear CVE Dependabot alerts: Curator/ZooKeeper bump, assertj, e2e test fixtures (#13913)\n\nThis clears the actionable, non-Go Dependabot alerts on `master`. (The Go e2e-fixture alerts require a Go 1.24 agent toolchain and are handled separately via skywalking-go image work + an e2e follow-up.)\n\n### Shipped product (oap-server-bom + LICENSE + docs)\n- **Apache Curator `4.3.0` → `5.9.0`** (+ `curator-test`) and **Apache ZooKeeper `3.5.7` → `3.9.5`**, bumped together — Curator 5.x is the line that carries the ZK 3.9.x client. Clears **CVE-2023-44981** (critical). OAP is a ZooKeeper *client* only, so the server-side bug was never reachable, but the bundled jar tripped Dependabot. The cluster-zookeeper and configuration-zookeeper plugins use only stable Curator APIs, so no source changes were required. Operator-facing change: supported ZooKeeper server version is now 3.5+ (3.4.x dropped by Curator 5.x). `dist-material/release-docs/LICENSE` regenerated (curator ×4, zookeeper + jute, audience-annotations); `application.yml` + `backend-cluster.md` updated.\n\n### Build/test scope\n- **assertj-core `3.20.2` → `3.27.7`** — clears CVE-2026-24400 (XXE in `isXmlEqualTo`, unused), test scope.\n\n### e2e test fixtures (`test/e2e-v2`, never shipped)\n- guava → `32.0.0-jre`, kafka-clients → `3.9.2` (+ removed a stale unused `2.4.1` property), log4j-core → `2.25.4`, logback → `1.2.13` (the Java-8 line, not Dependabot\u0027s JDK-11 `1.4.12`), json-path → `2.9.0`, flask → `3.1.3`, protobuf → `4.25.8`."
    },
    {
      "commit": "fe6f04e0ea0d5b7af0fe2be6cc6cad7486815d81",
      "tree": "18a9407cc52a54fd7fd3d51aecff5ca0ea854fbb",
      "parents": [
        "c94b4e00d35dfa543c10fa6bd282903a205f523f"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 16 11:57:36 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 11:57:36 2026 +0800"
      },
      "message": "Fix BanyanDB runtime-rule self-heal + v2 MAL CounterWindow collision \u0026 Elvis falsy semantics (#13911)"
    },
    {
      "commit": "c94b4e00d35dfa543c10fa6bd282903a205f523f",
      "tree": "d2b315001654c411f637aa491abf9f979679b6b7",
      "parents": [
        "53baf8e5da6c45670da6509eb7fcceed7b082ceb"
      ],
      "author": {
        "name": "mrproliu",
        "email": "741550557@qq.com",
        "time": "Mon Jun 15 11:07:46 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 15 11:07:46 2026 +0800"
      },
      "message": "Align default BanyanDB stage segmentInterval to integer multiples (#13910)\n\n### Improve the efficiency of BanyanDB hot → warm → cold lifecycle stage migration (default config)\n\nEach coarser lifecycle stage\u0027s `segmentInterval` should be an integer multiple of the immediately finer (preceding) stage\u0027s. BanyanDB segments are epoch-anchored, so when the coarser interval is a multiple of the finer one, every source segment nests entirely inside exactly one target segment and the tier migration stays on the cheap **whole-segment fast path** (byte-copy). A non-multiple interval makes source segments straddle target boundaries, forcing a row-by-row decode-and-re-bucket **slow path** that costs significantly more CPU, IO, and peak memory, and produces more small parts for the background merge loop to compact. It does not affect correctness — only migration efficiency.\n\nThis aligns the shipped defaults that previously violated the rule:\n\n| Group | Field | Old → New |\n|-------|-------|-----------|\n| records | cold `segmentInterval` | 3 → 4 (multiple of warm\u003d2) |\n| metricsMinute | cold `segmentInterval` | 5 → 6 (multiple of warm\u003d3) |\n| metricsHour | warm `segmentInterval` | 7 → 10 (multiple of hot\u003d5) |\n| metricsHour | cold `segmentInterval` | 15 → 20 (multiple of warm\u003d10) |\n\nAll adjusted values still satisfy `hot ≤ warm ≤ cold` and `segmentInterval ≤ that stage\u0027s ttl`. The other groups already comply and are unchanged."
    },
    {
      "commit": "53baf8e5da6c45670da6509eb7fcceed7b082ceb",
      "tree": "a96fb70818f8088c2136f9fd3ce67f428007ffe3",
      "parents": [
        "b4bc7ea8dbfbea9b5acb501f07f88b47861f7c47"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sun Jun 14 08:04:36 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 14 08:04:36 2026 +0800"
      },
      "message": "Fix runtime-rule (MAL/LAL) hot-update in no-init mode + k8s cluster node identity (#13909)\n\nTwo bugs in the runtime-rule (DSL hot-update) cluster path, both confirmed end-to-end on a local kind cluster:\n\n**1. Runtime-rule schema changes were inoperative in `no-init` mode** — the mode every production OAP cluster runs (a one-shot `-Dmode\u003dinit` Job creates the static schema; the OAP Deployment runs `-Dmode\u003dno-init`). A runtime `addOrUpdate` introducing a new metric blocked forever in the storage installer\u0027s init-node poll loop (`ModelInstaller.whenCreating`), because the loop was gated on `RunningMode` rather than the operation\u0027s intent. `/delete?mode\u003drevertToBundled` recreate and BanyanDB in-place shape updates were dead the same way. **Fix:** a new `StorageManipulationOpt.Flags.deferDDLToInitNode` bit, set only on the static boot-time `schemaCreateIfAbsent()` opt (DRYed into `ModelInstaller.deferDDLToInitNode(opt)`, reused by the BanyanDB shape-check / group-DDL gates). The runtime-rule opts (`withSchemaChange` / `verifySchemaOnly` / `withoutSchemaChange`) are now driven by their flags and by cluster main-ness — `no-init` and `default` no longer differ for DSL DDL; `init` stays the dedicated initializer. `DSLManager.tickStorageOpt` is collapsed accordingly.\n\n**2. Runtime-rule cross-node writes failed with `HTTP 400 forward_self_loop` on a multi-replica Kubernetes cluster.** Every OAP replica shared the cluster `selfNodeId` `0.0.0.0_11800` (derived from the `0.0.0.0` agent gRPC bind host via `TelemetryRelatedContext`), so the main\u0027s self-loop guard rejected a legitimate peer-to-peer Forward as if it had looped back. **Fix:** resolve the runtime-rule node identity from the unique per-pod `SKYWALKING_COLLECTOR_UID` (the pod UID injected by the helm chart / swck operator from `metadata.uid`), in `start()` before any apply; falls back to the telemetry id off-Kubernetes. `MainRouter` already routes correctly off the cluster peer addresses (pod IPs); only the self-loop identity needed to be unique.\n\n**Tests:** new `ModelInstallerNoInitTest` (UT) for the no-init create chokepoint; the runtime-rule cluster e2e is converted from docker-compose (default mode — which never exercised either bug) to a kind + skywalking-helm `no-init` cluster (`oap.replicas\u003d2`) driving the apply / STRUCTURAL / inactivate / delete lifecycle, cross-node convergence, and the cross-node Forward path."
    },
    {
      "commit": "b4bc7ea8dbfbea9b5acb501f07f88b47861f7c47",
      "tree": "f264eea5427bba9dfa8327aa6bc8674180ab13cc",
      "parents": [
        "53cc332752d5b5aa84a0eddf66ccd2a5c1b7d316"
      ],
      "author": {
        "name": "mrproliu",
        "email": "741550557@qq.com",
        "time": "Sat Jun 13 12:41:10 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 12:41:10 2026 +0800"
      },
      "message": "Fix wrong banyanDB resource options in record data (#13907)\n\n#### What\u0027s the problem\n\nIn `MetadataRegistry.parseMetadata`, the `RECORDS` stream-group branch builds its\n`SchemaMetadata` from `config.getRecordsBrowserErrorLog()` instead of\n`config.getRecordsNormal()`:\n\n```java\ncase RECORDS:\n    return new SchemaMetadata(\n        namespace,\n        BanyanDB.StreamGroup.RECORDS.getName(),   // group \u003d sw_records\n        model.getName(),\n        Kind.STREAM,\n        model.getDownsampling(),\n        config.getRecordsBrowserErrorLog()         // \u003c-- wrong: should be recordsNormal\n    );\n```\n\nAs a result the `sw_records` group is created/reconciled with the\n`recordsBrowserErrorLog` settings (its `shardNum`, `segmentInterval`, `ttl`,\nper-stage `warm`/`cold` config) rather than its own `records` settings. The\n`RECORDS_LOG` and `RECORDS_BROWSER_ERROR_LOG` branches are already correct; only\n`RECORDS` is affected.\n\n#### Why it matters\n\n`BanyanDBIndexInstaller` reconciles a group on startup (init mode) by comparing\nevery field — including per-stage `shardNum` / `segmentInterval` / `ttl` — and\nissues `client.update` on drift. Because `sw_records` was being fed the wrong\nconfig object, its group settings silently tracked\n`SW_STORAGE_BANYANDB_BROWSER_ERROR_LOG_*` instead of\n`SW_STORAGE_BANYANDB_RECORDS_*`. In deployments where the two differ (e.g. a\ndifferent `shardNum`), this can drive `sw_records` to the wrong shard count or\nsegment-interval grid.\n\n#### The fix\n\nPoint the `RECORDS` branch at the correct config getter:\n\n```java\nconfig.getRecordsNormal()\n```\n\nOne-line change. `getRecordsNormal()` is the existing Lombok getter for the\n`recordsNormal` field, populated from the `records` section of `bydb.yml`\n(`SW_STORAGE_BANYANDB_RECORDS_*`).\n\n#### Impact\n\n- `sw_records` now honors its own `records` configuration.\n- The `RECORDS_LOG` / `RECORDS_BROWSER_ERROR_LOG` groups are untouched.\n- Segment-interval changes only affect newly created segments; existing segments\n  keep their grid and no data is rewritten or lost."
    },
    {
      "commit": "53cc332752d5b5aa84a0eddf66ccd2a5c1b7d316",
      "tree": "d7944f27463221919161ba30bc7280592363a2e7",
      "parents": [
        "4185f50e74254bfc82efd45290eef5c1946ca499"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Jun 12 21:40:18 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 12 21:40:18 2026 +0800"
      },
      "message": "Fix BanyanDB property_index_merge_latency unit: nanoseconds, not seconds (#13906)\n\nproperty_index_merge_latency converted its source with *1000 (seconds-\u003ems), but\nbanyandb_property_inverted_index_total_merge_latency is bluge\u0027s inverted-index\nZapTime -- a raw time.Duration in NANOSECONDS (pkg/index/inverted/metrics.go\nsets float64(TotFileMergeZapTime); bluge index/merge.go computes\nuint64(time.Since(...))), never .Seconds(). So the metric over-reported by 1e6.\nConvert ns-\u003ems with /1000000."
    },
    {
      "commit": "4185f50e74254bfc82efd45290eef5c1946ca499",
      "tree": "0554b4048df87ae8015d4bbcefa250066b20442b",
      "parents": [
        "75d9433d7bcb80494dde084af559f955f5897116"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Jun 12 20:19:26 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 12 20:19:26 2026 +0800"
      },
      "message": "SWIP-15: BanyanDB instance-relation deployment topology + category-separated self-observability rules (#13905)\n\n#### What this includes\n\n**1. `SERVICE_INSTANCE_RELATION` MAL scope + deployment topology**\n- New `SERVICE_INSTANCE_RELATION` scope + `serviceInstanceRelation(...)` builder; the meter `Analyzer` bridges to the `ServiceInstanceRelation` server/client-side topology metrics, so `getServiceInstanceTopology` renders the edges.\n- New `banyandb-instance-relation.yaml`: the pod-to-pod flow graph (the Horizon UI \"deployment\" component) with per-edge, per-operation `publish_*` / `queue_sub_*` / `migration_*` metrics (throughput / p99 / error / bytes).\n\n**2. Category-separated BanyanDB self-observability rules**\n- `banyandb-instance.yaml` → role-separated (`node_*` shared, `liaison_*`, `data_*`, `lifecycle_*`).\n- `banyandb-endpoint.yaml` → data-type-separated (`measure_*` / `stream_*` / `stream_tst_*` / `trace_*` / `property_*`; operation-keyed `queue_*` stay type-agnostic). Adds the previously-unmodeled **property** type (so `sw_property` groups stop rendering all-empty) and the trace storage inverted-index series.\n\n**3. Fix: percent metrics rendered as 100%**\n- `system_memory_percent` / `disk_usage_percent` / `disk_used_percent_by_path` emitted a 0–1 fraction (collapsed to 0/1 in the integer meter store → rendered 100%). Now use BanyanDB\u0027s `used_percent` × 100. Verified live on a kind cluster: a ~51% disk now reads 51%.\n\n**4. Docs**\n- SWIP-15 synced to the implemented metrics (then treated as the stable design doc); operator catalog `docs/en/banyandb/dashboards-banyandb.md` refreshed; the SWIP-15 changelog consolidated into one concise entry.\n- `guides/How-to-release.md`: new \"Publish the GitHub release\" section documenting the changelog-wrapping rule (GitHub renders a bullet\u0027s prose continuation lines as `\u003cbr\u003e`, so keep prose on one line; sub-bullets are fine — verified on v10.4.0). Related conventions added to `CLAUDE.md`."
    },
    {
      "commit": "75d9433d7bcb80494dde084af559f955f5897116",
      "tree": "74aba4089201f6a8d4f9952328a68fa98be17d13",
      "parents": [
        "c9f816a4de32c53e87d4ac27ec2f54c6c1cbe8a4"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Jun 11 21:18:37 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 11 21:18:37 2026 +0800"
      },
      "message": "SWIP-15: add BanyanDB queue batch/message metrics (apache/skywalking-banyandb#1169) (#13904)"
    },
    {
      "commit": "c9f816a4de32c53e87d4ac27ec2f54c6c1cbe8a4",
      "tree": "760d2f1a9a058c2ccfdfce1f4dcfd02d82bd886d",
      "parents": [
        "a144e537ce764f96039b53e0d99019289dfc731c"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Jun 11 12:13:22 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 11 12:13:22 2026 +0800"
      },
      "message": "SWIP-15: implement BanyanDB self-observability (cluster / container / group model) (#13903)\n\n### Implement SWIP-15 BanyanDB self-observability around the cluster / container / group model\n\nRebuilds the `otel-rules/banyandb/` self-observability feature to match how BanyanDB is actually built and operated (**requires BanyanDB 0.11+**):\n\n- **Entity model**: `Service` \u003d one BanyanDB **cluster** (`service([\u0027cluster\u0027])`); `ServiceInstance` \u003d one **container** keyed on `pod_name` + `container_name` (with `node_role` / `node_type` / `container_name` / `pod_name` as instance attributes); `Endpoint` \u003d one storage **group**.\n- **Rules**: new `banyandb-endpoint.yaml`; `banyandb-service.yaml` (7 rules) and `banyandb-instance.yaml` (43 rules) redesigned. Source expressions mirror the upstream BanyanDB FODC-proxy Grafana boards (`grafana-fodc-nodes.json` / `grafana-fodc-workload.json`) so the SkyWalking dashboards stay in lockstep. The stale single-node `host_name` model and the removed `etcd_operation_rate` / `up`-derived `active_instance` / `queue_sub_total_msg_sent_err` metrics are dropped.\n- **Docs**: `docs/en/banyandb/dashboards-banyandb.md` rewritten to the cluster/container/group model.\n- **E2E**: rewritten to a no-FODC, file-discovery BanyanDB 0.11 cluster (1 liaison + 1 hot data node, no etcd). The OTel collector scrapes each node\u0027s `:2121` directly and injects the FODC-equivalent identity labels as static per-scrape-job labels, so the full rule set is exercised without a FODC proxy."
    },
    {
      "commit": "a144e537ce764f96039b53e0d99019289dfc731c",
      "tree": "1a534f053a34f3346561a166d97ae4ff7ad2cafb",
      "parents": [
        "d30d022354e297079e40389235a0527d13c99cb8"
      ],
      "author": {
        "name": "songzhendong",
        "email": "xiaodong12315@qq.com",
        "time": "Thu Jun 11 07:56:21 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 11 07:56:21 2026 +0800"
      },
      "message": "Add Apache Airflow monitoring layer (SWIP-7) (#13891)"
    },
    {
      "commit": "d30d022354e297079e40389235a0527d13c99cb8",
      "tree": "0741780140e86269fb119a44d7f1f02a5d5efe0f",
      "parents": [
        "3e5cb0ca7fb6ea4cf1d9dcaceaa9d9c473e4f67b"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Jun 10 20:55:55 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 10 20:55:55 2026 +0800"
      },
      "message": "SWIP-15: container-level instances and post-review corrections (#13901)"
    },
    {
      "commit": "3e5cb0ca7fb6ea4cf1d9dcaceaa9d9c473e4f67b",
      "tree": "ffaa2592388708e640009d3745414384093c44fb",
      "parents": [
        "1b670267a1329e934a015047908ccc90b61efde6"
      ],
      "author": {
        "name": "mrproliu",
        "email": "741550557@qq.com",
        "time": "Tue Jun 09 13:12:32 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 13:12:32 2026 +0800"
      },
      "message": "Fix continuous profiling policy validation: reject zero threshold/count (#13898)\n\n* Fix continuous profiling policy validation to reject zero threshold/count\n\nThe validation conditions used `\u003c 0` while the error messages said\n\"must bigger than zero\". rover triggers profiling when `value \u003e\u003d threshold`\n(and `matchedCount \u003e\u003d count`), so a threshold/count of 0 always fires and is\nmeaningless. Tighten the conditions to `\u003c\u003d 0`, align CPU percent / HTTP error\nrate to (0-100], and fix the message grammar."
    },
    {
      "commit": "1b670267a1329e934a015047908ccc90b61efde6",
      "tree": "6e57bac96d621d7a79ba58556fc7979590d3914f",
      "parents": [
        "b1dc4238a32fb1defcf4a1b6aa1081c0052b2bae"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 09 10:21:27 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 10:21:27 2026 +0800"
      },
      "message": "Fix docker-compose quickstart for Horizon UI and OAP healthcheck (#13899)\n\nAddresses apache/skywalking discussion #13896:\n\n- OAP healthcheck used `curl http://localhost:12800/internal/l7check`, but\n  the eclipse-temurin JRE image ships no curl/wget/nc. Probe the query port\n  with bash\u0027s built-in /dev/tcp instead, and widen start_period to 90s so\n  BanyanDB schema install doesn\u0027t burn the retry budget.\n- Horizon UI listens on 8081 inside the container, not 8080; fix the port\n  mapping (8080:8081).\n- The Horizon image takes its OAP URLs and login users ONLY from a mounted\n  config file, not env vars. Drop the non-existent SW_OAP_ADDRESS /\n  SW_ADMIN_ADDRESS / SW_ZIPKIN_ADDRESS vars and mount docker/horizon.yaml.\n- New docker/horizon.yaml: server.host 0.0.0.0 (the example config ships\n  127.0.0.1, which binds container-loopback only and 503s from the host),\n  oap query/admin/zipkin URLs pointed at the compose `oap` service, and a\n  demo admin/admin local login."
    },
    {
      "commit": "b1dc4238a32fb1defcf4a1b6aa1081c0052b2bae",
      "tree": "4c9701b44998eae0c4d99d4ce61cc4d68cc1861a",
      "parents": [
        "2aa0e8502a928c7066a01f864ee32122f12dfcae"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon Jun 08 21:58:31 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 08 21:58:31 2026 +0800"
      },
      "message": "SWIP-15: Redesign BanyanDB self-observability (cluster / node / group model) (#13897)"
    },
    {
      "commit": "2aa0e8502a928c7066a01f864ee32122f12dfcae",
      "tree": "d5cdcd9bd3a0cba550b88ca799410732f3644434",
      "parents": [
        "bf0fe4bac6ba212c9a6e67e6d60ca297337b454f"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon Jun 08 09:47:11 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 08 09:47:11 2026 +0800"
      },
      "message": "Bump shipped OAP dependencies to clear CVE Dependabot alerts (#13893)\n\nBump in oap-server-bom:\n- log4j         2.25.3 -\u003e 2.25.4\n- jackson       2.18.5 -\u003e 2.18.6\n- kafka-clients 3.4.0  -\u003e 3.9.2\n- postgresql    42.4.4 -\u003e 42.7.11\n- commons-compress 1.21 -\u003e 1.26.2\n\nRegenerate dist-material/release-docs/LICENSE accordingly, including the\nkafka-clients transitives: zstd-jni 1.5.6-4, snappy-java 1.1.10.5, and the\nlz4-java groupId change org.lz4 -\u003e at.yawk.lz4 1.10.1. Add a .licenserc.yaml\noverride so postgresql keeps its BSD-2-Clause classification (42.7.11 no longer\ntext-matches the SPDX template, so license-eye otherwise falls back to the raw\nlicense URL).\n\nThe kafka-clients 3.9.2 bump also carries KAFKA-17078, fixing the SASL auth\ncrash on JDK 24+ (Closes #13849). Corrects the closed PR #13859, which failed\nthe dependency-license check by not regenerating the LICENSE file."
    },
    {
      "commit": "bf0fe4bac6ba212c9a6e67e6d60ca297337b454f",
      "tree": "85b47508ab91fbdf57fb18940811f49cc60c8670",
      "parents": [
        "89624809f078b6424b474323ae091f72b9e694b4"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Thu Jun 04 16:35:15 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 04 16:35:15 2026 +0800"
      },
      "message": "fix: do not read runtime-rule storage if the feature is disabled. (#13890)"
    },
    {
      "commit": "89624809f078b6424b474323ae091f72b9e694b4",
      "tree": "30700c0246e90b79970167b136f4813c1d333ffa",
      "parents": [
        "768d0693aac34ed49ce4d1c89e4a56df353e4140"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Jun 04 09:18:58 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 04 09:18:58 2026 +0800"
      },
      "message": "Migrate e2e admin-API curl calls to swctl admin commands (#13889)\n\n* Migrate e2e admin-API curl calls to swctl admin commands\n\nReplace raw curl interactions with the OAP admin-server REST host (port 17128)\nacross the e2e suite with the new \u0027swctl admin ...\u0027 command tree\n(skywalking-cli #228, commit b447211):\n\n- runtime-rule flows (mal/lal/cluster) -\u003e swctl admin runtime-rule ...\n- dsl-debug flows (oal/mal/lal-block/lal-statement) -\u003e swctl admin dsl-debug ...\n- ui-management -\u003e swctl admin ui-template ...\n- storage inspect/config(dump,ttl) -\u003e swctl admin inspect|config ...\n\n--display json/yaml keeps response bodies parseable by the existing jq/yq\nassertions; runtime-rule negative paths assert the CLI\u0027s typed error envelope\n(HTTP \u003ccode\u003e (\u003capplyStatus\u003e)). config-dump.yml is regenerated as the JSON\nstring-map that \u0027admin config dump\u0027 returns. Bumps SW_CTL_COMMIT to the\nadmin-capable commit. Non-admin curls (BanyanDB probe, self-telemetry, alarm\nwebhook) are intentionally kept.\n\n* e2e: fix swctl admin review feedback (yaml.v2 key casing + missing swctl install)\n\n- inspect cases: the CLI marshals typed structs through yaml.v2 (json tags\n  ignored -\u003e lowercased keys scopeid/entityid/mqeentity), which would not match\n  the existing fixtures (scopeId/entityId/mqeEntity). Use \u0027--display json | yq -P\u0027\n  so the json tags are honored and the fixtures stay unchanged.\n- runtime-rule/cluster and ui-management/banyandb setups now install swctl: both\n  cases newly depend on it (the flows/cases no longer use curl), but their setup\n  only installed jq / yq, so a clean e2e shell would hit \u0027swctl: command not found\u0027."
    },
    {
      "commit": "768d0693aac34ed49ce4d1c89e4a56df353e4140",
      "tree": "e7404a89ce181382e58ccd87cd8476061a63ad58",
      "parents": [
        "b92e0e6d0302ac5d8f08b8e1360112147c0f574e"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 02 23:00:54 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 02 23:00:54 2026 +0800"
      },
      "message": "Correct Horizon UI setup docs: Docker Hub image, port 8081, horizon.yaml config (#13888)\n\nThe UI setup docs pointed operators at the GHCR dev registry, used port\n8080, and documented SW_OAP_ADDRESS / SW_ADMIN_ADDRESS / SW_ZIPKIN_ADDRESS\nenvironment variables that Horizon UI does not read (it is configured via a\nmounted horizon.yaml). Correct them:\n\n- Released images come from Docker Hub apache/skywalking-ui (latest /\n  horizon-\u003cversion\u003e); ghcr.io/apache/skywalking-horizon-ui is per-commit/dev\n  only.\n- Default port is 8081 (Horizon BFF), not 8080.\n- Configuration is via horizon.yaml (oap.queryUrl/adminUrl/zipkinUrl), not\n  environment variables.\n- Do not lock a Horizon UI version: OAP 11.0+ is supported and compatibility\n  is Horizon UI\u0027s responsibility.\n- Keep the OAP-side docs to basics and link to the Horizon UI website docs;\n  drop source-code links.\n\nAlso align the Helm ui.image examples, the changelog upgrade path, and the\nrelease guide for consistency. Verified against the Horizon UI source and the\nskywalking-helm chart (ui-svc.yaml: service port 80 -\u003e targetPort 8081)."
    },
    {
      "commit": "b92e0e6d0302ac5d8f08b8e1360112147c0f574e",
      "tree": "07171d2d3a453f3b38a8b3da0c0d889dc1aa8208",
      "parents": [
        "e88675d3e91368a225615149cd7a19c618340841"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Jun 02 10:46:49 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 02 10:46:49 2026 +0800"
      },
      "message": "Add 3D Infrastructure Map demo to README (#13887)"
    },
    {
      "commit": "e88675d3e91368a225615149cd7a19c618340841",
      "tree": "3bf88ba256731fd113a99e59809787a6ec7873fc",
      "parents": [
        "ad733554b0273d6165eff7bae4150df83d49ebe8"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Fri May 29 11:36:07 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri May 29 11:36:07 2026 +0800"
      },
      "message": "add back status query example (#13886)"
    },
    {
      "commit": "ad733554b0273d6165eff7bae4150df83d49ebe8",
      "tree": "051b9494b8631ea26cbe51b72c60f3bea2b01335",
      "parents": [
        "40d95a179b0af6fab342316bce905f28918dd4ee"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Tue May 26 12:22:51 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue May 26 12:22:51 2026 +0800"
      },
      "message": "Mask more keywords by default and remove auto generate id for UI templates (#13884)"
    },
    {
      "commit": "40d95a179b0af6fab342316bce905f28918dd4ee",
      "tree": "e82bd5f06a56519ccc032b02231e36466973dbf1",
      "parents": [
        "658832efe5ce8e93414a1afbf575be308006d449"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sun May 24 23:55:57 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun May 24 23:55:57 2026 +0800"
      },
      "message": "Runtime MAL/LAL rules can declare dynamic layers (#13883)\n\n* Runtime MAL/LAL rules can declare dynamic layers\n\nRuntime hot-update rules pushed through the runtime-rule admin API may\nnow declare a layerDefinitions: block. Layers register through a new\nLayer.registerDynamic channel (post-seal-allowed) and are refcount-\ntracked by RuntimeLayerRegistry: removing the last declaring rule\nunregisters the layer. Ordinals are operator-pinned in the 100_000+\ntier (no auto-allocation; the ordinal is persisted in ServiceTraffic\nprimary keys and must be operator-stable across restarts).\n\nBundled and runtime are strictly separate ownership channels:\n* Runtime overrides of bundled rules cannot carry layerDefinitions —\n  REST rejects with applyStatus\u003dlayer_override_forbidden.\n* Legacy override rows on disk-twins drop the static-loader\n  substitution and apply post-seal via the dynamic channel so they\n  remain operator-removable.\n* RuleSetMerger no longer injects resolver-only ACTIVE rows into the\n  static loader; pure-runtime rules go through RuleSync.runOnce.\n\nConflict validation surfaces structured 400s with new applyStatus\ncodes: layer_ordinal_out_of_range, layer_name_conflict,\nlayer_ordinal_collision, layer_name_invalid, layer_override_forbidden.\nThe checker covers in-batch duplicates, self-update multi-claimant\nordinal reuse, and bundled-vs-runtime conflicts.\n\nE2E (test/e2e-v2/cases/runtime-rule/mal-storage/runtime-rule-flow.sh)\nextended with Phase 5e-5h: three layer-rejection assertions plus a\nrestart-survival round-trip that POST -\u003e swctl layer ls -\u003e docker\nrestart -\u003e swctl layer ls still shows -\u003e /delete -\u003e swctl layer ls\nno longer shows.\n\nSee docs/en/concepts-and-designs/runtime-rule-hot-update.md#dynamic-layers\nfor the full contract.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) \u003cnoreply@anthropic.com\u003e\n\n* Replace bare assert with assertTrue in LayerDynamicRegisterTest\n\nAddress Copilot review on PR #13883. Project\u0027s surefire enableAssertions\ndefaults to true so bare `assert` does fire, but JUnit assertions are\nthe convention used by every other check in these tests and survive any\ntest-runner configuration."
    },
    {
      "commit": "658832efe5ce8e93414a1afbf575be308006d449",
      "tree": "7fea09cadf8c554ee245bae3ca3253e9e5d539c0",
      "parents": [
        "1ad850f0245cb0303748af035886e62446d7da7d"
      ],
      "author": {
        "name": "somil jain",
        "email": "89907422+somiljain2006@users.noreply.github.com",
        "time": "Sat May 23 13:00:12 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat May 23 15:30:12 2026 +0800"
      },
      "message": "Improve downsampling documentation (#13880)"
    },
    {
      "commit": "1ad850f0245cb0303748af035886e62446d7da7d",
      "tree": "643d5312b181244b3f0ea87d777f150a8e548f1a",
      "parents": [
        "5e9db8fba4c6b11620137afcbf9ccbd788c1214d"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Fri May 22 10:38:10 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri May 22 10:38:10 2026 +0800"
      },
      "message": "Banyandb support update tag family (#13879)"
    },
    {
      "commit": "5e9db8fba4c6b11620137afcbf9ccbd788c1214d",
      "tree": "71a8198eaea2005d190905b1599944e28cbd577a",
      "parents": [
        "5b481a41a99861249410118e4cfbf591c4508dae"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Thu May 21 14:23:51 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu May 21 14:23:51 2026 +0800"
      },
      "message": "Add `@Stream(allowBootReshape \u003d true)` opt-in for additive boot-time reshape of BanyanDB streams / measures. (#13878)"
    },
    {
      "commit": "5b481a41a99861249410118e4cfbf591c4508dae",
      "tree": "82cb3aa4a88fe5b2c8040d37e5310024fc585c91",
      "parents": [
        "137935d364be83d4b4438730540856cc35a2d5c8"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue May 19 18:49:55 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue May 19 18:49:55 2026 +0800"
      },
      "message": "11.0.0: drop bundled UI, retire status public REST, add ui-management + queryAlarms (#13877)\n\n* Remove the bundled legacy UI from the SkyWalking OAP distribution.\n  * Drop the `apm-webapp` module, `skywalking-ui` submodule, UI Docker image build, `docker.ui` Maven target, webapp distribution packaging, and related startup scripts.\n  * Remove boot-time dashboard/menu seeding and the legacy UI menu management storage/service model.\n  * The official UI is now maintained separately as `apache/skywalking-horizon-ui`.\n\n* Move dashboard template management from GraphQL to the admin server.\n  * Remove `UIConfigurationManagement` GraphQL APIs and `SW_ENABLE_UPDATE_UI_TEMPLATE`.\n  * Add the `ui-management` admin feature module with REST APIs for dashboard template list/get/create/update/disable operations.\n\n* Restrict status and debugging REST APIs to the admin server.\n  * `/status/*` and `/debugging/*` are now registered only on the admin server, default port `17128`.\n  * Public REST binding is removed while keeping URI and payload formats unchanged.\n\n* Add the new `queryAlarms(condition: AlarmQueryCondition!): Alarms` GraphQL API.\n  * Supports filtering alarms by entities, layers, rule names, keyword, tags, duration, and paging.\n  * Keeps the existing `getAlarm` API as deprecated compatibility surface.\n  * Add `layer` to `AlarmRecord` and index `id0`/`id1` to support entity-based alarm filtering.\n  * Add `IAlarmQueryDAO.queryAlarms(...)` and implement it for BanyanDB, Elasticsearch, and JDBC.\n\n* Enable all admin feature modules by default.\n  * `admin-server`, `status`, `inspect`, `ui-management`, `dsl-debugging`, and `receiver-runtime-rule` are enabled by default.\n  * Operators can disable individual modules by setting the matching `SW_*` environment variable to empty.\n\n* Update tests, E2E cases, release materials, and documentation for the new no-bundled-UI architecture.\n  * E2E cases now access OAP directly instead of the removed UI proxy.\n  * Status/debugging tests are updated to use the admin server port.\n  * New alarm E2E cases cover `queryAlarms` filters."
    },
    {
      "commit": "137935d364be83d4b4438730540856cc35a2d5c8",
      "tree": "7032d1592232cb3ef40a8cb243b4a38f1c7f3ad8",
      "parents": [
        "dc77df696afb5d97cca79ec123d0e93f7ae84939"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Fri May 15 11:03:25 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri May 15 11:03:25 2026 +0800"
      },
      "message": "Fix: MAL `expPrefix` now applies to every metric source in `exp`, not just the leading one. (#13875)"
    },
    {
      "commit": "dc77df696afb5d97cca79ec123d0e93f7ae84939",
      "tree": "1871ae42ccb2d1406c24f8bed2bb449209826757",
      "parents": [
        "0cec0de68b6767a5328418ecf1115d09458517d7"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue May 12 10:54:58 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue May 12 10:54:58 2026 +0800"
      },
      "message": "SWIP-14: Inspect API on admin-server (with Status API relocation) (#13869)"
    },
    {
      "commit": "0cec0de68b6767a5328418ecf1115d09458517d7",
      "tree": "58d9215a1ebdc8bd6aa4cbedc0e39324fbb0ea3c",
      "parents": [
        "e35cea3a20a75ae85d0b10a3df942fca81b2f243"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Sat May 09 23:25:39 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat May 09 23:25:39 2026 +0800"
      },
      "message": "Fix: `avgHistogramPercentile` / `sumHistogramPercentile` meter functions reported the smallest finite bucket boundary (#13866)"
    },
    {
      "commit": "e35cea3a20a75ae85d0b10a3df942fca81b2f243",
      "tree": "1f69ecd181fee6d38d5059d8d63e8c50aec11e15",
      "parents": [
        "fd54f92e9ceda918db4b28814e56a87478ef1099"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sat May 09 21:46:28 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat May 09 21:46:28 2026 +0800"
      },
      "message": "DSL debugger (OAL): emit source @ScopeDefaultColumn fields on output sample via codegen (#13867)\n\nThe terminal `output` sample of an OAL debug session was missing the\nsource-derived @Column fields that the OAL-generated subclass carries\non its instance — entityId + attr0..attr5 for any Service-style scope.\nOperators inspecting `service_cpm` saw only `total` / `value` from\nCPMMetrics.appendDebugFields; the layer name written to attr0 by\nServiceDecorator (and any other source attributes) was on the live\nobject and in the storage row, but invisible in the debug capture.\n\nWhy the gap: `attr0..attr5` are NOT inherited from a fixed parent for\nOAL — they\u0027re declared on the source class via\n`@ScopeDefaultColumn.DefinedByField` and copied to the generated\nmetrics subclass at OAL boot by `OALClassGeneratorV2.generateMetricsClass`\n(line 220, the per-source-field `addField` loop). The family parent\n(CPMMetrics, SumMetrics, ...) doesn\u0027t know they exist, so its\n`appendDebugFields` override can\u0027t surface them. Reflection-based or\n`Convert2Storage` shim approaches were considered; codegen-side\ngeneration is the right scope — the same pass that materialises the\nfields also emits their debug projection.\n\nAdds `appendDebugFields` to METRICS_CLASS_METHODS so the existing\ntemplate loop generates an override on every OAL-generated `*Metrics`\nsubclass. The override calls `super.appendDebugFields(obj)` first\n(delegating the family\u0027s value columns — total / value / summation /\n...) then iterates `fieldsFromSource` to emit each\n@ScopeDefaultColumn-declared field with the right typed\n`obj.addProperty(...)` overload (Long / Integer / Double / Float /\nBoolean wrappers for primitives so Javassist resolves the\n`addProperty(String, Number)` overload unambiguously; null-safe\n`toString()` for object types).\n\nVerification:\n- `mvn test -pl oap-server/oal-rt`: 98/98 pass.\n- After deploy, an OAL debug session against `oal/core.oal` /\n  `service_cpm` will show `payload.attr0\u003dGENERAL` (set by\n  ServiceDecorator) on the terminal output sample, alongside the\n  family\u0027s `total` and `value`.\n\nCost: zero when `SW_DSL_DEBUGGING_INJECTION_ENABLED\u003dfalse` (codegen\nemits an `appendDebugFields` override either way; it\u0027s only invoked\nfrom `Metrics.toJson()` which is only called by the gated debug\nrecorder). When debug is on, one extra method call per probed emit\nper debug session."
    },
    {
      "commit": "fd54f92e9ceda918db4b28814e56a87478ef1099",
      "tree": "5ba0433a8eebc5ca682404fbde2fa822d11bee2f",
      "parents": [
        "4890024b6cc1c222838b5ebd16e10938762cd7f2"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sat May 09 20:30:09 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat May 09 20:30:09 2026 +0800"
      },
      "message": "DSL debugger (MAL): surface terminal payload.value with two-phase calculate; reduce session record cap to 100 (#13865)\n\n- MAL terminal output sample now carries payload.value rendered per holder\n  type: Long/Int/Double scalars as JSON numbers (NaN / +-Infinity as strings),\n  LabeledValueHolder DataTables as JSON object {key: long}. Force\n  Metrics.calculate() at probe time for two-phase functions\n  (AvgHistogramPercentileFunction / SumHistogramPercentileFunction) so the\n  captured value carries the percentile result keyed by p\u003d\u003crank\u003e rather\n  than the empty pre-calculate map.\n- Per-session record cap dropped from 10000 (default 1000) to 100 hard\n  cap \u003d default. ~1 MiB worst-case heap per session and a UI-readable\n  page; operators inspect a handful of executions, not a paginated\n  firehose. SessionLimits constructor still rejects out-of-range with\n  IllegalArgumentException -\u003e 400 invalid_limits.\n- Both changes are debug-only and zero-cost when no session is installed:\n  the captureMeterEmit probe gate is JIT-elided on hot paths, calculate()\n  is idempotent via the function\u0027s isCalculated guard, and combine()\n  resets isCalculated\u003dfalse so cluster-merged state still recomputes on\n  read.\n- Updated the MAL admin-API doc with a concrete payload example and the\n  SWIP-13 reference cap line / heap math.\n- E2E MAL flow asserts payload.value is present and numeric on every\n  terminal output sample.\n- All 16 existing dsl-debugging unit tests pass."
    },
    {
      "commit": "4890024b6cc1c222838b5ebd16e10938762cd7f2",
      "tree": "0054149f231d72838c1eaf300e4831a6eb50ea50",
      "parents": [
        "67160de8b1cecfa9a679fb345c7566cdd2b760f3"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri May 08 14:07:37 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri May 08 14:07:37 2026 +0800"
      },
      "message": "SWIP-13: Live Debugger for MAL / LAL / OAL + admin-server + runtime-rule integration. (#13864)\n\nSWIP-13: Live Debugger for MAL / LAL / OAL + admin-server module\n\nLands SWIP-13 (https://github.com/apache/skywalking/pull/13864 / docs/en/swip/SWIP-13.md)\nend-to-end as three coordinated changes to the OAP admin surface for 10.5.0:\n\n  1. New `admin-server` module — shared host for admin / on-demand write APIs.\n  2. Runtime-rule hot-update — reroofed onto admin-server, with single-main\n     write routing and L7-LB-safe forwarding over the new admin-internal bus.\n  3. New `dsl-debugging` module — sample-based runtime debugger for the three\n     DSLs (MAL / LAL / OAL) implementing SWIP-13 end-to-end.\n\n\u003d\u003d 1. admin-server (new module) \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nShared host that runs on TWO ports:\n\n  * `port` (default 17128, HTTP)             — operator-facing REST surface.\n  * `gRPCPort` (default 17129, admin-internal) — peer-to-peer cluster RPCs:\n        runtime-rule:   Suspend / Resume / Forward\n        dsl-debugging:  install / collect / stop / stopByClientId\n\nThe admin-internal gRPC bus is a DEDICATED transport, separate from the public\nagent / cluster gRPC port (`core.gRPCPort`, default 11800), so privileged\nadmin RPCs stay out of the agent network\u0027s blast radius. Operators bind\n`gRPCHost` to a private peer-to-peer interface only.\n\nDisabled by default (`SW_ADMIN_SERVER\u003ddefault` to enable). No built-in\nauthentication — must be gateway-protected. See `docs/en/security/README.md`\nand `docs/en/setup/backend/admin-api/readme.md` for the full operator\nchecklist.\n\nDefault per-call timeout for admin-internal RPCs is configurable via\n`admin-server.internalCommunicationTimeout` (default 5000 ms); workflow-\nspecific call sites (runtime-rule Suspend, Forward) keep their own tuned\ndeadlines.\n\n\u003d\u003d 2. runtime-rule hot-update (consolidated onto admin-server) \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nThe runtime-rule plugin\u0027s HTTP routes (`addOrUpdate` / `inactivate` / `delete`\n/ `get` / `bundled` / `list` / `dump`) now mount on `admin-server`\u0027s HTTP\nhost. Single-main write routing is made an explicit public contract:\n\n  * All admin writes for a given (catalog, name) serialize on a single OAP\n    per cluster — the sorted-first peer by address (deterministic, no\n    leader election).\n  * Non-main nodes that receive an HTTP write transparently FORWARD to the\n    main over the admin-internal gRPC bus, so an L7 load balancer in front\n    of the admin port can route any operator request to any OAP.\n  * Cluster convergence on the periodic refresh tick is configurable via\n    `receiver-runtime-rule.refreshRulesPeriod` (default 30 s).\n  * Self-heal threshold for stuck SUSPENDED states stays at\n    `receiver-runtime-rule.selfHealThresholdSeconds` (default 60 s).\n\nThe runtime-rule plugin\u0027s old HTTP-server keys (`receiver-runtime-rule\n.restHost` / `restPort` / `restContextPath` / `restIdleTimeOut` /\n`restAcceptQueueSize` / `httpMaxRequestHeaderSize`, plus their\n`SW_RECEIVER_RUNTIME_RULE_REST_*` env vars) are REMOVED; host-level knobs\nmove under the new `admin-server` block.\n\n\u003d\u003d 3. dsl-debugging (SWIP-13 — new module) \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nSample-based runtime debugger that captures per-stage inputs/outputs as MAL,\nLAL, and OAL process live ingest. Generated bytecode carries one\nvolatile-bool gate per probe call site; idle path is a single volatile load\nthe JIT eliminates after warm-up. Active sessions fan out to every cluster\npeer over the admin-internal gRPC bus so each node captures its own slice.\n\nWire shape (per `docs/en/setup/backend/admin-api/dsl-debugging.md`):\n\n  POST /dsl-debugging/session?catalog\u003d\u0026name\u003d\u0026ruleName\u003d\u0026clientId\u003d\u0026granularity\u003d\n  GET  /dsl-debugging/session/{id}\n  POST /dsl-debugging/session/{id}/stop\n  GET  /dsl-debugging/sessions\n  GET  /dsl-debugging/status\n  GET  /runtime/oal/files            — read-only OAL rule picker source.\n  GET  /runtime/oal/rules/{source}\n\nContract highlights:\n\n  * LB-safe routing. Any node can serve any verb. POST mints `sessionId` on\n    the receiving node, broadcasts install to peers, returns\n    `404 rule_not_found` ONLY when no node owns the rule, and\n    `429 too_many_sessions` ONLY when every rule-owning node is full.\n    Response carries `installed: {created, total}` so operators see\n    \"session live on N of M OAPs\" at a glance.\n  * Two-dimension capture cap (no byte cap, no structural sub-caps):\n        MAX_ACTIVE_SESSIONS \u003d 200    per node (hard ceiling, returns 429)\n        recordCap          ≤ 10000   per session (out-of-range → 400)\n        retentionMillis    ≤ 1 h     per session (out-of-range → 400)\n  * `clientId` is required so the prior session bound to the same client is\n    swept (locally + cluster-broadcast) before a new one is installed.\n  * `sourceText` carries the verbatim ANTLR slice byte-for-byte; `dsl` and a\n    structured `rule` envelope are stamped per-record so a hot-update mid-\n    session keeps the captures unambiguous.\n  * MAL `filter` payload renders the full surviving SampleFamily map\n    (`{\"families\": N, \"items\": [...]}`) so multi-metric expressions show\n    cross-family filter narrowing in the captured wire.\n  * MAL probe sites null-check the GateHolder so a build with\n    `injectionEnabled\u003dfalse` runs MAL analysis without NPEs.\n  * OAL terminal `appendEmit` produces a TYPE_OUTPUT sample carrying the\n    L1-ready Metrics snapshot (matches the wire contract).\n  * OAL debug-source sidecar (.java alongside .class for IDE source-attach)\n    compiles cleanly: WithMetadata FQCN corrected, final fields get `null`\n    initialisers, stub methods get bodies.\n  * Install/uninstall atomicity guarded by a `synchronized(sessions)` block\n    in `DebugSessionRegistry` so concurrent install + uninstall can\u0027t leak\n    an unreachable recorder onto the holder. (Other races have bounded\n    consequences via retention timeout + active-session ceiling and are\n    intentionally unlocked.)\n  * Cluster fan-out runs in parallel with a global deadline \u003d\n    `internalCommunicationTimeout`; per-peer outcomes preserve the peer\u0027s\n    address even on timeout / interrupt / execution failure, so operators\n    can see exactly which OAP failed in `peers[]`.\n  * `MALDebugRecorderImpl.lastDownsample` is per-thread (ThreadLocal) so\n    concurrent MAL passes for the same rule on different analyzer threads\n    can\u0027t overwrite each other\u0027s emit-sample sourceText.\n\nDisabled by default (`SW_DSL_DEBUGGING\u003ddefault` *and* `SW_ADMIN_SERVER\u003ddefault`);\n`injectionEnabled` defaults `true` once the module is enabled (set `false`\nto keep the REST surface but emit bytecode byte-identical to a build\nwithout SWIP-13). Per-DSL operator references at\n`docs/en/setup/backend/admin-api/dsl-debugging-{mal,lal,oal}.md`.\n\n\u003d\u003d Tests \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nUnit tests cover the new session machinery (DebugSessionRegistry,\nRecorderCap, AbstractDebugRecorder, ClusterServiceImpl, GateHolder) and\ninclude a concurrent-install regression that asserts\n`MAX_ACTIVE_SESSIONS` is never overshot under contention.\n\nFour end-to-end cases under\n`test/e2e-v2/cases/dsl-debugging/{mal,lal-block,lal-statement,oal}/` drive\nthe full session lifecycle against real telemetry through BanyanDB +\nruntime-rule and assert the captured wire shape per DSL.\n\nExisting runtime-rule e2e cases now set `SW_ADMIN_SERVER\u003ddefault` alongside\n`SW_RECEIVER_RUNTIME_RULE\u003ddefault` (lal, cluster, mal-storage banyandb /\nelasticsearch / postgresql).\n\n\u003d\u003d Operator upgrade notes \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\n  * Set `SW_ADMIN_SERVER\u003ddefault` whenever `SW_RECEIVER_RUNTIME_RULE\u003ddefault`\n    is set; OAP fails fast at startup otherwise.\n  * Migrate runtime-rule REST environment variables: drop\n    `SW_RECEIVER_RUNTIME_RULE_REST_*`, set `SW_ADMIN_SERVER_*` instead.\n  * Bind admin-server gRPC (`SW_ADMIN_SERVER_GRPC_HOST`, default `0.0.0.0`)\n    to a private peer-to-peer interface; never expose it to operators or\n    to the agent network.\n  * `SW_RECEIVER_RUNTIME_RULE_RECONCILER_INTERVAL_SECONDS` is renamed to\n    `SW_RECEIVER_RUNTIME_RULE_REFRESH_RULES_PERIOD` (same default 30 s,\n    same semantics).\n  * If TLS is enabled on the admin-internal gRPC bus\n    (`SW_ADMIN_SERVER_GRPC_SSL_ENABLED\u003dtrue`), a CA bundle path is\n    REQUIRED — OAP fails fast at startup if `gRPCSslTrustedCAsPath` is\n    empty (prevents silent plaintext fallback on the client side)."
    },
    {
      "commit": "67160de8b1cecfa9a679fb345c7566cdd2b760f3",
      "tree": "cd3cb90baf4f123c84dd0a0fee4b37f43473db60",
      "parents": [
        "2b745b2783472e5f0a65b237b6799eb327938914"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon May 04 10:00:07 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon May 04 10:00:07 2026 +0800"
      },
      "message": "LAL: unify arithmetic operators (+ - * /) with JLS-style type promotion (#13858)"
    },
    {
      "commit": "2b745b2783472e5f0a65b237b6799eb327938914",
      "tree": "a6e2b66a6cd9cfa2e2951e622f8dd7a158b082b9",
      "parents": [
        "dae15534d92aad328f86552a11588473d7cac988"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Apr 30 21:57:26 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 30 21:57:26 2026 +0800"
      },
      "message": "Layer extension: register custom layers without modifying OAP source (#13856)"
    },
    {
      "commit": "dae15534d92aad328f86552a11588473d7cac988",
      "tree": "71e314a42f8f15f68434fb772b20de3ccca0d2b8",
      "parents": [
        "3064b5ffa32db675cdce4f568f834ebb0849c806"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Thu Apr 30 19:06:23 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 30 19:06:23 2026 +0800"
      },
      "message": "Fix: LAL compiler treated `(tag(\"x\") as Integer) + (tag(\"y\") as Integer)` as string concatenation instead of numeric addition. (#13857)"
    },
    {
      "commit": "3064b5ffa32db675cdce4f568f834ebb0849c806",
      "tree": "da9a52607737a3148898627a093c761d0e225316",
      "parents": [
        "7754e3ec3646f8fe965507b0d7618cc34c95742e"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Thu Apr 30 13:50:09 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 30 13:50:09 2026 +0800"
      },
      "message": "Fix: remove the redundant tags from the `envoy-ai-gateway.yaml` LAL configuration. (#13854)"
    },
    {
      "commit": "7754e3ec3646f8fe965507b0d7618cc34c95742e",
      "tree": "c618c8bbfc84db0337c5a5543f461f744734abd5",
      "parents": [
        "36a3f9cb46cfe36f9bbf83ea7731bcbfa3a9cabd"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Apr 30 09:06:35 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 30 09:06:35 2026 +0800"
      },
      "message": "Runtime rule hot-update for MAL and LAL (#13851)\n\nRuntime rule hot-update: REST admin surface for MAL/LAL rule files.\n\nOperators can add, override, inactivate, and delete MAL (`otel-rules`,\n`log-mal-rules`, `telegraf-rules`) and LAL rule files at runtime without\nrestarting OAP. Edits compile and load into the OAP JVM on the fly; every\nnode in a cluster converges on its next periodic scan (~30 s).\n\nThe admin surface is **disabled by default** and listens on **port 17128**\nwhen enabled (`SW_RECEIVER_RUNTIME_RULE\u003ddefault`). It has **no built-in\nauthentication** — operators must gateway-protect with IP allow-lists and\nnever expose it to the public internet.\n\n## REST endpoints\n\n### Write\n\n`POST /runtime/rule/addOrUpdate`\n\n  Body: raw rule YAML. Filter-only edits use a fast in-place swap;\n  structural edits run a cluster pause + DDL + verify + persist + resume\n  cycle.\n\n  Query parameters:\n  - `catalog`               — required; one of `otel-rules`, `log-mal-rules`,\n                              `telegraf-rules`, `lal`. Unknown returns\n                              `400 invalid_catalog`.\n  - `name`                  — required; filesystem-style path under the\n                              catalog root, no extension. Pattern:\n                              `[A-Za-z0-9._-]+(/[A-Za-z0-9._-]+)*`.\n  - `allowStorageChange`    — optional, default `false`. Set `true` to\n                              permit shape-breaking edits (drops measure\n                              data on BanyanDB; orphans rows on ES/JDBC).\n  - `force`                 — optional, default `false`. Recovery flag;\n                              bypasses the byte-identical no-change\n                              short-circuit so re-pushing known-good content\n                              is treated as a fresh apply.\n\n`POST /runtime/rule/inactivate`\n\n  Soft-pause. Stops dispatching for that rule but preserves the backend\n  measure + history so a later `/addOrUpdate` is lossless. The \"off\" intent\n  is durable across restarts.\n\n  Query parameters:\n  - `catalog`, `name`       — required, same as above.\n\n`POST /runtime/rule/delete`\n\n  Removes an INACTIVE row (ACTIVE rules return\n  `409 requires_inactivate_first`). Behaviour depends on `mode` and whether\n  a bundled YAML twin exists on disk:\n  - default mode + no bundled twin: drops the row, leaves the backend as\n    inert artefact (matches bundled-rule deletion on disk).\n  - default mode + bundled twin: refused with\n    `409 requires_revert_to_bundled` so bundled cannot silently take over\n    without an explicit operator decision.\n  - `?mode\u003drevertToBundled` + bundled twin: schema-change pipeline\n    (install runtime locally, apply bundled through the standard pipeline\n    so the runtime-\u003ebundled delta drops runtime-only metrics, installs\n    bundled-only metrics) before removing the row.\n  - `?mode\u003drevertToBundled` + no bundled twin: returns\n    `400 no_bundled_twin`.\n\n  Query parameters:\n  - `catalog`, `name`       — required.\n  - `mode`                  — optional, default empty. Set\n                              `revertToBundled` to drive the schema-change\n                              pipeline.\n\n### Read\n\n`GET /runtime/rule`\n\n  One rule\u0027s YAML body. Default returns the runtime row; falls back to\n  bundled when the row is absent. Supports `ETag` and `If-None-Match` for\n  cheap 304s.\n\n  Query parameters:\n  - `catalog`, `name`       — required.\n  - `source`                — optional, `runtime` (default) or `bundled`.\n                              `bundled` reads on-disk YAML even when a\n                              runtime override is in place.\n  - HTTP `Accept`           — `application/x-yaml` (default) or\n                              `application/json` for the JSON envelope.\n\n`GET /runtime/rule/bundled`\n\n  Bundled rules in one catalog as JSON, with override flag joined from\n  runtime rows.\n\n  Query parameters:\n  - `catalog`               — required.\n  - `withContent`           — optional, default `true`. When `false`,\n                              omits each YAML body (listing only).\n\n`GET /runtime/rule/list`\n\n  Single JSON envelope `{generatedAt, loaderStats, rules}` merging stored\n  rules with this node\u0027s local state. Each row carries `loaderKind`,\n  `loaderName`, `bundled`, and `bundledContentHash` so a UI can render\n  override badges without a second roundtrip.\n\n  Query parameters:\n  - `catalog`               — optional. Narrows the output to one\n                              catalog. Unknown returns\n                              `400 invalid_catalog`.\n\n`GET /runtime/rule/dump[/\u003ccatalog\u003e]`\n\n  Tar.gz of stored rules + manifest.yaml for backup/DR. Trailing\n  `/\u003ccatalog\u003e` narrows the dump.\n\n### Catalog shortcut routes\n\nMirror the canonical paths for scripts that drive a single catalog:\n- `/runtime/mal/otel/{addOrUpdate,inactivate,delete}` -\u003e `catalog\u003dotel-rules`\n- `/runtime/mal/log/{addOrUpdate,inactivate,delete}`  -\u003e `catalog\u003dlog-mal-rules`\n- `/runtime/lal/{addOrUpdate,inactivate,delete}`      -\u003e `catalog\u003dlal`\n\n`telegraf-rules` is supported via canonical routes only.\n\n## Lifecycle / status of a DSL rule\n\nStatus (DAO row + synthetic):\n- `BUNDLED`  — synthetic, shipped on disk with no operator override. Healthy steady state, no DAO row.\n- `ACTIVE`   — DAO row, runtime override is serving.\n- `INACTIVE` — DAO row, soft-paused tombstone. Handlers torn down; backend preserved.\n- `n/a`      — synthetic transient: row was just removed and this node hasn\u0027t swept yet.\n\nLocal state (per node, transient):\n- `RUNNING`     — dispatching samples; commit complete.\n- `SUSPENDED`   — mid-structural-apply. `suspendOrigin` in {SELF, PEER, BOTH}.\n- `NOT_LOADED`  — after `/inactivate` or never installed; no handlers.\n- (null)        — boot-seeded bundled entry; gone-keys reconcile leaves it alone.\n\nLoader kind (per-file classloader):\n- `RUNTIME` — operator-pushed override active.            Loader prefix `runtime-rule:`.\n- `BUNDLED` — bundled rule served via fall-over loader.   Loader prefix `bundled:`.\n- `NONE`    — no per-file loader (bundled-only via the OAP shared default loader, or INACTIVE).\n\nState matrix:\n\n| Operator action history                  | status     | loaderKind | bundled | What is serving                                                 |\n| ---------------------------------------- | ---------- | ---------- | ------- | --------------------------------------------------------------- |\n| Bundled rule, never touched              | `BUNDLED`  | `NONE`     | `true`  | Bundled YAML, OAP shared default classloader.                   |\n| `/addOrUpdate` overriding bundled        | `ACTIVE`   | `RUNTIME`  | `true`  | Runtime override; compare contentHash vs bundledContentHash.    |\n| `/addOrUpdate` brand-new (no twin)       | `ACTIVE`   | `RUNTIME`  | `false` | Runtime override; no bundled fallback.                          |\n| `/inactivate` of override                | `INACTIVE` | `NONE`     | `true`  | Nothing. Bundled does NOT auto-resurrect.                       |\n| `/inactivate` of bundled-only            | `INACTIVE` | `NONE`     | `true`  | Nothing. Tombstone carries the bundled YAML at inactivate-time. |\n| `/inactivate` of brand-new               | `INACTIVE` | `NONE`     | `false` | Nothing. Rule is off.                                           |\n| Post-`revertToBundled` row removed       | `n/a`      | `BUNDLED`  | `true`  | Bundled rule freshly compiled into a `bundled:` loader.         |\n\nLifecycle transitions (linear form, friendly to plain-text diff views):\n\n1.  Initial state: `BUNDLED` (rule shipped on disk, no DAO row).\n2.  `/addOrUpdate` against a bundled or absent rule  -\u003e  `ACTIVE` (loaderKind\u003dRUNTIME).\n3.  `/addOrUpdate` against an `ACTIVE` rule          -\u003e  `ACTIVE` (re-applies; filter-only fast path or structural pipeline depending on the diff).\n4.  `/inactivate` against `ACTIVE`                   -\u003e  `INACTIVE` (handlers torn down, backend preserved).\n5.  `/inactivate` against `BUNDLED`                  -\u003e  `INACTIVE` (tombstone row carrying the bundled YAML at inactivate time).\n6.  `/inactivate` against `INACTIVE`                 -\u003e  `INACTIVE` (idempotent, returns `200 already_inactive`).\n\nFrom `INACTIVE` there are exactly three legal exits:\n\n7a. `/addOrUpdate` with same content                 -\u003e  `ACTIVE` (reactivate; full structural pipeline).\n7b. `/addOrUpdate` with new content                  -\u003e  `ACTIVE` (reactivate with edits).\n7c. `/delete?mode\u003drevertToBundled`                   -\u003e  row gone, `BUNDLED` loader installed (only if a bundled twin exists on disk).\n\n`/delete` (default mode) on `INACTIVE`:\n8a. No bundled twin on disk                          -\u003e  row gone, backend left as inert artefact.\n8b. Bundled twin on disk                             -\u003e  `409 requires_revert_to_bundled` (refused; operator must opt in via 7c).\n\nConstraints:\n- `/delete` against `ACTIVE` always returns `409 requires_inactivate_first` — destruction goes through the explicit two-step `/inactivate -\u003e /delete` workflow.\n- The `INACTIVE` tombstone is durable across OAP restarts; bundled does NOT auto-resurrect when a runtime override is removed via `/inactivate`. Only path 7c brings bundled back.\n\n## Persistence\n\nHot-updates survive OAP restart: at boot, OAP merges bundled rule files with\npersisted runtime rules so the cluster never silently regresses to bundled\ndefaults.\n\nDAO row shape: `(catalog, name, content, status, updateTime)`. Per-backend\nDAO implementations:\n- BanyanDB — etcd-backed property writes; cluster fences on `mod_revision` via Schema Barrier.\n- Elasticsearch — upsert by row.\n- JDBC (H2 / MySQL / PostgreSQL / TiDB / OceanBase) — upsert by row.\n\n## Configuration\n\nApplication.yml block (`oap-server/server-starter/src/main/resources/application.yml`):\n\n| Knob                       | Env var                                                 | Default          |\n| -------------------------- | ------------------------------------------------------- | ---------------- |\n| selector                   | `SW_RECEIVER_RUNTIME_RULE`                              | empty (disabled) |\n| `restHost`                 | `SW_RECEIVER_RUNTIME_RULE_REST_HOST`                    | `0.0.0.0`        |\n| `restPort`                 | `SW_RECEIVER_RUNTIME_RULE_REST_PORT`                    | `17128`          |\n| `restContextPath`          | `SW_RECEIVER_RUNTIME_RULE_REST_CONTEXT_PATH`            | `/`              |\n| `restIdleTimeOut`          | `SW_RECEIVER_RUNTIME_RULE_REST_IDLE_TIMEOUT`            | `30000`          |\n| `restAcceptQueueSize`      | `SW_RECEIVER_RUNTIME_RULE_REST_QUEUE_SIZE`              | `0`              |\n| `httpMaxRequestHeaderSize` | `SW_RECEIVER_RUNTIME_RULE_HTTP_MAX_REQUEST_HEADER_SIZE` | `8192`           |\n| `reconcilerIntervalSeconds`| `SW_RECEIVER_RUNTIME_RULE_RECONCILER_INTERVAL_SECONDS`  | `30`             |\n| `selfHealThresholdSeconds` | `SW_RECEIVER_RUNTIME_RULE_SELF_HEAL_THRESHOLD_SECONDS`  | `60`             |\n\n## Security\n\n- Disabled by default; `selector` is empty out of the box.\n- The admin port has **no authentication** in this iteration. Operators must\n  gateway-protect with IP allow-lists + auth and never expose port 17128 to\n  the public internet.\n- Audit every request — rule content compiles into the OAP JVM, equivalent\n  to shell access on the OAP host.\n- Cluster Suspend RPC rides the existing OAP cluster-bus gRPC server\n  (RemoteService / HealthCheck transport), separate from port 17128.\n\n## Documentation\n\n- `docs/en/setup/backend/backend-runtime-rule-api.md` — full API reference with applyStatus codes and per-backend `/delete` semantics.\n- `docs/en/concepts-and-designs/runtime-rule-hot-update.md` — design doc.\n- `docs/en/security/README.md` — security notice for the admin surface.\n- `docs/en/setup/backend/configuration-vocabulary.md` — env-var reference."
    },
    {
      "commit": "36a3f9cb46cfe36f9bbf83ea7731bcbfa3a9cabd",
      "tree": "65eaa7b4a583b190d5b97be31a5415ae9936795b",
      "parents": [
        "a06f2e1681d0a1cf76a54858dc949a8ea898f96d"
      ],
      "author": {
        "name": "Fine0830",
        "email": "fanxue0830@gmail.com",
        "time": "Mon Apr 27 19:50:26 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 27 19:50:26 2026 +0800"
      },
      "message": "Sync UI (#13848)"
    },
    {
      "commit": "a06f2e1681d0a1cf76a54858dc949a8ea898f96d",
      "tree": "e6a4df3a03c581a0fa0af402d0465edb629355ef",
      "parents": [
        "2319def4a905862aca21edf7703e36549335e3ea"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Mon Apr 27 12:41:01 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 27 12:41:01 2026 +0800"
      },
      "message": "MAL: add `safeDiv(divisor)` on `SampleFamily` that yields `0` when the divisor is `0`. (#13846)"
    },
    {
      "commit": "2319def4a905862aca21edf7703e36549335e3ea",
      "tree": "a3c8b412c1c690cbdc50e9e74ece30f708a1526f",
      "parents": [
        "8242ff6370a92863ba58fc9231fe9add1cc13778"
      ],
      "author": {
        "name": "weixiang1862",
        "email": "652048614@qq.com",
        "time": "Thu Apr 23 16:16:02 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 23 16:16:02 2026 +0800"
      },
      "message": "Fix potential unexpected current directory inclusion in Docker OAP classpath (#13844)"
    },
    {
      "commit": "8242ff6370a92863ba58fc9231fe9add1cc13778",
      "tree": "57af7ba846bca111853de69996314df37f9b2319",
      "parents": [
        "315defe81613fdfa53b874b9bfda0d8296f1e68c"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Tue Apr 21 18:12:24 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 21 18:12:24 2026 +0800"
      },
      "message": "Fix: remove the dependency from `VirtualServiceAnalysisListener` if `GenAIAnalyzerModule` is disabled. (#13838)"
    },
    {
      "commit": "315defe81613fdfa53b874b9bfda0d8296f1e68c",
      "tree": "92149c2824fae20d52a597034b0191f3cecaf75b",
      "parents": [
        "c171fbfdb75cb5ee04761ff872cb2972092e01d2"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Apr 21 15:59:25 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 21 15:59:25 2026 +0800"
      },
      "message": "Bump skywalking-ui submodule for SWIP-12 i18n menu labels (#13840)"
    },
    {
      "commit": "c171fbfdb75cb5ee04761ff872cb2972092e01d2",
      "tree": "da8415264acfce9cefa3f0729acff71cbd074ec8",
      "parents": [
        "681a5be8cb1d4bb77eb40a0d079391ade439a64c"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Apr 21 15:33:09 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 21 15:33:09 2026 +0800"
      },
      "message": "Implement SWIP-12: WeChat \u0026 Alipay Mini Program monitoring (#13835)\n\n## Implement SWIP-12: WeChat \u0026 Alipay Mini Program monitoring (#13835)\n\nAdds end-to-end OAP support for WeChat and Alipay Mini Program observability via the\n[SkyAPM mini-program-monitor](https://github.com/SkyAPM/mini-program-monitor) SDK. Both\nruntimes report through standard OTLP (metrics + logs) plus SkyWalking native trace\nsegments — no new receivers, no new SPIs.\n\n### Highlights\n\n- Two new layers: `WECHAT_MINI_PROGRAM(48)` and `ALIPAY_MINI_PROGRAM(49)`.\n- Two new JavaScript component ids registered in `component-libraries.yml`:\n  `WeChat-MiniProgram(10002)` and `AliPay-MiniProgram(10003)`.\n- Mini-program services / instances / endpoints are produced by **MAL** (OTLP metrics)\n  and **LAL** (OTLP logs) — not by trace analysis. Client-side (exit-only) segments\n  flow through the standard `RPCAnalysisListener` pipeline unchanged, same pattern as\n  browser and iOS layers; `service_cpm` / `service_resp_time` / `endpoint_cpm` do not\n  populate under mini-program layers by design.\n- One MAL enhancement applies generally: `TimeUnit` added to `MALCodegenHelper.ENUM_FQCN`\n  so rule YAML can write `.histogram(\"le\", TimeUnit.MILLISECONDS)` for SDKs that emit\n  bucket bounds in ms (e.g. mini-program\u0027s `miniprogram.request.duration`).\n\n### OAP server\n\n- `Layer.java`: add `WECHAT_MINI_PROGRAM(48, true)` and `ALIPAY_MINI_PROGRAM(49, true)`.\n- `component-libraries.yml`: register `WeChat-MiniProgram: 10002`, `AliPay-MiniProgram: 10003`.\n- `MALCodegenHelper.ENUM_FQCN`: register `TimeUnit → java.util.concurrent.TimeUnit`.\n- Four MAL rule files under `otel-rules/miniprogram/` — per-platform × per-scope:\n  - `wechat-mini-program.yaml` (service + endpoint variants)\n  - `wechat-mini-program-instance.yaml`\n  - `alipay-mini-program.yaml` (subset — Alipay lacks `route` / `script` / `packageLoad` / `first_paint`)\n  - `alipay-mini-program-instance.yaml`\n  - Top-level `filter` gates each file to the correct `miniprogram.platform`.\n  - Each rule explicitly chains `.service(...)` / `.endpoint(...)` — `expSuffix` stays\n    empty in the mixed-scope files so a tail `.service(...)` does not override the\n    endpoint scope (APISIX pattern).\n  - Histogram percentile rule uses `.histogram(\"le\", TimeUnit.MILLISECONDS)` so the\n    bucket-family `le` labels are kept in ms (no default SECONDS × 1000 rescale).\n  - `request_cpm` metric is derived from the histogram\u0027s `_count` family via `.sum()`\n    (DELTA temporality — MAL\u0027s per-minute bucketing sums per-flush counts directly,\n    no `.rate()` / `.increase()` needed).\n- One LAL rule `lal/miniprogram.yaml` using `layer: auto` — one file produces both\n  layers via `sourceAttribute(\"miniprogram.platform\")` dispatch. Extractor emits a\n  `miniprogram_error_count` counter sample per error log.\n- Two log-MAL rules for `error_count`:\n  - `log-mal-rules/miniprogram-wechat.yaml` — gated on `miniprogram_platform \u003d\u003d \u0027wechat\u0027`\n  - `log-mal-rules/miniprogram-alipay.yaml` — gated on `miniprogram_platform \u003d\u003d \u0027alipay\u0027`\n  - Split into two files because `Rules.loadRules` uses `Yaml.loadAs` (single-document).\n- `application.yml` defaults updated:\n  - `enabledOtelMetricsRules` appends `miniprogram/*`\n  - `lalFiles` appends `miniprogram`\n  - `malFiles` appends `miniprogram-wechat,miniprogram-alipay`\n  - `test/e2e-v2/cases/storage/expected/config-dump.yml` mirrored.\n\n### UI\n\n- Menu (`ui-initialized-templates/menu.yaml`): two new entries under the existing\n  `Mobile` group — `WeChat Mini Program` and `Alipay Mini Program`. i18n keys\n  `mobile_wechat_mini_program` / `mobile_alipay_mini_program` are pending in a\n  follow-up `apache/skywalking-booster-ui` PR; the keys fall back to the raw YAML\n  `title` until that lands.\n- Eight new dashboard JSONs:\n  - `wechat_mini_program/{root,service,instance,endpoint}.json`\n  - `alipay_mini_program/{root,service,instance,endpoint}.json`\n  - Each root uses `isRoot: true` with a `ServiceList` widget (4 metric columns).\n  - Service dashboard uses a `Tab` with Overview / Instance / Endpoint / Trace / Log\n    sub-tabs. Alipay service dashboard omits the WeChat-only perf widgets.\n\n### Docs\n\n- `docs/en/setup/backend/backend-wechat-mini-program-monitoring.md` and\n  `backend-alipay-mini-program-monitoring.md`: user-facing setup guides covering\n  prerequisites (SDK ≥ v0.4.0), OAP configuration, SDK init snippet, metric catalog,\n  error-log categories, entity model (incl. the `serviceInstance \u003d\u003d serviceVersion`\n  operator recommendation), SDK-version compatibility, and platform-specific\n  limitations.\n- `docs/menu.yml`: two new entries under `Mobile Monitoring`.\n- `docs/en/changes/changes.md`: entries under `#### OAP Server` and `#### Documentation`.\n\n### Tests\n\n- Two new e2e cases under `test/e2e-v2/cases/miniprogram/{wechat,alipay}/` drive the\n  published `ghcr.io/skyapm/mini-program-monitor/sim-{wechat,alipay}:v0.4.1` image in\n  `MODE\u003dtimed DURATION_MS\u003d60000 SCENARIO\u003ddemo` against OAP wired with the new rules.\n  WeChat: 11 verify cases (service under layer, service/instance/endpoint perf gauges,\n  request_cpm, request_duration_percentile, error_count, LAL-persisted logs). Alipay:\n  8 verify cases (subset matching Alipay\u0027s metric surface).\n- Listener unit tests (`RPCAnalysisListenerTest`,\n  `EndpointDepFromCrossThreadAnalysisListenerTest`) are unchanged from master\n  semantics.\n\n### Follow-ups\n\n- `apache/skywalking-booster-ui` PR for `mobile_wechat_mini_program` /\n  `mobile_alipay_mini_program` i18n keys (menu labels fall back until this lands).\n- Submodule bump once booster-ui PR lands."
    },
    {
      "commit": "681a5be8cb1d4bb77eb40a0d079391ade439a64c",
      "tree": "c1184aeb47d2808cf49a371eadd601d66e451422",
      "parents": [
        "0dabc7033749c0ad9431915d8327e076bc5f4840"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon Apr 20 19:03:16 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 20 19:03:16 2026 +0800"
      },
      "message": "SWIP-12 design + UITemplateInitializer auto-discovery \u0026 dev hot-reload (#13834)\n\n**1. SWIP-12 design doc** (`docs/en/swip/SWIP-12.md`)\nProposes WeChat \u0026 Alipay Mini-Program monitoring as a new pair of `Layer` values. Covers SDK alignment (histogram bucket unit), native-trace SegmentListener SPI, entity model, layer partitioning, dashboards layout, and MAL/OAL scope split. Still a design-only proposal — implementation lands in follow-up PRs.\n\n**2. UITemplateInitializer extensibility + dev hot-reload**\n- `UI_TEMPLATE_FOLDER` is now computed from `Layer.values() + \"custom\"` at class-init time. Adding a new `Layer` enum value is enough — drop a `ui-initialized-templates/\u003clayer-name-lowercased\u003e/` folder on disk and it\u0027s scanned on the next boot. Removes the prior hardcoded allowlist that was easy to miss.\n- `SW_UI_TEMPLATE_FORCE_RELOAD` env var switches the initializer from `addIfNotExist` to a new `addOrReplace` helper on `UITemplateManagementService`. When true, shipped templates overwrite any seeded copy every boot — so dev/extension edits show up after a simple OAP restart without wiping storage. Unset / false preserves the production behavior where operator UI edits persist.\n- `UITemplateCheckerTest` updated to tolerate missing folders (several `Layer` values have no template folders today).\n\n**3. `new-monitoring-feature` skill** (`.claude/skills/new-monitoring-feature/SKILL.md`)\nA wiring map for contributors adding a new layer: which extension point handles which signal (OAL / MAL / LAL / SpanListener / SegmentListener), where contracts live, UI template + submodule touchpoints, and cross-cutting traps."
    },
    {
      "commit": "0dabc7033749c0ad9431915d8327e076bc5f4840",
      "tree": "8e342f02f2f4f6a00f34d42dd3d52f97fddc4ccb",
      "parents": [
        "9e57d91daae1a7511d1e34584fd573af557364c6"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Mon Apr 20 10:22:03 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 20 09:22:03 2026 +0800"
      },
      "message": "Optimize TraceQueryService.sortSpans from O(N^2) to O(N) (#13831)\n\n`TraceQueryService.sortSpans()` builds the parent-child span tree for trace detail rendering. The existing implementation runs in O(N^2):\n\n- `findRoot()` iterates all N spans and, for each, linearly scans the full list to check whether its parent exists.\n- `findChildren()` is called per root and recursively scans the full list at each node to find direct children.\n\nFor traces with deep call chains or many parallel spans this becomes noticeable latency on every trace detail query (a UI hot path).\n\nThis PR pre-indexes the span list once per trace and turns the algorithm into O(N):\n\n- `Set\u003cString\u003e segmentSpanIds` — membership check used by `findRoot` to decide if a span has a parent in the current list.\n- `Map\u003cString, List\u003cSpan\u003e\u003e childrenByParentSegmentSpanId` — direct lookup for `findChildren`.\n\nThe three helpers (`sortSpans`, `findRoot`, `findChildren`) are now package-private `static` because they have always been pure functions — no instance state. This also makes them directly unit-testable.\n\n## Behavior\n\nPreserved from the previous implementation:\n- Root spans sorted by `startTime`.\n- Children traversed in input order (DFS).\n- Orphaned spans (parent not in the list due to lost/sampled segments) treated as roots.\n- Cross-segment ref parents resolved via the shared `segmentSpanId` namespace (`segmentId + \u0027S\u0027 + spanId`)."
    },
    {
      "commit": "9e57d91daae1a7511d1e34584fd573af557364c6",
      "tree": "924545d839c7674d5096db4f72adb631343738be",
      "parents": [
        "272ba7d04251d780f0ce40f5415e0c12b084b1b4"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Sun Apr 19 10:17:02 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 19 10:17:02 2026 +0800"
      },
      "message": "Add iOS/iPadOS app monitoring via OpenTelemetry Swift SDK (SWIP-11) (#13828)\n\n* Add iOS/iPadOS app monitoring via OpenTelemetry Swift SDK (SWIP-11). Includes the `IOS` layer, `IOSHTTPSpanListener` for outbound HTTP client metrics (supports OTel Swift `.old`/`.stable`/`.httpDup` semantic-convention modes via stable-then-legacy attribute fallback), `IOSMetricKitSpanListener` for daily MetricKit metrics (exit counts split by foreground/background, app-launch / hang-time percentile histograms with finite 30 s overflow ceiling), LAL rules for crash/hang diagnostics, Mobile menu, and iOS dashboards.\n* Fix LAL `layer: auto` mode dropping logs after extractor set the layer. Codegen now propagates `layer \"...\"` assignments to `LogMetadata.layer` so `FilterSpec.doSink()` sees the script-decided layer.\n* Fix MetricKit histogram percentile metrics being reported at 1000× their true value — the listener now marks its `SampleFamily` with `defaultHistogramBucketUnit(MILLISECONDS)` so MAL\u0027s default SECONDS→MS rescale of `le` labels is not applied."
    },
    {
      "commit": "272ba7d04251d780f0ce40f5415e0c12b084b1b4",
      "tree": "a96c50c710f3476c59478802c23e17bc95e735d4",
      "parents": [
        "097fe8b448d57bf47fbd428dbf54b71bf08ca1db"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Fri Apr 17 12:17:44 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 17 12:17:44 2026 +0800"
      },
      "message": "Fix: TTL query add metadata TTL and PersistentWorker used wrong TTL for metrics cache if the storage is BanyanDB. (#13827)"
    },
    {
      "commit": "097fe8b448d57bf47fbd428dbf54b71bf08ca1db",
      "tree": "0e7f92af1a866b8f972147174a5a512744c00f5b",
      "parents": [
        "52af116cb49e5f9a91e5a65ee6b632f23b11deea"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Apr 16 18:44:33 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 16 18:44:33 2026 +0800"
      },
      "message": "Add OTLP/HTTP receiver support for traces, logs, and metrics (#13826)\n\nEach existing OTLP gRPC handler now also registers an HTTP handler\nSupported endpoints:\n- POST /v1/traces (protobuf + JSON)\n- POST /v1/logs (protobuf + JSON)\n- POST /v1/metrics (protobuf + JSON)"
    },
    {
      "commit": "52af116cb49e5f9a91e5a65ee6b632f23b11deea",
      "tree": "81b7981c74b76f151bc91f8ae0df35b3ae551a14",
      "parents": [
        "9fda21938fcbf71d77a057105c89d8c1e1d33f5e"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Apr 16 11:39:52 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 16 11:39:52 2026 +0800"
      },
      "message": "Add SpanListener SPI, LAL sourceAttribute() and layer:auto mode (#13825)\n\n### SWIP-11 general-purpose enhancements for extensible trace and log processing\n\nThree features from [SWIP-11](https://github.com/apache/skywalking/discussions/13821):\n\n1. **LAL `sourceAttribute()` function** — non-persistent source context (e.g., OTLP resource attributes) accessible to LAL scripts. Values are NOT stored in `tagsRawData`; scripts selectively copy useful ones into persistent tags.\n\n2. **LAL `layer: auto` mode** — rules with `layer: auto` match logs where `service.layer` is absent. The script determines the layer in the extractor. `abort` \u003d \"not mine, fall back to GENERAL\"; `drop` \u003d \"mine but sampled, no fallback\". If all auto rules abort, falls back to GENERAL automatically.\n\n3. **Two-phase `SpanListener` SPI** — extensible trace span processing in `server-core` (`core.trace` package). Phase 1 (`onOTLPSpan`) runs before Zipkin conversion (OTLP-only). Phase 2 (`onZipkinSpan`) runs after conversion (all trace sources). `requiredModules()` for dependency checking. Lazy init on first span arrival. GenAI refactored from hardcoded `SpanForward.processGenAILogic()` to `GenAISpanListener.onZipkinSpan()`. Removes zipkin-receiver-plugin dependency on gen-ai-analyzer.\n\nAdditional fixes:\n- Register `SpanListenerManager` in `MockCoreModuleProvider` (profile exporter tool)\n- Fix GenAI e2e docker-compose: `provider-py` now depends on `provider` healthcheck to avoid startup race"
    },
    {
      "commit": "9fda21938fcbf71d77a057105c89d8c1e1d33f5e",
      "tree": "a89b6f343338b737e537ab820cc0a9ece8e9ef4f",
      "parents": [
        "9e3dcf1216afcd174e0344725566d5474ce9e0c4"
      ],
      "author": {
        "name": "Mukunda Rao Katta",
        "email": "mukunda.vjcs6@gmail.com",
        "time": "Wed Apr 15 05:07:03 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 20:07:03 2026 +0800"
      },
      "message": "Fix \u0027seperated\u0027 typo in apm-webapp application.yml comment (#13824)"
    },
    {
      "commit": "9e3dcf1216afcd174e0344725566d5474ce9e0c4",
      "tree": "dc8ad748492e2338723b2d050624a6d39aa3e9f2",
      "parents": [
        "35a8b1cac9cf2e684faf0de0dfdaf99119b4b4ea"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Wed Apr 15 20:17:13 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 19:17:13 2026 +0800"
      },
      "message": "Add unit tests for Elasticsearch profiling query DAOs (#13820)"
    },
    {
      "commit": "35a8b1cac9cf2e684faf0de0dfdaf99119b4b4ea",
      "tree": "3d1c2135834b82e764cdbccef70924d5a7b2f7ef",
      "parents": [
        "9e55f574bd11117fb9afe4c17f0f8acd0577424d"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Apr 15 15:42:52 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 15:42:52 2026 +0800"
      },
      "message": "Add SWIP-11: Support iOS App Monitoring via OpenTelemetry (#13822)"
    },
    {
      "commit": "9e55f574bd11117fb9afe4c17f0f8acd0577424d",
      "tree": "0de5f055582c230e218fec3764889174502996e3",
      "parents": [
        "9ea3bab32f8344ece2949f640a2baf52d7c6d465"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Apr 15 13:47:34 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 13:47:34 2026 +0800"
      },
      "message": "Bump infra-e2e to testcontainers-go v0.42.0 and remove deprecated compose version field (#13817)\n\n**Changes:**\n- Bump `skywalking-infra-e2e` to `530f997` (merged apache/skywalking-infra-e2e#146), which migrates testcontainers-go from v0.11.1 to v0.42.0, using Docker Compose v2 plugin natively and removing docker-compose v1 dependency.\n- Remove deprecated `version` field from all docker-compose files (Compose v2 ignores it with a warning).\n\n**What the infra-e2e change does:**\n- Migrates testcontainers-go v0.11.1 → v0.42.0, using native `compose.NewDockerComposeWith` API\n- Deletes ~686 lines of custom `DockerContainer`/`DockerProvider` reimplementation\n- Removes docker-compose v1 binary installation from CI `action.yaml`\n- Adds TCP port waiting after `docker compose up -d` (matching old behavior)\n- Restores `DOCKER_API_VERSION` negotiation for Docker 29+ compatibility\n- User-facing contract (e2e.yaml format, env vars, log paths, CLI) is preserved"
    },
    {
      "commit": "9ea3bab32f8344ece2949f640a2baf52d7c6d465",
      "tree": "f49657fce2e9ea68372a407c757098b657ed7b21",
      "parents": [
        "61a241bbaeaa1558e16af2b9517dbc4ff22e2f6b"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Wed Apr 15 11:48:16 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 11:48:16 2026 +0800"
      },
      "message": "PromQL: support querying Zipkin metadata and TraceQL support more tags and variables querying in Grafana (#13819)"
    },
    {
      "commit": "61a241bbaeaa1558e16af2b9517dbc4ff22e2f6b",
      "tree": "223d5e8c0d5b1c8ca37bf8086cc1ad3ed37ff4b5",
      "parents": [
        "55638d4c9a0df01cd2dec49e76d50d891947beb6"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Wed Apr 15 10:09:41 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 09:09:41 2026 +0800"
      },
      "message": "Fix missing isMergedTable check in ProfileTaskQueryEsDAO.getById() (#13813)"
    },
    {
      "commit": "55638d4c9a0df01cd2dec49e76d50d891947beb6",
      "tree": "60ce82f8dfa7bf7febd629bb3966becd61e7d713",
      "parents": [
        "b4a8811df9f48c66edb61c7b72d0293e3ecfa7cf"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Wed Apr 15 07:11:16 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 15 07:11:16 2026 +0800"
      },
      "message": "Fix Virtual GenAI e2e test base URL for openai-java SDK compatibility (#13818)\n\nSpring AI 2.0.0-SNAPSHOT switched to the official openai-java SDK which\nexpects the base URL to include /v1. Without it, requests go to\n/llm/chat/completions instead of /llm/v1/chat/completions, causing 404."
    },
    {
      "commit": "b4a8811df9f48c66edb61c7b72d0293e3ecfa7cf",
      "tree": "2e7fd1197a5a323bbd82f1b4668f485f91fe8819",
      "parents": [
        "42c613bea94999a6cc8e805ed4c8c7659f3a735c"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Apr 14 11:16:33 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 14 11:16:33 2026 +0800"
      },
      "message": "Fix duplicate calls in EndpointTopologyBuilder (#13816)\n\n* Fix duplicate calls in EndpointTopologyBuilder and enforce no-duplicate in e2e\n\nEndpointTopologyBuilder.build() created a new Call for every CallDetail\nwithout deduplication, unlike ServiceTopologyBuilder which uses a HashMap.\nThis caused duplicate call entries when storage returns multiple records\nfor the same endpoint relation.\n\nAlso switch all dependency topology e2e expected files from `contains`\nto `containsOnce` to enforce strict 1:1 matching and catch duplicates.\n\n* Bump infra-e2e to ef073ad and add noDuplicates to dependency expected files\n\nUpgrade skywalking-infra-e2e to include the noDuplicates pipe function.\nAdd | noDuplicates to all dependency topology expected files for both\nnodes and calls, ensuring storage-level duplicates are caught in e2e."
    },
    {
      "commit": "42c613bea94999a6cc8e805ed4c8c7659f3a735c",
      "tree": "32b962cd0b40c656fff75d7a185f80e07e503903",
      "parents": [
        "7abe7b3b85215a254e2aec9d1e6858848267c728"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon Apr 13 21:51:00 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 13 21:51:00 2026 +0800"
      },
      "message": "Use containsOnce for metadata e2e expected files (#13815)\n\nMigrate outer-level contains to containsOnce in service, instance,\nendpoint, and topology expected files (101 files). containsOnce uses\nbacktracking for optimal 1:1 assignment between expected and actual\nentries, which is more precise for metadata where we know exactly\nwhich entries should exist.\n\nInner nested contains (layers, tags, etc.) are left unchanged."
    },
    {
      "commit": "7abe7b3b85215a254e2aec9d1e6858848267c728",
      "tree": "703098d69378bb6a15cc82ca4ddf2b70492f227d",
      "parents": [
        "5e9b9e2c707b0866f878e7df22e1b006ae5ca725"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon Apr 13 16:10:48 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 13 16:10:48 2026 +0800"
      },
      "message": "Update infra-e2e to b2a6639 and fix duplicate expected entries (#13812)\n\nBump `skywalking-infra-e2e` from `e26033e` to `b2a6639` (apache/skywalking-infra-e2e#143), which enforces distinct matching in `contains` — each actual item can only satisfy one expected entry.\n\nRemove duplicate expected entries that only passed due to the old buggy behavior where a single actual item could satisfy multiple expected entries:\n- `alarm/expected/silence-after-webhook.yml`: reduce from 11 to 5 entries (removed duplicate `service_percentile_rule` and `comp_rule` entries)\n- `rover/process/istio/expected/service.yml`: remove duplicate `ratings.default` entry"
    },
    {
      "commit": "5e9b9e2c707b0866f878e7df22e1b006ae5ca725",
      "tree": "ce3544c1904aa1489ea01bf27c9c69f5fe0e2b8f",
      "parents": [
        "7e93babb2f694e6ed47cd09871ec50f85134a0a2"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Fri Apr 10 21:08:24 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 10 20:08:24 2026 +0800"
      },
      "message": "Add unit tests for 8 more JDBC query DAOs (inline SQL) (#13809)"
    },
    {
      "commit": "7e93babb2f694e6ed47cd09871ec50f85134a0a2",
      "tree": "087de5efad07e135c2ca167095971e7d4dedd568",
      "parents": [
        "073238cd2ad2eaa1ecf948bbc2b04df3fe81e927"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Apr 10 18:47:59 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 10 18:47:59 2026 +0800"
      },
      "message": "Fix Virtual GenAI e2e test failure (#13810)\n\nPin Python dependencies in the OpenAI e2e test Dockerfile and remove\n`opentelemetry-bootstrap --action\u003dinstall` which auto-installs the official `opentelemetry-instrumentation-openai-v2` package that is incompatible with OTel SDK 1.41.0, crashing GenAI instrumentation\nat runtime."
    },
    {
      "commit": "073238cd2ad2eaa1ecf948bbc2b04df3fe81e927",
      "tree": "2ba1d5cbcef1d69aaec13052bd67c25f78eaaec1",
      "parents": [
        "2f03a0179157a3b06416221516733825bb452521"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Thu Apr 09 21:40:35 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 09 20:40:35 2026 +0800"
      },
      "message": "Add unit tests for 6 more JDBC query DAOs (#13808)"
    },
    {
      "commit": "2f03a0179157a3b06416221516733825bb452521",
      "tree": "f3a822f10bcac36e476764ad788a0f8472722856",
      "parents": [
        "cb742a24a22474a0ad734475ceaa3e036ac556a5"
      ],
      "author": {
        "name": "mrproliu",
        "email": "741550557@qq.com",
        "time": "Thu Apr 09 11:54:56 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 09 11:54:56 2026 +0800"
      },
      "message": "Fix missing `taskId` filter in pprof task log query and its DB implementations (#13807)"
    },
    {
      "commit": "cb742a24a22474a0ad734475ceaa3e036ac556a5",
      "tree": "53fc9a48bfe6b0796d7f00ea1489accf8e8c61e4",
      "parents": [
        "ad12d91e8ef55d22e086a4e9364e7173956f0101"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Wed Apr 08 19:51:34 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 08 18:51:34 2026 +0800"
      },
      "message": "Fix wrong merged table check in JFRDataQueryEsDAO (#13805)"
    },
    {
      "commit": "ad12d91e8ef55d22e086a4e9364e7173956f0101",
      "tree": "185866fbbf2a55736ea0d87f0c235c5d24acc002",
      "parents": [
        "4742a3062c6ec5fa9ab77f72dfa8280a1fef4ee4"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Wed Apr 08 17:10:38 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 08 16:10:38 2026 +0800"
      },
      "message": "Add unit tests for JDBCEventQueryDAO, JDBCBrowserLogQueryDAO, and JDBCProfileThreadSnapshotQueryDAO (#13802)"
    },
    {
      "commit": "4742a3062c6ec5fa9ab77f72dfa8280a1fef4ee4",
      "tree": "1fb6186593058a073c1127bcca60137fa5e58a20",
      "parents": [
        "acb63379cdaa80837a2c02835be837b12afb06a8"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Wed Apr 08 15:08:46 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 08 15:08:46 2026 +0800"
      },
      "message": "polish TraceQL service docs (#13804)"
    },
    {
      "commit": "acb63379cdaa80837a2c02835be837b12afb06a8",
      "tree": "16ea6bc5c3a2b8430d37b240a9b104bdc9e44872",
      "parents": [
        "ebda65ca12b64ebfb2eb8e10a6348288f9b5c4c3"
      ],
      "author": {
        "name": "Wan Kai",
        "email": "wankai123@foxmail.com",
        "time": "Tue Apr 07 17:38:11 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 07 17:38:11 2026 +0800"
      },
      "message": "Add TraceQL configuration in docs ui-grafana.md (#13803)"
    },
    {
      "commit": "ebda65ca12b64ebfb2eb8e10a6348288f9b5c4c3",
      "tree": "250101903cb2fe8e8d3d38bf47e03cda4dfe7fe0",
      "parents": [
        "33ad987a72dced25521fe4b2c62fba3d4e187fc9"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Tue Apr 07 09:52:21 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 07 09:52:21 2026 +0800"
      },
      "message": "Add weighted handler support to BatchQueue adaptive partitioning (#13801)\n\n`PartitionPolicy.resolve()` now accepts a weighted handler count instead of raw handler count.\n`BatchQueue.addHandler(type, handler, weight)` overload allows callers to specify partition weight per handler type.\n\n**L1 (MetricsAggregateWorker):** MAL metrics use weight 0.05 (vs 1.0 for OAL). Rationale: MAL emits ~500 items/type per scrape interval. With 20,000-slot buffers, ~40 MAL types can safely share one partition (20,000 / 500 \u003d 40). Weight 0.05 ≈ 1/20 gives 2x headroom.\n\n**L2 (MetricsPersistentMinWorker):** No weight differentiation. After L1 pre-aggregation, both OAL and MAL have similar per-minute burst patterns.\n\n**Impact (8-core, 642 OAL + 1,247 MAL types):**\n\n| | L1 Before | L1 After | Reduction |\n|---|---|---|---|\n| Partitions | 1,045 | 452 | 57% |\n| Array overhead | 167 MB | 72 MB | 57% |"
    },
    {
      "commit": "33ad987a72dced25521fe4b2c62fba3d4e187fc9",
      "tree": "eb8907815b9f0bb178157ca1c129dee9d53b9a7f",
      "parents": [
        "8907f0ce7aa1e211fc4df1c31ed962ae37b76a99"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Mon Apr 06 23:05:26 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 06 23:05:26 2026 +0800"
      },
      "message": "Support MCP observability for Envoy AI Gateway (#13791)\n\n**MAL rules** (new files):\n- `gateway-mcp-service.yaml` — 13 MCP service-level metrics (request CPM/latency/percentile, method CPM, error CPM, initialization latency, capabilities, per-backend breakdown)\n- `gateway-mcp-instance.yaml` — 13 MCP instance-level metrics\n\n**LAL rules** (modified `envoy-ai-gateway.yaml`):\n- Split into two rules: `envoy-ai-gateway-llm-access-log` and `envoy-ai-gateway-mcp-access-log`\n- LLM logs: persist error responses (\u003e\u003d 400) and upstream failures only\n- MCP logs: persist error responses (\u003e\u003d 400) only\n- Both rules tag `ai_route_type` (`llm` or `mcp`) for searchable filtering\n\n**Dashboard** (modified service + instance JSON):\n- Added **MCP** tab with 9 widgets (service) / 6 widgets (instance): request CPM, latency avg/percentile, error CPM, method CPM, initialization latency, backend breakdown\n\n**E2E test** (modified):\n- Added `mcp-server` service (`tzolov/mcp-everything-server:v3` — MCP reference server with StreamableHttp)\n- Added MCP request steps (initialize + tools/list + tools/call)\n- Added MCP metric verification cases\n- Log query uses `ai_route_type\u003dllm` tag filter\n\n**Config**:\n- Added `ai_route_type` to `searchableLogsTags` in `application.yml`\n- Fixed aigw healthcheck binary path (`/app` instead of `aigw`)"
    },
    {
      "commit": "8907f0ce7aa1e211fc4df1c31ed962ae37b76a99",
      "tree": "f170f609174ef8e495f7e625f17c20547aa0d032",
      "parents": [
        "86b6d62d66e8d33bafeac94a3fb21ef390729863"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Mon Apr 06 23:00:11 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 06 22:00:11 2026 +0800"
      },
      "message": "Add unit tests for JDBC query DAO SQL building (#13800)\n\nAdd unit tests for SQL building in JDBCAlarmQueryDAO, JDBCLogQueryDAO, JDBCTraceQueryDAO, and JDBCTopologyQueryDAO, verifying correct WHERE clause construction, JOIN generation, parameter binding, and ORDER BY/LIMIT handling across various filter combinations. "
    },
    {
      "commit": "86b6d62d66e8d33bafeac94a3fb21ef390729863",
      "tree": "afaa28b96e0ae3f5203565f77f4cef6ede0c7e9b",
      "parents": [
        "1b66915a579275c086bc37ca9faa1c67bb77b1aa"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Mon Apr 06 21:46:00 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 06 20:46:00 2026 +0800"
      },
      "message": "Fix duplicate TABLE_COLUMN condition in JDBCMetadataQueryDAO.findEndpoint() (#13794)\n\n`findEndpoint()` was adding the `TABLE_COLUMN \u003d ?` WHERE condition twice and binding `EndpointTraffic.INDEX_NAME` as a parameter twice, due to a copy-paste error.\n\nThe generated SQL was:\n\n```sql\nselect * from endpoint_traffic where table_name \u003d ? and service_id \u003d ? and table_name \u003d ? ...\n```\n\nThe second `table_name \u003d ?` condition is redundant. All other methods in `JDBCMetadataQueryDAO` add the `TABLE_COLUMN` condition exactly once. The fix removes the duplicate condition and its corresponding parameter binding."
    },
    {
      "commit": "1b66915a579275c086bc37ca9faa1c67bb77b1aa",
      "tree": "fc726f854e8ac0164e1dfae1ac1acfd4d9fa6494",
      "parents": [
        "3bb501fd5f1b74c36c2258a1cf798df7db5ebce4"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Sat Apr 04 12:03:31 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Apr 04 11:03:31 2026 +0800"
      },
      "message": "Fix missing AND keyword in JDBCEBPFProfilingTaskDAO.getTaskRecord() SQL (#13789)"
    },
    {
      "commit": "3bb501fd5f1b74c36c2258a1cf798df7db5ebce4",
      "tree": "3f5d3cfed9fe3bf8587981f8ed72a96ea1cc7c60",
      "parents": [
        "f213c3b61022c9b00c61541ed227433406724291"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Sat Apr 04 10:36:58 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Apr 04 09:36:58 2026 +0800"
      },
      "message": "Fix missing parentheses around OR conditions in JDBCZipkinQueryDAO.getTraces() (#13790)\n\n Fix incorrect trace ID filter (OR chain without parentheses) in JDBCZipkinQueryDAO.getTraces(), replaced with IN clause. "
    },
    {
      "commit": "f213c3b61022c9b00c61541ed227433406724291",
      "tree": "cbbdda3bcf72965c8d353bb836048d615daed062",
      "parents": [
        "2f652be84ff6131fc4c9477a405ff2cb1d1066e8"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Fri Apr 03 14:56:28 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 03 13:56:28 2026 +0800"
      },
      "message": "Push taskId filter down to storage layer in AsyncProfilerTaskLog query (#13787)"
    },
    {
      "commit": "2f652be84ff6131fc4c9477a405ff2cb1d1066e8",
      "tree": "e71fa804702c8dc4959402b117e67126b2b7ceb1",
      "parents": [
        "9aac8301ef9aa0cc6421cacd1851f2d45737c4cc"
      ],
      "author": {
        "name": "Hyunjin-Jeong",
        "email": "hyun0524e@naver.com",
        "time": "Fri Apr 03 11:55:36 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 03 10:55:36 2026 +0800"
      },
      "message": "Remove GroupBy.field_name from BanyanDB MeasureQuery request building (#13786)"
    }
  ],
  "next": "9aac8301ef9aa0cc6421cacd1851f2d45737c4cc"
}
