Redesign of metric labels - secondary queries (lazy|query) now just u…#3779
Conversation
…se parent + relativePath + type
# Query metric/plan label change — comparison
Improves the metric/plan name generated for **secondary** (`_lazy` / `_query`) loads so
they relate to their parent/root query, and unifies separators on `.`.
The secondary lazy name is now **always** `orm.<parent's full name>.<path>.<loadMode>`,
so it always prefixes the real parent metric.
## Root query name
| Root query source | Original | New |
|---|---|---|
| `setLabel("custMain")` | `orm.Customer_custMain` | `orm.Customer.custMain` |
| ProfileLocation `CustomerFinder.byName` | `orm.CustomerFinder.byName` | `orm.CustomerFinder.byName` *(same)* |
| ProfileLocation `DataLoader.loadAll` (Customer query) | `orm.Customer_DataLoader.loadAll` | `orm.Customer.DataLoader.loadAll` |
| Unlabeled, no location | `orm.Customer.findList` | `orm.Customer.findList` *(same)* |
## Secondary lazy (`contacts`) name
Original prefixes the **loaded** type (`Contact`) + the call-site location and uses `__`
between path and load mode. New prefixes the **parent's full name**.
| Root query source | Original lazy name | New lazy name |
|---|---|---|
| `setLabel("custMain")` *(profile location also present)* | `orm.Contact_CustomerFinder.findActive_contacts__lazy` — explicit label **lost** | `orm.Customer.custMain.contacts.lazy` |
| `setLabel("custMain")` *(no profile location)* | `orm.Contact_custMain_contacts__lazy` | `orm.Customer.custMain.contacts.lazy` |
| ProfileLocation `CustomerFinder.byName` | `orm.Contact_CustomerFinder.byName_contacts__lazy` | `orm.CustomerFinder.byName.contacts.lazy` |
| ProfileLocation `DataLoader.loadAll` | `orm.Contact_DataLoader.loadAll_contacts__lazy` | `orm.Customer.DataLoader.loadAll.contacts.lazy` |
| Unlabeled, no location | `orm.Contact.findList` *(own name; no parent path)* | `orm.Contact.findList` *(same)* |
## Problems fixed
- **(A) Secondary load didn't relate to its parent** — original prefixed the *loaded* type
(`Contact`) + the *call-site* location, never the parent query's name. New name literally
starts with the parent's full name.
- Explicit `setLabel` was **silently dropped** for secondary queries when a profile location
existed.
- `__` path/loadMode separator and mixed `_`/`.` replaced by uniform `.`.
## Nested and `.query` secondary loads
Each secondary query name is `<immediate parent's full name>.<immediate path>.<loadMode>`,
so every hop literally prefixes its parent metric. Example with root `setLabel("custMain")`
on `Customer`, chain `Customer -> orders -> details`:
Nested lazy:
```
orm.Customer.custMain
orm.Customer.custMain.orders.lazy
orm.Customer.custMain.orders.lazy.details.lazy
```
Secondary eager `.query` fetch:
```
orm.Customer.custMain
orm.Customer.custMain.orders.query
orm.Customer.custMain.orders.query.details.query
```
The intermediate load mode (`.lazy.` / `.query.`) is retained so each name is an exact
extension of its immediate parent's name.
|
Hi @rPraml ... this is a breaking change wrt "metric names" that ebean is using ... but, I really think we need to make this change. The main downside is that for secondary queries (lazy/query) the query type of that is no longer in the metric name. However, the type is still part of the MetaQueryMetric API. I am also making changes in the avaje metrics lib that is targeting reportering that uses "Tags". That is, StatsD Tags and Open Telemetry Attributes ... so in this world this we get the bean type from that "type" tag or attribute and the name is more clear as to how it relates to parent metrics. Hopefully this is ok, but yeah I can also understand that this change could also be a pain wrt a change with lots of existing production metrics etc. |
…ry-comment Regression introduced by #3779 in sql inline comment for label (missing bean type prefix)
…el (missing bean type prefix) So when we used to get an inline comment like: ```sql select /* Customer.hiLabel */ ... ``` We started to instead have (missing bean type): ```sql select /* hiLabel */ ... ``` This fixes that regression that was introduced in ebean-orm#3779
…se parent + relativePath + type
Query metric/plan label change — comparison
Improves the metric/plan name generated for secondary (
_lazy/_query) loads sothey relate to their parent/root query, and unifies separators on
..The secondary lazy name is now always
orm.<parent's full name>.<path>.<loadMode>,so it always prefixes the real parent metric.
Root query name
setLabel("custMain")orm.Customer_custMainorm.Customer.custMainCustomerFinder.byNameorm.CustomerFinder.byNameorm.CustomerFinder.byName(same)DataLoader.loadAll(Customer query)orm.Customer_DataLoader.loadAllorm.DataLoader.loadAllorm.Customer.findListorm.Customer.findList(same)An explicit
setLabel(..)is a short, ambiguous token so it is prefixed with the beantype (
Customer.custMain) for disambiguation. A profile location is already a unique,type-independent identifier (class + method) so it is used as-is — no bean type prefix.
The bean/entity type is still available downstream as the avaje-metrics
typetag.Secondary lazy (
contacts) nameOriginal prefixes the loaded type (
Contact) + the call-site location and uses__between path and load mode. New prefixes the parent's full name.
setLabel("custMain")(profile location also present)orm.Contact_CustomerFinder.findActive_contacts__lazy— explicit label lostorm.Customer.custMain.contacts.lazysetLabel("custMain")(no profile location)orm.Contact_custMain_contacts__lazyorm.Customer.custMain.contacts.lazyCustomerFinder.byNameorm.Contact_CustomerFinder.byName_contacts__lazyorm.CustomerFinder.byName.contacts.lazyDataLoader.loadAllorm.Contact_DataLoader.loadAll_contacts__lazyorm.DataLoader.loadAll.contacts.lazyorm.Contact.findList(own name; no parent path)orm.Contact.findList(same)Problems fixed
(
Contact) + the call-site location, never the parent query's name. New name literallystarts with the parent's full name.
setLabelwas silently dropped for secondary queries when a profile locationexisted.
__path/loadMode separator and mixed_/.replaced by uniform..SQL comment) — neither is bean-type prefixed, so the secondary is an exact extension of the
root (e.g. root
QOrderTest.run→ secondaryQOrderTest.run.customer.query).Nested and
.querysecondary loadsEach secondary query name is
<immediate parent's full name>.<immediate path>.<loadMode>,so every hop literally prefixes its parent metric. Example with root
setLabel("custMain")on
Customer, chainCustomer -> orders -> details:Nested lazy:
Secondary eager
.queryfetch:The intermediate load mode (
.lazy./.query.) is retained so each name is an exactextension of its immediate parent's name.
avaje-metrics: bean type moved to a tag
Because the new ebean names no longer prefix the queried bean type, the entity is now
surfaced as an avaje-metrics tag instead.
ebean.querymetrics now carry:The previous
typetag (which held the category orm/dto/sql) was renamed tokind,freeing
typeto carry the entity name.typeis omitted when the bean type is unknown.This tag is what disambiguates two different-entity queries that happen to share a
profile-location label (e.g. two
DB.find(..)calls of different types in one method witha fixed
ProfileLocation). It does so independently of source line numbers, which are notalways present (fetch-group secondary loads and
ProfileLocation.create("fixed")have none).DatabaseMetricSuppliercaches the derivedMetric.IDby name + bean type (not namealone), so two plans that share a name but differ by type map to distinct ids/tags rather
than the first one's cached id being reused for the second.
The same applies to a ProfileLocation root (no explicit
setLabel). Example with thefinder
CustomerFinder.byNameStatusonCustomer, chainCustomer -> orders -> details:Nested lazy:
Secondary eager
.queryfetch: