Skip to content

Commit 95a24ad

Browse files
committed
Add config schemas for unstable module
These were missing. This also changes the state store config to match with our design guidelines for config structures.
1 parent 7cef0c3 commit 95a24ad

File tree

8 files changed

+346
-60
lines changed

8 files changed

+346
-60
lines changed

cognite/extractorutils/unstable/configuration/models.py

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,7 @@ class RawStateStoreConfig(RawDestinationConfig):
818818
Configuration of a state store based on CDF RAW.
819819
"""
820820

821+
type: Literal["raw"]
821822
upload_interval: TimeIntervalConfig = Field(default_factory=lambda: TimeIntervalConfig("30s"))
822823

823824

@@ -826,17 +827,70 @@ class LocalStateStoreConfig(ConfigModel):
826827
Configuration of a state store using a local JSON file.
827828
"""
828829

830+
type: Literal["local"]
829831
path: Path
830832
save_interval: TimeIntervalConfig = Field(default_factory=lambda: TimeIntervalConfig("30s"))
831833

832834

833-
class StateStoreConfig(ConfigModel):
835+
StateStoreConfig = Annotated[RawStateStoreConfig | LocalStateStoreConfig, Field(discriminator="type")]
836+
837+
838+
def create_state_store(
839+
config: StateStoreConfig | None,
840+
cdf_client: CogniteClient | None = None,
841+
default_to_local: bool = True,
842+
cancellation_token: CancellationToken | None = None,
843+
) -> AbstractStateStore:
834844
"""
835-
Configuration of the State Store, containing ``LocalStateStoreConfig`` or ``RawStateStoreConfig``.
845+
Create a state store object based on the config.
846+
847+
Args:
848+
config: StateStoreConfig object defining the state store to create. If None, the behavior depends on the
849+
default_to_local parameter.
850+
cdf_client: CogniteClient object to use in case of a RAW state store (ignored otherwise)
851+
default_to_local: If true, return a LocalStateStore if no state store is configured. Otherwise return a
852+
NoStateStore
853+
cancellation_token: Cancellation token to pass to created state stores
854+
855+
Returns:
856+
An (uninitialized) state store
857+
"""
858+
if isinstance(config, RawStateStoreConfig):
859+
if cdf_client is None:
860+
raise TypeError("A cognite client object must be provided when state store is RAW")
861+
862+
return RawStateStore(
863+
cdf_client=cdf_client,
864+
database=config.database,
865+
table=config.table,
866+
save_interval=config.upload_interval.seconds,
867+
cancellation_token=cancellation_token,
868+
)
869+
870+
if isinstance(config, LocalStateStoreConfig):
871+
if config.path.is_dir():
872+
raise IsADirectoryError(config.path)
873+
874+
return LocalStateStore(
875+
file_path=str(config.path),
876+
save_interval=config.save_interval.seconds,
877+
cancellation_token=cancellation_token,
878+
)
879+
880+
if default_to_local:
881+
return LocalStateStore(file_path="states.json", cancellation_token=cancellation_token)
882+
883+
return NoStateStore()
884+
885+
886+
class ExtractorConfig(ConfigModel):
887+
"""
888+
Base class for application configuration for extractors.
836889
"""
837890

838-
raw: RawStateStoreConfig | None = None
839-
local: LocalStateStoreConfig | None = None
891+
state_store: StateStoreConfig | None = None
892+
metrics: MetricsConfig | None = None
893+
log_handlers: list[LogHandlerConfig] = Field(default_factory=_log_handler_default)
840894

