Skip to content

introduce new service.cost_center.id attribute #3397#3537

Open
ankitbhadu wants to merge 3 commits intoopen-telemetry:mainfrom
ankitbhadu:main
Open

introduce new service.cost_center.id attribute #3397#3537
ankitbhadu wants to merge 3 commits intoopen-telemetry:mainfrom
ankitbhadu:main

Conversation

@ankitbhadu
Copy link
Copy Markdown

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

  • [ x] CONTRIBUTING.md guidelines followed.
  • [ x] Change log entry added, according to the guidelines in When to add a changelog entry.
    • If your PR does not need a change log, start the PR title with [chore]
  • [ x] Links to the prototypes or existing instrumentations (when adding or changing conventions)

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla bot commented Mar 11, 2026

CLA Signed

The committers listed above are authorized under a signed CLA.

@github-actions github-actions bot added enhancement New feature or request area:service labels Mar 11, 2026
@ankitbhadu ankitbhadu marked this pull request as ready for review March 12, 2026 06:26
@ankitbhadu ankitbhadu requested review from a team as code owners March 12, 2026 06:26
Comment on lines +21 to +23
- ref: service.cost_center.id
requirement_level: recommended
role: descriptive
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor

@thompson-tomo thompson-tomo Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @thompson-tomo

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. 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.
  2. We should, for now, tie things to lifecycles. Effectively cost_center seems more like a "relationship" between cost centers and services. We're using a descriptive attribute to denote this today. Having it on service makes 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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:service enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: Add service.cost_center.id attribute

5 participants