open-telemetry / open-telemetry/opentelemetry-python

Allow Callback Management for Observable Instruments

Open
#4,304 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature-request
Dominant language
Python
Stars
2.6k
Forks
1k
Avg merge
4d 15h
Merged PRs (30d)
19

Description

Is your feature request related to a problem?

Once an instrument is created, there is no straightforward logic to be able to dynamically add or remove callback functions associated with the instrument created. This poses a challenge in scenarios where the instrument is defined at the module level, but the callback functions are dependent on the specific class instances that utilize the instrument.

An instrument is intended to be a singleton, created once with a unique name to ensure consistent data collection and reporting. However, the need for flexibility arises when different class instances require different callback functions to be associated with the same instrument. Since the instrument can only be instantiated once with a given name, it is typically created at the module level. This design choice ensures that the instrument is shared across the application, but it complicates the management of callbacks that are specific to individual classes.

Describe the solution you'd like

Want to be able to manage the callback of a proxy or real instrument within a class to be able to get the data related to the specific class.

Create instrument without callback

udc = meter.create_observable_up_down_counter(name="example")

udc._callbacks = []

Add callback to instrument and be able to see the changes on the fly

udc.add_callback(_instrument_callback)

udc._callbacks=[_instrument_callback]

Remove callback to instrument and be able to see the changes on the fly

udc.remove_callback(_instrument_callback)

udc._callbacks = []

Describe alternatives you've considered

Creating a custom class that directly manipulates the private variables of the instrument to manage callbacks. It breaks the encapsulation principle, making the codebase more susceptible to error if the internal implementation of the instrument changes in future updates.

class ObservableInstrument:
    def __init__(self, inst):
        self._inst = inst
        if not self._inst._callbacks:
            self._inst._callbacks = []

    @property
    def instrument(self):
        return self._inst._real_instrument or self._inst

    def add_callback(self, cb) -> None:
        self.instrument._callbacks.append(cb)

    def remove_callback(self, cb) -> None:
        self.instrument._callbacks.remove(cb)
Additional Context

No response

Would you like to implement a fix?

None

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the observable instrument and proxy callback handling described in the issue, including _real_instrument and _callbacks. Compare the requested add_callback and remove_callback behavior with the existing instrument lifecycle semantics. Done means callbacks can be added and removed at runtime without callers mutating private fields, including for module-level instruments.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
observability-sre
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.