introduce new service.cost_center.id attribute #3397#3537
introduce new service.cost_center.id attribute #3397#3537ankitbhadu wants to merge 3 commits intoopen-telemetry:mainfrom
Conversation
| - ref: service.cost_center.id | ||
| requirement_level: recommended | ||
| role: descriptive |
There was a problem hiding this comment.
Shouldn't this on the instance entity? given it is describing the cost coming from an instance. This ensures that 2 different instances (ie Europe & NA) of the 1 service can have different cost centre.
There was a problem hiding this comment.
Great point! Different regional deployments definitely need different cost centers. However, service.cost_center handles this without going to the instance level.
I believe that service attributes aren't globally locked to a service.name. The EU deployment can emit service.name=my-app, service.cost_center=EU-123, while the NA deployment emits service.name=my-app, service.cost_center=NA-456.
I'm assuming service.instance.id would refer to a single compute unit (like a K8s Pod UID or EC2 instance). Budgets would fund logical deployments/teams, not individual ephemeral pods. Tying the cost center to the instance entity implies two identical pod replicas in the same cluster could be billed to different cost centers, which sounds weird.
Keeping it at service.cost_center correctly maps the financial budget to the logical deployment rather than the underlying compute ID. Wdyt?
There was a problem hiding this comment.
I believe that service attributes aren't globally locked to a service.name. The EU deployment can emit service.name=my-app, service.cost_center=EU-123, while the NA deployment emits service.name=my-app, service.cost_center=NA-456.
The issue is with entities, the design of entities is that the descriptive attributes will update the entity identified by the identifying attributes. Hence in your case the service entity will initially have a cost_center of EU-123 (assuming eu starts first) and then changes to NA-456 when NA starts, if eu restarts it would switch back.
I'm assuming service.instance.id would refer to a single compute unit (like a K8s Pod UID or EC2 instance). Budgets would fund logical deployments/teams, not individual ephemeral pods. Tying the cost center to the instance entity implies two identical pod replicas in the same cluster could be billed to different cost centers, which sounds weird.
Keeping it at service.cost_center correctly maps the financial budget to the logical deployment rather than the underlying compute ID.
Yes that could be theoretically possible but I see that as a better option when compared to the option in this PR where the value on the entity is constantly changing and subject to a race condition.
As a third option, could we add it to the deployment.environment entity and update the namespace to match entity?
There was a problem hiding this comment.
AFAIU
The issue you described should only surface if the service running in (for eg.) EU and NA have identical identifying attributes.. (service.name + service.namespace / service.instance.id are exactly the same) which already seems like a stretch.
If EU and NA have different identifying attributes, then restarts should not overwrite the descriptive attributes attached to it and as such can have different cost_centers for different entities.
Can you clarify if this understanding is somehow incorrect or are you describing a different scenario where EU and NA will identify as the same entity?
There was a problem hiding this comment.
@Ayushi-12 the issue is the below is not actually the case
The issue you described should only surface if the service running in (for eg.) EU and NA have identical identifying attributes.. (service.name + service.namespace / service.instance.id are exactly the same) which already seems like a stretch.
The identifying attributes for the service entity is purely service.name, the other 2 attributes are identifying but on different entities. This is why the restarts become an issue.
The scenario you are thinking of is the resource which would have 3 entities and all 3 of those identifying attributes.
There was a problem hiding this comment.
As a third option, could we add it to the deployment.environment entity and update the namespace to match entity?
This doesn't make sense to me. In practice service.instance.id exists so we can deal with "replicated deployments". It lets you know the instance of something that was deployed. And service itself MAY be a deployment or MAY be a single thing, it's not guaranteed that it's always a deployment. I do not think we want to conflate these two, but there is reasonable reason why a service would update its descriptive attribtues every time a k8s deployment is made - we'll be inferring the service attribtues from the deployment, essentially.
This is why the restarts become an issue.
I don't think this is as big an issue as you're making of it. I agree it's an issue if you need to restart to change cost center for an application however, I'd say two things:
- With Entities SIG - we're working on ways to allow modifying descriptive attributes during execution of a program. That doesn't exist today, but let's leverage that model.
- We should, for now, tie things to lifecycles. Effectively
cost_centerseems more like a "relationship" between cost centers and services. We're using a descriptive attribute to denote this today. Having it onservicemakes the most sense, because it can handle "deployments" or single-instances or other mechanisms of running services.
Shouldn't this on the instance entity? given it is describing the cost coming from an instance. This ensures that 2 different instances (ie Europe & NA) of the 1 service can have different cost centre.
This doesn't make much sense to me. The idea behind service.instance is so you can replicate components of the service and uniquely identify them, but the service itself hasn't changed. I don't think we'll be using different cost centers across that boundary.
I think your example of crossing availability zones is more problematic to the core model. We'd need the ability to distinguish between "service A running in EU" from "service A runing in NA" and have different cost centers for each? While that feels a little contrived, it is something that could be solved via the Entity model, as Entities are only unique globally not universally. I.e. we could place "Service" inside an "Availabiltiy Zone" universe such that services are only unique within a zone, and we can track them separately.
Also - in suggestions - remember that we want Entities so that we can report descriptive attributes separately (not just inline) for joins later. So how would we even be able to report relationships reasonable in an Entities signal if cost center is allocated per-instance? How would users engage with that data model? That feels quite poor.
cc @open-telemetry/entities-maintainers for thoughts on the availability zone concerns.
There was a problem hiding this comment.
In cross-zone/region deployments we can have service instances that belong to different zones. Although they are part of the same "named" service (the value of "service.name" is the same), they can belong to a different set of instances (e.g. one set per zone). This works because we require (service.namespace, service.name, service.instance.id) triplet to be globally unique.
One approach to model the costs would be that cost_center is always an attribute of the runtime entity, not of the logical entity. The reason for that is that costs are almost always incurred by existence of runtime entities (they are runtime costs). Between service and service.instance, the service.instance is the runtime entity and that's where we want to record the cost_center attribute (as a Descriptive attribute of course, not as an Identifying attribute).
To answer a question "what's the total cost of running service X in region Y" you will have to do an aggregation across all service instances "where service.name=X and cloud.region=Y".
--
An additional thing to discuss is whether cost_center is purely a service concept. I can see value in tagging other entities by a cost_center attribute (e.g. "what's the cost of all my hosts grouped by cost_center?").
If we want to generalize like this then I think we can say any entity can have an attribute "cost_center" in its Descriptive attributes. It will be up to the person who does cost calculation to make aggregation queries in a way that makes sense for their situation. Otel will not make any claims about the expect cost structure and hierarchy and which aggregations are meaningful. With this approach we avoid all those discussions about cost tagging boundaries.
The downside of this approach is that building cost observability tools that work in general would be harder since it is hard to know what aggregations are meaningful and which are not.
There was a problem hiding this comment.
The idea behind service.instance is so you can replicate components of the service and uniquely identify them, but the service itself hasn't changed. I don't think we'll be using different cost centers across that boundary.
Correct the service has not changed but who is funding the running of the instances of the service has changed.
We'd need the ability to distinguish between "service A running in EU" from "service A runing in NA" and have different cost centers for each? While that feels a little contrived, it is something that could be solved via the Entity model, as Entities are only unique globally not universally. I.e. we could place "Service" inside an "Availabiltiy Zone" universe such that services are only unique within a zone, and we can track them separately.
The scenario is not contrived at all in fact I am aware of multiple companies who operate in that manner and have in fact worked for a couple that do it. Wouldn't putting service inside an "Availabiltiy Zone" then split the metrics as the entity is now pointing to different entities? Hence resulting in a an even poorer experience.
So how would we even be able to report relationships reasonable in an Entities signal if cost center is allocated per-instance?
The relationship would simply be that which is already defined between service & service.instance.
How would users engage with that data model? That feels quite poor.
I think @tigrannajaryan summarised how this model would be engaged with and key thing for me is this a runtime cost. Yes that query would likely be a bigger query due to needing to generate a list of instances
An additional thing to discuss is whether cost_center is purely a service concept.
I agree and this is where my alternative option comes in. We could add cost_center to deployment.environment and this way we could get all costs not just those for the service but also hosts, hw etc. This would give us a consistent way of querying/using the cost center which could then be filtered as we need.
Fixes #3397
This PR introduces a new attribute - service.cost_center.id
Relevant discussion has been made during Service and Deployment Semconv SIG meet
Meet notes https://docs.google.com/document/d/1Fy6yXfZqrwN_oHw95Bdfg_0hzUgzlk3VO5wA1invgkI/edit?pli=1&tab=t.0#heading=h.bf8dallpt1qu
Recording can be found https://docs.google.com/spreadsheets/d/1SYKfjYhZdm2Wh2Cl6KVQalKg_m4NhTPZqq-8SzEVO6s/edit?gid=0#gid=0 (Feb 12, 2026)
Supporting Doc: https://docs.google.com/document/d/1-UWXtg7vUzSBD_7f6KRLe3o_9pXHBpOrVycoOamvp_8/edit?usp=sharing
Changes
This PR introduces a new semantic convention attribute service.cost_center.id. The cost center identifier enables tracking and attribution of service resource costs to organizational units or teams. This standardization ensures consistent cost allocation across cloud providers, Kubernetes clusters, and observability platforms.
Important
Pull requests acceptance are subject to the triage process as described in Issue and PR Triage Management.
PRs that do not follow the guidance above, may be automatically rejected and closed.
Merge requirement checklist
[chore]