skip to content

ReportPortal's `CreateClustersRQ` carries only `launchId` and `removeNumbers`. What does `removeNumbers` change about the clusters you get back, and how does each setting fail?

level: middleimportance: must knowfreq 52%

answer

  1. one boolean, no other tuning
  2. normalise the text before comparing
  3. digits only, nothing else
  4. off splits, on merges

basics

~10 s

removeNumbers strips digits from failure messages before they are compared. Left off, ids and counts split one problem into many clusters; turned on, failures whose only difference was a numeric code merge into one.

solid answer

~40 s

`removeNumbers` is the single normalisation knob on the request that starts cluster generation -- the body has only `launchId` and this boolean, and being a primitive boolean, omitting it means `false`. With it off, failure messages are compared as they arrived, so any digit that varies between runs -- an order id, a port, an elapsed time, a row count -- makes otherwise identical failures land in separate clusters, and you get a page of one-member clusters. With it on, digits are stripped before comparison, which collapses those correctly, but also merges failures whose only distinguishing feature *was* a numeric code, giving one bucket holding unrelated problems. The project stores its own default as `analyzer.uniqueError.removeNumbers`; the request value overrides it for that generation only and is not persisted.

code

json · 4 lines
json
{
  "launchId": 4821,
  "removeNumbers": true
}

go deeper

for a junior

Know that the request that starts clustering takes only the launch and one boolean, and that the boolean decides whether numbers are stripped from failure text before it is compared.

for a middle

Explain both directions of failure -- off is too narrow, on can be too broad -- and that the request value overrides the project's stored default for that run without saving it.

for a senior

Demonstrate that you test the flag by regenerating the same finished launch and comparing member-count distributions, and that you recognise when the varying token is not numeric at all.

for a principal

Argue where the normalisation should live: one flag on a request, a project-wide default, or discipline about what failure messages are allowed to contain in the first place.

## The request has exactly one knob `CreateClustersRQ` -- the body that starts cluster generation for a ReportPortal launch -- carries **two fields and nothing else**: `launchId`, which is required and names the launch to cluster, and `removeNumbers`, a plain boolean. There is no similarity threshold on this request, no log-line count, no cluster cap. Whatever the grouping does, `removeNumbers` is the only lever the caller gets over it. `removeNumbers` is a **primitive boolean**, so a request that simply omits the field is asking for `false`: group the failure messages exactly as they arrived. ## What each setting does - **`false` -- group on the message as it stands.** Two failures land together only if their failure text compares as the same. Any digit that varies between runs is part of that text: an order id, a port, a row count, an elapsed-milliseconds figure, a line number, a generated account number. - **`true` -- strip digits before comparing.** Messages that differ *only* in their numbers collapse onto each other, so one defect reported a hundred times with a hundred different ids becomes one cluster instead of a hundred. The two settings fail in opposite directions, and both failures are ordinary: | setting | what merges | how it goes wrong | |---|---|---| | `removeNumbers` false | only byte-identical failure text | **too narrow** -- every run mints new clusters, and a cluster list of singletons tells you nothing | | `removeNumbers` true | text that differs only in digits | **too broad** -- failures whose only distinguishing feature *was* a numeric code merge into one bucket | The second column is the part worth rehearsing in an interview. Stripping numbers is not free: if the meaningful difference between two failures is a status code, an error number or an exit code, normalising it away is exactly the wrong move, and you get one large cluster that quietly contains two unrelated problems. ## The project setting underneath it A project stores its own value under the analyzer settings, as `analyzer.uniqueError.removeNumbers`, alongside `analyzer.uniqueError.enabled` which decides whether this kind of clustering is on for the project at all. When a request arrives, the value on the request is **applied over the project's stored value for that one generation**. It is not validated against it and it does not update it. That has a practical consequence worth stating plainly: 1. The project setting is the default that automatic, unattended generation uses. 2. The request flag is a per-run override, so you can try the opposite normalisation on one launch without changing anything for anyone else. 3. Because the override is not persisted, the next automatic run reverts to the project's value -- an experiment you liked has to be promoted into the project setting deliberately. ## When the knob cannot help you `removeNumbers` normalises **digits**. It does nothing about any other varying token, and real failure messages are full of them: - a hostname or pod name with a random suffix - an identifier made of letters as well as digits - a temporary file path with a generated segment - a stack frame from a synthetic proxy class If those are what is splitting your clusters, flipping the flag changes nothing measurable, and the fix has to happen earlier -- in what the failure message says by the time it reaches the report. Recognising that boundary is what separates "I tried the flag" from "I understood what the flag does". ## How to tell whether the flag helped Because a full generation rebuilds a launch's clusters from scratch, the experiment is cheap and repeatable on the same launch: generate with one setting, read the cluster list, generate again with the flag flipped, read it again, and compare the `matchedTests` distributions. A good outcome is a small number of clusters with counts that look like the number of distinct problems you believe the launch actually had. A bad outcome in either direction is visible immediately -- one enormous count, or a page of ones.

  • You turn removeNumbers on, regenerate, and the cluster list looks exactly the same. What is your next move?
    Read the messages. The flag normalises digits only, so if what varies between failures is a hostname suffix, a generated path segment or an identifier containing letters, nothing changes. At that point the fix is not on the request at all -- the varying token has to be gone from the message by the time it reaches the report.
  • Does setting removeNumbers on a request change anything for the project's later automatic runs?
    No. The request value is applied over the project's stored `analyzer.uniqueError.removeNumbers` for that one generation and is not written back. Unattended generation keeps using the project value, so an experiment you liked has to be promoted into the project setting deliberately.
  • Why is stripping digits not simply the safer default to leave on permanently?
    Because numbers are sometimes the only thing distinguishing two failures -- a status code, an error number, an exit code. Normalising those away merges genuinely different problems behind identical text, and the resulting single large cluster hides the second problem completely, which is harder to notice than a list of singletons.

It is the difference between filing letters by their full address and filing them by street name only. Include the house number and every house gets its own drawer; drop it and the street is one drawer -- which is right until two different streets happen to share a name.

saying these in an interview costs you the question

  • Thinking removeNumbers filters out failures containing numbers
  • Believing it caps how many clusters are produced
  • Assuming stripping numbers is always the better setting
  • Expecting it to normalise non-numeric varying tokens