Skip to content

Commit

Permalink
automated rules
Browse files Browse the repository at this point in the history
  • Loading branch information
solidiquis committed Jun 18, 2024
1 parent 6bdece9 commit cbf27cc
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 55 deletions.
2 changes: 1 addition & 1 deletion python/examples/telemetry_config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ rules:
channel_references:
- $1: *log_channel
sub_expressions:
- $2: '\"ERROR\"' # Strings must be escaped
- $2: ERROR
tags:
- foo
- bar
Expand Down
25 changes: 0 additions & 25 deletions python/lib/sift_internal/convert/json.py

This file was deleted.

3 changes: 2 additions & 1 deletion python/lib/sift_py/grpc/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ def _metadata_interceptor(config: SiftChannelConfig) -> ClientInterceptor:
"""
Any new metadata goes here.
"""
apikey = config["apikey"]
metadata: Metadata = [
("authorization", f"Bearer {config["apikey"]}"),
("authorization", f"Bearer {apikey}"),
]
return MetadataInterceptor(metadata)

Expand Down
2 changes: 1 addition & 1 deletion python/lib/sift_py/ingestion/config/yaml_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def test_named_expressions():
channel_references:
- $1: *log_channel
sub_expressions:
- $2: '\"ERROR\"' # Strings must be escaped
- $2: ERROR
tags:
- foo
- bar
Expand Down
2 changes: 1 addition & 1 deletion python/lib/sift_py/ingestion/impl/ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def update_rules(
organization_id: Optional[str] = None,
):
svc = RuleServiceStub(channel)
json_rules = json.dumps([rule.as_json() for rule in rule_configs])
json_rules = json.dumps(rule_configs, default=lambda x: x.as_json())
req = UpdateJsonRulesRequest(
request=JsonRulesRequest(
asset_id=asset_id,
Expand Down
26 changes: 17 additions & 9 deletions python/lib/sift_py/ingestion/rule/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
from ..channel import ChannelConfig, channel_fqn
from sift.annotations.v1.annotations_pb2 import AnnotationType
from sift.rules.v1.rules_pb2 import ActionKind
from sift_internal.convert.json import AsJson, RemoveNullEncoder
from typing import Any, Dict, List, Optional, TypedDict

import json


class RuleConfig(AsJson):
class RuleConfig:
# TODO: Finish doc comment for this
"""
Defines a rule to be used during ingestion. If a rule's expression validates to try, then
Expand Down Expand Up @@ -44,7 +41,7 @@ def __init__(
self.channel_references = channel_references
self.expression = self.__class__.interpolate_sub_expressions(expression, sub_expressions)

def as_json(self) -> str:
def as_json(self) -> Dict[str, Any]:
"""
Produces the appropriate JSON structure that's suitable for the Rules API.
"""
Expand All @@ -68,22 +65,33 @@ def as_json(self) -> str:

if isinstance(self.action, RuleActionCreateDataReviewAnnotation):
hash_map["type"] = RuleActionAnnotationKind.REVIEW.value
hash_map["tags"] = self.action.tags
hash_map["assignee"] = self.action.assignee

if self.action.assignee is not None and len(self.action.assignee) > 0:
hash_map["assignee"] = self.action.assignee

if self.action.tags is not None and len(self.action.tags) > 0:
hash_map["tags"] = self.action.tags

elif isinstance(self.action, RuleActionCreatePhaseAnnotation):
hash_map["type"] = RuleActionAnnotationKind.PHASE.value
hash_map["tags"] = self.action.tags

if self.action.tags is not None and len(self.action.tags) > 0:
hash_map["tags"] = self.action.tags
else:
raise TypeError(f"Unsupported rule action '{self.action.kind()}'.")

return json.dumps(hash_map, cls=RemoveNullEncoder)
return hash_map

@staticmethod
def interpolate_sub_expressions(expression: str, sub_expressions: Dict[str, str]) -> str:
for ref, expr in sub_expressions.items():
if ref not in expression:
raise ValueError(f"Couldn't find '{ref}' in expression '{expression}'.")
expression = expression.replace(ref, str(expr))
if isinstance(expr, str):
expression = expression.replace(ref, f'"{expr}"')
else:
expression = expression.replace(ref, str(expr))

return expression

Expand Down
46 changes: 29 additions & 17 deletions python/lib/sift_py/ingestion/rule/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from ..channel import ChannelConfig, ChannelDataType


def test_rule_config_basic_expression():
expression = "$1 > 10"
config = RuleConfig(
def test_rule_config_json():
voltage_rule_expression = "$1 > 10"
voltage_rule_config = RuleConfig(
name="High Voltage",
description="Rock & Roll",
expression=expression,
expression=voltage_rule_expression,
action=RuleActionCreatePhaseAnnotation(),
channel_references={
"$1": ChannelConfig(
Expand All @@ -20,19 +20,13 @@ def test_rule_config_basic_expression():
),
},
)
assert config.expression == expression
assert (
config.as_json()
== '{"name": "High Voltage", "description": "Rock & Roll", "expression": "$1 > 10", "expression_channel_references": [{"channel_reference": "$1", "channel_identifier": "voltage"}], "type": "phase", "tags": null}'
)

assert voltage_rule_config.expression == voltage_rule_expression

def test_rule_config_test_sub_expression():
expression = '$1 == "Accelerating" && $2 > $3'
config = RuleConfig(
overheating_rule_expression = '$1 == "Accelerating" && $2 > $3'
overheating_rule_config = RuleConfig(
name="overheating",
description="checks if vehicle overheats while accelerating",
expression=expression,
expression=overheating_rule_expression,
action=RuleActionCreateDataReviewAnnotation(
tags=["foo", "bar"],
assignee="[email protected]",
Expand All @@ -53,7 +47,25 @@ def test_rule_config_test_sub_expression():
"$3": 80,
},
)
assert (
config.as_json()
== '{"name": "overheating", "description": "checks if vehicle overheats while accelerating", "expression": "$1 == \\"Accelerating\\" && $2 > 80", "expression_channel_references": [{"channel_reference": "$1", "channel_identifier": "motor.vehicle_state"}, {"channel_reference": "$2", "channel_identifier": "motor.temperature"}], "type": "review", "tags": ["foo", "bar"], "assignee": "[email protected]"}'
assert overheating_rule_config.expression == '$1 == "Accelerating" && $2 > 80'

contains_rule_expression = "contains($1, $2)"
contains_rule_config = RuleConfig(
name="contains",
description="checks if vehicle overheats while accelerating",
expression=contains_rule_expression,
action=RuleActionCreateDataReviewAnnotation(
tags=["foo", "bar"],
assignee="[email protected]",
),
channel_references={
"$1": ChannelConfig(
name="log",
data_type=ChannelDataType.INT_32,
),
},
sub_expressions={
"$2": "Error",
},
)
assert contains_rule_config.expression == 'contains($1, "Error")'

0 comments on commit cbf27cc

Please sign in to comment.