@@ -22,6 +22,11 @@ class MyConfig(ExtractorConfig):
2222 another_parameter: int
2323 schedule: ScheduleConfig
2424
25+ class MyMetrics(BaseMetrics):
26+ def __init__(self, extractor_name: str, extractor_version: str):
27+ super().__init__(extractor_name, extractor_version)
28+ self.custom_counter = Counter("custom_counter", "A custom counter")
29+
2530 class MyExtractor(Extractor[MyConfig]):
2631 NAME = "My Extractor"
2732 EXTERNAL_ID = "my-extractor"
@@ -30,6 +35,9 @@ class MyExtractor(Extractor[MyConfig]):
3035
3136 CONFIG_TYPE = MyConfig
3237
38+ # Override metrics type annotation for IDE support
39+ metrics: MyMetrics
40+
3341 def __init_tasks__(self) -> None:
3442 self.add_task(
3543 ScheduledTask(
@@ -42,6 +50,8 @@ def __init_tasks__(self) -> None:
4250
4351 def my_task_function(self, task_context: TaskContext) -> None:
4452 task_context.logger.info("Running my task")
53+ # IDE will now autocomplete custom_counter
54+ self.metrics.custom_counter.inc()
4555"""
4656
4757import logging
@@ -123,7 +133,7 @@ def __init__(
123133 self .application_config = application_config
124134 self .current_config_revision : ConfigRevision = current_config_revision
125135 self .log_level_override = log_level_override
126- self .metrics_class = metrics_class
136+ self .metrics_class : type [ BaseMetrics ] | None = metrics_class
127137
128138
129139class Extractor (Generic [ConfigType ], CogniteLogger ):
@@ -148,7 +158,7 @@ class Extractor(Generic[ConfigType], CogniteLogger):
148158 RESTART_POLICY : RestartPolicy = WHEN_CONTINUOUS_TASKS_CRASHES
149159 USE_DEFAULT_STATE_STORE : bool = True
150160 _statestore_singleton : AbstractStateStore | None = None
151- _metrics_singleton : BaseMetrics
161+ _metrics_singleton : BaseMetrics | None = None
152162
153163 cancellation_token : CancellationToken
154164
@@ -271,16 +281,15 @@ def _load_metrics(self, metrics_class: type[BaseMetrics] | None = None) -> BaseM
271281 Reuses existing singleton if available to avoid Prometheus registry conflicts.
272282 """
273283 if Extractor ._metrics_singleton is not None :
274- self .metrics = Extractor ._metrics_singleton
275- return self .metrics
284+ return Extractor ._metrics_singleton
276285
277- if metrics_class :
278- self . metrics = safe_get (metrics_class )
286+ if metrics_class and issubclass ( metrics_class , BaseMetrics ) :
287+ metrics_instance = safe_get (metrics_class )
279288 else :
280- self . metrics = BaseMetrics ( extractor_name = self .EXTERNAL_ID , extractor_version = self .VERSION )
289+ metrics_instance = safe_get ( BaseMetrics , extractor_name = self .EXTERNAL_ID , extractor_version = self .VERSION )
281290
282- Extractor ._metrics_singleton = self . metrics
283- return self . metrics
291+ Extractor ._metrics_singleton = metrics_instance
292+ return metrics_instance
284293
285294 @classmethod
286295 def get_current_metrics (cls ) -> BaseMetrics :
0 commit comments