841895
def create_state_store(
842896
self,
@@ -845,56 +899,17 @@ def create_state_store(
845899
cancellation_token: CancellationToken | None = None,
846900
) -> AbstractStateStore:
847901
"""
848-
Create a state store object based on the config.
902+
Create a state store based on the configuration.
849903
850904
Args:
851905
cdf_client: CogniteClient object to use in case of a RAW state store (ignored otherwise)
852906
default_to_local: If true, return a LocalStateStore if no state store is configured. Otherwise return a
853907
NoStateStore
854908
cancellation_token: Cancellation token to pass to created state stores
855-
856909
Returns:
857-
An (uninitialized) state store
910+
An (uninitialized) state store based on the configuration.
858911
"""
859-
if self.raw and self.local:
860-
raise ValueError("Only one state store can be used simultaneously")
861-
862-
if self.raw:
863-
if cdf_client is None:
864-
raise TypeError("A cognite client object must be provided when state store is RAW")
865-
866-
return RawStateStore(
867-
cdf_client=cdf_client,
868-
database=self.raw.database,
869-
table=self.raw.table,
870-
save_interval=self.raw.upload_interval.seconds,
871-
cancellation_token=cancellation_token,
872-
)
873-
874-
if self.local:
875-
if self.local.path.is_dir():
876-
raise IsADirectoryError(self.local.path)
877-
878-
return LocalStateStore(
879-
file_path=str(self.local.path),
880-
save_interval=self.local.save_interval.seconds,
881-
cancellation_token=cancellation_token,
882-
)
883-
884-
if default_to_local:
885-
return LocalStateStore(file_path="states.json", cancellation_token=cancellation_token)
886-
887-
return NoStateStore()
888-
889-
890-
class ExtractorConfig(ConfigModel):
891-
"""
892-
Base class for application configuration for extractors.
893-
"""
894-
895-
state_store: StateStoreConfig | None = None
896-
metrics: MetricsConfig | None = None
897-
log_handlers: list[LogHandlerConfig] = Field(default_factory=_log_handler_default)
912+
return create_state_store(self.state_store, cdf_client, default_to_local, cancellation_token)
898913

899914

900915
ConfigType = TypeVar("ConfigType", bound=ExtractorConfig)

cognite/extractorutils/unstable/core/base.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ def my_task_function(self, task_context: TaskContext) -> None:
7272
from cognite.extractorutils.metrics import BaseMetrics, MetricsType, safe_get
7373
from cognite.extractorutils.statestore import (
7474
AbstractStateStore,
75-
LocalStateStore,
7675
NoStateStore,
7776
)
7877
from cognite.extractorutils.threading import CancellationToken
@@ -83,6 +82,7 @@ def my_task_function(self, task_context: TaskContext) -> None:
8382
ExtractorConfig,
8483
LogConsoleHandlerConfig,
8584
LogFileHandlerConfig,
85+
create_state_store,
8686
)
8787
from cognite.extractorutils.unstable.core._dto import (
8888
CogniteModel,
@@ -295,16 +295,12 @@ def _load_state_store(self) -> None:
295295
"""
296296
state_store_config = self.application_config.state_store
297297

298-
if state_store_config:
299-
self.state_store = state_store_config.create_state_store(
300-
cdf_client=self.cognite_client,
301-
default_to_local=self.USE_DEFAULT_STATE_STORE,
302-
cancellation_token=self.cancellation_token,
303-
)
304-
elif self.USE_DEFAULT_STATE_STORE:
305-
self.state_store = LocalStateStore("states.json", cancellation_token=self.cancellation_token)
306-
else:
307-
self.state_store = NoStateStore()
298+
self.state_store = create_state_store(
299+
config=state_store_config,
300+
cdf_client=self.cognite_client,
301+
default_to_local=self.USE_DEFAULT_STATE_STORE,
302+
cancellation_token=self.cancellation_token,
303+
)
308304

309305
try:
310306
self.state_store.initialize()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$id": "either_id.schema.json",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"type": "object",
5+
"unevaluatedProperties": false,
6+
"oneOf": [{ "required": ["id"] }, { "required": ["external-id"] }],
7+
"properties": {
8+
"id": {
9+
"type": "integer",
10+
"description": "Resource internal ID"
11+
},
12+
"external-id": {
13+
"type": "string",
14+
"description": "Resource external ID"
15+
}
16+
}
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"$id": "extractor_config.schema.json",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"type": "object",
5+
"description": "Base extractor configuration object",
6+
"unevaluatedProperties": false,
7+
"properties": {
8+
"state-store": {
9+
"$ref": "state_store_config.schema.json"
10+
},
11+
"metrics": {
12+
"$ref": "metrics_config.schema.json"
13+
},
14+
"log-handlers": {
15+
"type": "array",
16+
"description": "List of log handlers to use for logging from the extractor",
17+
"items": {
18+
"$ref": "log_handler_config.schema.json"
19+
}
20+
}
21+
}
22+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"$id": "log_handler_config.schema.json",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"type": "object",
5+
"unevaluatedProperties": false,
6+
"description": "Configuration of a log handler for an extractor.",
7+
"discriminatorProp": "type",
8+
"oneOf": [
9+
{
10+
"type": "object",
11+
"description": "Configuration for a log handler that writes logs to a local file",
12+
"unevaluatedProperties": false,
13+
"title": "File",
14+
"properties": {
15+
"type": {
16+
"type": "string",
17+
"const": "file",
18+
"description": "Type of log handler, must be 'file' for a log handler that writes logs to a local file"
19+
},
20+
"path": {
21+
"type": "string",
22+
"description": "File path to the log file to write logs to"
23+
},
24+
"retention": {
25+
"type": "integer",
26+
"description": "Number of log files to retain when rotating logs.",
27+
"default": 7
28+
},
29+
"level": {
30+
"type": "string",
31+
"description": "Select the verbosity level for console logging. To reduce the verbosity levels, use `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.",
32+
"enum": [
33+
"DEBUG",
34+
"INFO",
35+
"WARNING",
36+
"ERROR",
37+
"CRITICAL"
38+
]
39+
}
40+
},
41+
"required": [
42+
"type",
43+
"path",
44+
"level"
45+
]
46+
},
47+
{
48+
"type": "object",
49+
"description": "Configuration for a log handler that writes logs to the console",
50+
"unevaluatedProperties": false,
51+
"title": "Console",
52+
"properties": {
53+
"type": {
54+
"type": "string",
55+
"const": "console",
56+
"description": "Type of log handler, must be 'console' for a log handler that writes logs to the console"
57+
},
58+
"level": {
59+
"type": "string",
60+
"description": "Select the verbosity level for console logging. To reduce the verbosity levels, use `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.",
61+
"enum": [
62+
"DEBUG",
63+
"INFO",
64+
"WARNING",
65+
"ERROR",
66+
"CRITICAL"
67+
]
68+
}
69+
},
70+
"required": [
71+
"type",
72+
"level"
73+
]
74+
}
75+
]
76+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
{
2+
"$id": "metrics_config.schema.json",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"type": "object",
5+
"unevaluatedProperties": false,
6+
"description": "Configuration of metrics collection for an extractor",
7+
"properties": {
8+
"push-gateways": {
9+
"type": "array",
10+
"description": "List of Prometheus Push Gateways to push metrics to",
11+
"items": {
12+
"type": "object",
13+
"unevaluatedProperties": false,
14+
"properties": {
15+
"host": {
16+
"type": "string",
17+
"description": "Host of the Prometheus Push Gateway, e.g. 'pushgateway.example.com'"
18+
},
19+
"job-name": {
20+
"type": "string",
21+
"description": "Job name to use when pushing metrics to the Prometheus Push Gateway"
22+
},
23+
"username": {
24+
"type": "string",
25+
"description": "Username for authenticating with the Prometheus Push Gateway, if required"
26+
},
27+
"password": {
28+
"type": "string",
29+
"description": "Password for authenticating with the Prometheus Push Gateway, if required"
30+
},
31+
"clear-after": {
32+
"type": "string",
33+
"description": "Interval for clearing metrics from the Prometheus Push Gateway, on the form 12s, 15m, 1h, etc. If not specified, metrics will not be cleared from the Push Gateway."
34+
},
35+
"push-interval": {
36+
"type": "string",
37+
"description": "Interval for pushing metrics to the Prometheus Push Gateway, on the form 12s, 15m, 1h, etc.",
38+
"default": "30s"
39+
}
40+
},
41+
"required": [
42+
"host",
43+
"job-name"
44+
]
45+
}
46+
},
47+
"cognite": {
48+
"type": "object",
49+
"unevaluatedProperties": false,
50+
"description": "Configuration for pushing metrics to CDF Classic time-series",
51+
"properties": {
52+
"external-id-prefix": {
53+
"type": "string",
54+
"description": "Prefix on external ID used when creating CDF time series to store metrics."
55+
},
56+
"asset-name": {
57+
"type": "string",
58+
"description": "Enter the name for a CDF asset that will have all the metrics time series attached to it."
59+
},
60+
"asset-external-id": {
61+
"type": "string",
62+
"description": "Enter the external ID for a CDF asset with all the metrics time series attached to it."
63+
},
64+
"push-interval": {
65+
"type": "string",
66+
"description": "Enter the interval between each push to CDF, on the form 12s, 15m, 1h, etc.",
67+
"default": "30s"
68+
},
69+
"data-set": {
70+
"description": "The data set where the metrics will be created.",
71+
"$ref": "either_id.schema.json"
72+
}
73+
},
74+
"required": [
75+
"external-id-prefix"
76+
]
77+
},
78+
"server": {
79+
"type": "object",
80+
"unevaluatedProperties": false,
81+
"description": "Configuration for exposing an HTTP server with Prometheus metrics for scraping.",
82+
"properties": {
83+
"host": {
84+
"type": "string",
85+
"description": "Host to run the Prometheus server on.",
86+
"default": "0.0.0.0"
87+
},
88+
"port": {
89+
"type": "integer",
90+
"description": "Port to run the Prometheus server on.",
91+
"default": 8080
92+
}
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)