Skip to content

Commit 0b3c669

Browse files
Merge branch 'main' into aastha-live-dlq-it
2 parents be1ada4 + 72a145d commit 0b3c669

File tree

58 files changed

+12763
-1970
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+12763
-1970
lines changed

.github/workflows/update-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
3737
- name: Create Pull Request
3838
id: cpr
39-
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
39+
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
4040
with:
4141
token: ${{ secrets.GITHUB_TOKEN }}
4242
commit-message: 'docs: update generated documentation'

.github/workflows/update-python-deps.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
3333
- name: Create Pull Request
3434
id: cpr
35-
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
35+
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
3636
with:
3737
token: ${{ secrets.GITHUB_TOKEN }}
3838
commit-message: 'deps: update Python dependencies'

plugins/templates-maven-plugin/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
<properties>
3939
<maven.version>3.9.9</maven.version>
40-
<dataflow.api.version>0.92.0</dataflow.api.version>
40+
<dataflow.api.version>0.94.0</dataflow.api.version>
4141
<mojo.executor.version>2.4.1</mojo.executor.version>
4242
<maven-plugin.version>3.15.1</maven-plugin.version>
4343
</properties>

pom.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<maven-checkstyle-plugin.version>3.2.1</maven-checkstyle-plugin.version>
4141
<maven-compiler-plugin.version>3.15.0</maven-compiler-plugin.version>
4242
<maven-dependency-plugin.version>3.10.0</maven-dependency-plugin.version>
43-
<exec-maven-plugin.version>3.6.2</exec-maven-plugin.version>
43+
<exec-maven-plugin.version>3.6.3</exec-maven-plugin.version>
4444
<maven-enforcer-plugin.version>3.6.2</maven-enforcer-plugin.version>
4545
<extra.enforcer.rules.version>1.11.0</extra.enforcer.rules.version>
4646
<maven-jar-plugin.version>3.5.0</maven-jar-plugin.version>
@@ -64,7 +64,7 @@
6464
<checkstyle.version>12.3.0</checkstyle.version>
6565
<commons-codec.version>1.21.0</commons-codec.version>
6666
<commons-compress.version>1.28.0</commons-compress.version>
67-
<commons-io.version>2.18.0</commons-io.version>
67+
<commons-io.version>2.21.0</commons-io.version>
6868
<commons-lang3.version>3.20.0</commons-lang3.version>
6969
<commons-configuration2.version>2.13.0</commons-configuration2.version>
7070
<commons-text.version>1.10.0</commons-text.version>
@@ -82,7 +82,7 @@
8282
<jettison.version>1.5.4</jettison.version>
8383
<json.version>20250517</json.version>
8484
<junit.version>4.13.2</junit.version>
85-
<log4j-2.version>2.25.3</log4j-2.version>
85+
<log4j-2.version>2.25.4</log4j-2.version>
8686
<mock-server-netty.version>5.15.0</mock-server-netty.version>
8787
<mockito.version>4.11.0</mockito.version>
8888
<nashorn.version>15.4</nashorn.version>
@@ -94,7 +94,7 @@
9494
<surefire.version>3.5.5</surefire.version>
9595
<testcontainers.version>1.21.4</testcontainers.version>
9696
<truth.version>1.4.5</truth.version>
97-
<netty.version>4.1.132.Final</netty.version>
97+
<netty.version>4.2.12.Final</netty.version>
9898
<zookeeper.version>3.8.6</zookeeper.version>
9999

100100
<!-- Drop pinned version once maven-dependency-plugin gets past plexus-archiver 4.8.0 -->
@@ -107,7 +107,7 @@
107107
<postgresql.version>42.6.1</postgresql.version>
108108
<ojdbc8.version>23.26.1.0.0</ojdbc8.version>
109109
<mssql-jdbc.version>13.4.0.jre11</mssql-jdbc.version>
110-
<neo4j-driver.version>4.4.18</neo4j-driver.version>
110+
<neo4j-driver.version>5.28.12</neo4j-driver.version>
111111
<okio.version>3.16.4</okio.version>
112112
<jetty.version>12.1.8</jetty.version>
113113
<!-- Socket factory JARs for Cloud SQL -->

python/src/main/java/com/google/cloud/teleport/templates/python/BigQueryAnomalyDetection.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ public interface BigQueryAnomalyDetection {
6363
description = "Detector Specification (JSON)",
6464
helpText =
6565
"JSON string defining the anomaly detector. "
66-
+ "Example: {\"type\":\"ZScore\"} or "
67-
+ "{\"type\":\"ZScore\",\"config\":{\"threshold_criterion\":{\"type\":\"FixedThreshold\","
68-
+ "\"config\":{\"cutoff\":10}}}}")
66+
+ "Statistical: {\"type\":\"ZScore\"}, {\"type\":\"IQR\"}, {\"type\":\"RobustZScore\"}. "
67+
+ "Threshold: {\"type\":\"Threshold\",\"expression\":\"value >= 100\"}. "
68+
+ "RelativeChange: {\"type\":\"RelativeChange\",\"direction\":\"decrease\","
69+
+ "\"threshold_pct\":20,\"lookback_windows\":1}.")
6970
String getDetectorSpec();
7071

7172
@TemplateParameter.Text(

python/src/main/python/bigquery-anomaly-detection/src/bqmonitor/pipeline.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@
236236
from bqmonitor.metric import ComputeMetric
237237
from bqmonitor.metric import FanoutStrategy
238238
from bqmonitor.metric import MetricSpec
239+
from bqmonitor.relative_change_detector import RelativeChangeConfig
240+
from bqmonitor.relative_change_detector import RelativeChangeDoFn
239241
from bqmonitor.safe_eval import Expr
240242
from apache_beam.ml.anomaly.base import AnomalyPrediction
241243
from apache_beam.ml.anomaly.base import AnomalyResult
@@ -250,7 +252,7 @@
250252

251253
_LOGGER = logging.getLogger(__name__)
252254

253-
_SUPPORTED_DETECTORS = ('ZScore', 'IQR', 'RobustZScore')
255+
_SUPPORTED_DETECTORS = ('ZScore', 'IQR', 'RobustZScore', 'RelativeChange')
254256

255257

256258
@dataclass(frozen=True)
@@ -516,6 +518,7 @@ def process(self, element):
516518
{'name': 'value', 'type': 'FLOAT64', 'mode': 'REQUIRED'},
517519
{'name': 'score', 'type': 'FLOAT64', 'mode': 'NULLABLE'},
518520
{'name': 'label', 'type': 'INT64', 'mode': 'REQUIRED'},
521+
{'name': 'info', 'type': 'STRING', 'mode': 'NULLABLE'},
519522
{'name': 'key', 'type': 'STRING', 'mode': 'NULLABLE'},
520523
]
521524
}
@@ -535,6 +538,7 @@ def process(self, element):
535538
'score': float(prediction.score) if prediction.score is not None
536539
else None,
537540
'label': int(prediction.label),
541+
'info': prediction.info if prediction.info else None,
538542
}
539543
if key is not None:
540544
row['key'] = str(key)
@@ -826,6 +830,34 @@ def _parse_detector_spec(json_str):
826830
"It will receive the computed metric value as 'value'.", expr_text)
827831
return _ThresholdAlert(expr_text)
828832

833+
if detector_type == 'RelativeChange':
834+
config = d.get('config', {})
835+
direction = d.get('direction', config.get('direction'))
836+
if direction is None:
837+
raise ValueError(
838+
"RelativeChange detector requires 'direction' "
839+
"(one of: increase, decrease, both).")
840+
lookback_windows = d.get('lookback_windows',
841+
config.get('lookback_windows'))
842+
if lookback_windows is None:
843+
raise ValueError(
844+
"RelativeChange detector requires 'lookback_windows' "
845+
"(number of prior windows to compare against).")
846+
threshold_pct = d.get('threshold_pct',
847+
config.get('threshold_pct'))
848+
absolute_threshold = d.get('absolute_threshold',
849+
config.get('absolute_threshold'))
850+
if threshold_pct is None and absolute_threshold is None:
851+
raise ValueError(
852+
"RelativeChange detector requires at least one of "
853+
"'threshold_pct' or 'absolute_threshold'.")
854+
return RelativeChangeConfig(
855+
direction=direction,
856+
lookback_windows=lookback_windows,
857+
threshold_pct=threshold_pct,
858+
absolute_threshold=absolute_threshold,
859+
)
860+
829861
if detector_type not in _SUPPORTED_DETECTORS:
830862
raise ValueError(
831863
f"Unknown detector type '{detector_type}'. "
@@ -1121,7 +1153,17 @@ def _add_offset_key(element, _wd=_window_duration, _keyed=has_group_by):
11211153
global_metrics = (
11221154
global_metrics | 'AddOffsetKey' >> beam.Map(_add_offset_key))
11231155

1124-
if isinstance(detector, _ThresholdAlert):
1156+
if isinstance(detector, RelativeChangeConfig):
1157+
anomalies = (
1158+
global_metrics
1159+
| 'DetectAnomalies' >> beam.ParDo(
1160+
RelativeChangeDoFn(
1161+
direction=detector.direction,
1162+
threshold_pct=detector.threshold_pct,
1163+
absolute_threshold=detector.absolute_threshold,
1164+
lookback_windows=detector.lookback_windows)))
1165+
1166+
elif isinstance(detector, _ThresholdAlert):
11251167
anomalies = global_metrics | 'DetectAnomalies' >> beam.ParDo(detector)
11261168
else:
11271169
global_metrics = (

0 commit comments

Comments
 (0)