diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/CHANGELOG.md b/sdk/anomalydetector/ai-anomaly-detector-rest/CHANGELOG.md new file mode 100644 index 000000000000..fe2090aa55f1 --- /dev/null +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/CHANGELOG.md @@ -0,0 +1,5 @@ +# Release History + +## 1.0.0-beta.1 (2022-11-08) + +- First release of package, see README.md for details. diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/karma.conf.js b/sdk/anomalydetector/ai-anomaly-detector-rest/karma.conf.js index 85ddb06133aa..f779f92c6a7f 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/karma.conf.js +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/karma.conf.js @@ -7,7 +7,7 @@ require("dotenv").config(); const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); -module.exports = function(config) { +module.exports = function (config) { config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) basePath: "./", @@ -27,7 +27,7 @@ module.exports = function(config) { "karma-coverage", "karma-sourcemap-loader", "karma-junit-reporter", - "karma-source-map-support" + "karma-source-map-support", ], // list of files / patterns to load in the browser @@ -37,8 +37,8 @@ module.exports = function(config) { pattern: "dist-test/index.browser.js.map", type: "html", included: false, - served: true - } + served: true, + }, ], // list of files / patterns to exclude @@ -47,7 +47,7 @@ module.exports = function(config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - "**/*.js": ["sourcemap", "env"] + "**/*.js": ["sourcemap", "env"], // IMPORTANT: COMMENT following line if you want to debug in your browsers!! // Preprocess source file to calculate code coverage, however this will make source file unreadable // "dist-test/index.js": ["coverage"] @@ -55,11 +55,9 @@ module.exports = function(config) { envPreprocessor: [ "TEST_MODE", - "ENDPOINT", - "AZURE_CLIENT_SECRET", - "AZURE_CLIENT_ID", - "AZURE_TENANT_ID", - "SUBSCRIPTION_ID" + "ANOMALY_DETECTOR_API_KEY", + "ANOMALY_DETECTOR_ENDPOINT", + "RECORDINGS_RELATIVE_PATH", ], // test results reporter to use @@ -74,8 +72,8 @@ module.exports = function(config) { { type: "json", subdir: ".", file: "coverage.json" }, { type: "lcovonly", subdir: ".", file: "lcov.info" }, { type: "html", subdir: "html" }, - { type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" } - ] + { type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" }, + ], }, junitReporter: { @@ -85,7 +83,7 @@ module.exports = function(config) { useBrowserName: false, // add browser name to report and classes names nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element - properties: {} // key value pair of properties to add to the section of the report + properties: {}, // key value pair of properties to add to the section of the report }, // web server port @@ -107,8 +105,8 @@ module.exports = function(config) { customLaunchers: { ChromeHeadlessNoSandbox: { base: "ChromeHeadless", - flags: ["--no-sandbox", "--disable-web-security"] - } + flags: ["--no-sandbox", "--disable-web-security"], + }, }, // Continuous Integration mode @@ -127,8 +125,8 @@ module.exports = function(config) { mocha: { // change Karma's debug.html to the mocha web reporter reporter: "html", - timeout: "600000" - } - } + timeout: "600000", + }, + }, }); }; diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/browsers/anomalydetectorclient/recording_should_detect_changes.json b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/browsers/anomalydetectorclient/recording_should_detect_changes.json new file mode 100644 index 000000000000..4deb0b52359e --- /dev/null +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/browsers/anomalydetectorclient/recording_should_detect_changes.json @@ -0,0 +1,335 @@ +{ + "Entries": [ + { + "RequestUri": "https://endpoint/anomalydetector/v1.1/timeseries/changepoint/detect", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-US", + "Connection": "keep-alive", + "Content-Length": "2760", + "Content-Type": "application/json; charset=UTF-8", + "ocp-apim-subscription-key": "fake_key", + "Referer": "http://localhost:9876/", + "sec-ch-ua": "", + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": "", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-site", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/103.0.5058.0 Safari/537.36", + "x-ms-client-request-id": "4d1c9c82-986e-4dba-987d-ddb4ed663cd5", + "x-ms-useragent": "azsdk-js-ai-anomaly-detector-rest/1.0.0-beta.1 core-rest-pipeline/1.10.1 OS/Linuxx86_64" + }, + "RequestBody": { + "series": [ + { + "timestamp": "2018-03-01T00:00:00.000Z", + "value": 32858923 + }, + { + "timestamp": "2018-03-02T00:00:00.000Z", + "value": 29615278 + }, + { + "timestamp": "2018-03-03T00:00:00.000Z", + "value": 22839355 + }, + { + "timestamp": "2018-03-04T00:00:00.000Z", + "value": 25948736 + }, + { + "timestamp": "2018-03-05T00:00:00.000Z", + "value": 34139159 + }, + { + "timestamp": "2018-03-06T00:00:00.000Z", + "value": 33843985 + }, + { + "timestamp": "2018-03-07T00:00:00.000Z", + "value": 33637661 + }, + { + "timestamp": "2018-03-08T00:00:00.000Z", + "value": 32627350 + }, + { + "timestamp": "2018-03-09T00:00:00.000Z", + "value": 29881076 + }, + { + "timestamp": "2018-03-10T00:00:00.000Z", + "value": 22681575 + }, + { + "timestamp": "2018-03-11T00:00:00.000Z", + "value": 24629393 + }, + { + "timestamp": "2018-03-12T00:00:00.000Z", + "value": 34010679 + }, + { + "timestamp": "2018-03-13T00:00:00.000Z", + "value": 33893888 + }, + { + "timestamp": "2018-03-14T00:00:00.000Z", + "value": 33760076 + }, + { + "timestamp": "2018-03-15T00:00:00.000Z", + "value": 33093515 + }, + { + "timestamp": "2018-03-16T00:00:00.000Z", + "value": 29945555 + }, + { + "timestamp": "2018-03-17T00:00:00.000Z", + "value": 22676212 + }, + { + "timestamp": "2018-03-18T00:00:00.000Z", + "value": 25262514 + }, + { + "timestamp": "2018-03-19T00:00:00.000Z", + "value": 33631649 + }, + { + "timestamp": "2018-03-20T00:00:00.000Z", + "value": 34468310 + }, + { + "timestamp": "2018-03-21T00:00:00.000Z", + "value": 34212281 + }, + { + "timestamp": "2018-03-22T00:00:00.000Z", + "value": 38144434 + }, + { + "timestamp": "2018-03-23T00:00:00.000Z", + "value": 34662949 + }, + { + "timestamp": "2018-03-24T00:00:00.000Z", + "value": 24623684 + }, + { + "timestamp": "2018-03-25T00:00:00.000Z", + "value": 26530491 + }, + { + "timestamp": "2018-03-26T00:00:00.000Z", + "value": 35445003 + }, + { + "timestamp": "2018-03-27T00:00:00.000Z", + "value": 34250789 + }, + { + "timestamp": "2018-03-28T00:00:00.000Z", + "value": 33423012 + }, + { + "timestamp": "2018-03-29T00:00:00.000Z", + "value": 30744783 + }, + { + "timestamp": "2018-03-30T00:00:00.000Z", + "value": 25825128 + }, + { + "timestamp": "2018-03-31T00:00:00.000Z", + "value": 21244209 + }, + { + "timestamp": "2018-04-01T00:00:00.000Z", + "value": 22576956 + }, + { + "timestamp": "2018-04-02T00:00:00.000Z", + "value": 31957221 + }, + { + "timestamp": "2018-04-03T00:00:00.000Z", + "value": 33841228 + }, + { + "timestamp": "2018-04-04T00:00:00.000Z", + "value": 33554483 + }, + { + "timestamp": "2018-04-05T00:00:00.000Z", + "value": 32383350 + }, + { + "timestamp": "2018-04-06T00:00:00.000Z", + "value": 29494850 + }, + { + "timestamp": "2018-04-07T00:00:00.000Z", + "value": 22815534 + }, + { + "timestamp": "2018-04-08T00:00:00.000Z", + "value": 25557267 + }, + { + "timestamp": "2018-04-09T00:00:00.000Z", + "value": 34858252 + }, + { + "timestamp": "2018-04-10T00:00:00.000Z", + "value": 34750597 + }, + { + "timestamp": "2018-04-11T00:00:00.000Z", + "value": 34717956 + }, + { + "timestamp": "2018-04-12T00:00:00.000Z", + "value": 34132534 + }, + { + "timestamp": "2018-04-13T00:00:00.000Z", + "value": 30762236 + }, + { + "timestamp": "2018-04-14T00:00:00.000Z", + "value": 22504059 + }, + { + "timestamp": "2018-04-15T00:00:00.000Z", + "value": 26149060 + }, + { + "timestamp": "2018-04-16T00:00:00.000Z", + "value": 35250105 + } + ], + "granularity": "daily" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "07dd353a-bf5d-4cf9-9c59-7faa6d82b6af", + "Content-Length": "1273", + "Content-Type": "application/json", + "csp-billing-usage": "CognitiveServices.AnomalyDetector.DataPoints=1", + "Date": "Sat, 05 Nov 2022 04:07:33 GMT", + "model-id": "60", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "11", + "x-ms-region": "West US 2" + }, + "ResponseBody": { + "confidenceScores": [ + 0.0, + 3.4933177600615167e-15, + 1.7466588800307583e-15, + 0.0001802983311627988, + 0.0002403977748819851, + 0.0002086171040525728, + 0.0004417101783327612, + 0.0010305134967024988, + 0.0013739797059854765, + 0.005995423102374702, + 0.010929176182266976, + 0.020736184312260576, + 0.02762108928222397, + 0.04096486521868273, + 0.05074252142699788, + 0.06319334137835343, + 0.07254566198477644, + 0.07858313707325576, + 0.08303129787041359, + 0.09363036130108665, + 0.12394107974251839, + 3.4933177600615167e-15, + 5.239976640092275e-15, + 0.0013637783433381966, + 0.001818371124454422, + 0.013534416450583547, + 0.02127575206397004, + 0.24776417093336886, + 0.0, + 0.07819891257886404, + 0.09383869509464103, + 0.03537183760959472, + 0.005846103682923545, + 0.04728275644955462, + 0.0769611816254694, + 0.03696191671373943, + 0.01010854483125586, + 0.02221533780077826, + 0.04472300712079572, + 0.0718394462852747, + 0.09129890160472946, + 0.06895302781018517, + 0.051193691220218364, + 0.02253817060044379, + 0.00038398714742631163, + 0.02105755538267086, + 0.03779147258669402 + ], + "isChangePoint": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + ], + "period": 7 + } + } + ], + "Variables": {} +} diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/browsers/anomalydetectorclient/recording_should_get_multivariate_models.json b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/browsers/anomalydetectorclient/recording_should_get_multivariate_models.json new file mode 100644 index 000000000000..0ca0c2e7bcf3 --- /dev/null +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/browsers/anomalydetectorclient/recording_should_get_multivariate_models.json @@ -0,0 +1,113 @@ +{ + "Entries": [ + { + "RequestUri": "https://endpoint/anomalydetector/v1.1/multivariate/models?skip=0\u0026top=10", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-US", + "Connection": "keep-alive", + "ocp-apim-subscription-key": "fake_key", + "Referer": "http://localhost:9876/", + "sec-ch-ua": "", + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": "", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-site", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/103.0.5058.0 Safari/537.36", + "x-ms-client-request-id": "94982a87-37b9-4f73-accf-b8188883dd11", + "x-ms-useragent": "azsdk-js-ai-anomaly-detector-rest/1.0.0-beta.1 core-rest-pipeline/1.10.1 OS/Linuxx86_64" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "7aaf00fd-60ce-489c-a983-13fcf2f1daa8", + "Content-Length": "1856", + "Content-Type": "application/json", + "Date": "Sat, 05 Nov 2022 04:07:34 GMT", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "192", + "x-ms-region": "West US 2" + }, + "ResponseBody": { + "models": [ + { + "modelId": "e471dd74-5c7a-11ed-8b9c-f2c260c1bff1", + "createdTime": "2022-11-04T19:57:20Z", + "lastUpdatedTime": "2022-11-04T19:57:23Z", + "modelInfo": { + "dataSource": "\u003Cyour data source\u003E", + "dataSchema": "MultiTable", + "startTime": "2021-01-02T00:00:00Z", + "endTime": "2021-01-02T05:00:00Z", + "displayName": "Devops-MultiAD", + "slidingWindow": 200, + "alignPolicy": { + "alignMode": "Outer", + "fillNAMethod": "Linear", + "paddingValue": 0.0 + }, + "status": "FAILED", + "errors": [ + { + "code": "GetDataError", + "message": "FailToAccessBlobURLInvalidIdentityError(\u0027Failed to get system assigned managed identity. Please enable system assigned managed identity and grant \u0027Storage Blob Data Reader\u0027 role to your Anomaly Detector to resolve this problem.\u0027, inner_exception=None)" + } + ], + "diagnosticsInfo": { + "modelState": { + "epochIds": [], + "trainLosses": [], + "validationLosses": [], + "latenciesInSeconds": [] + }, + "variableStates": [] + } + } + }, + { + "modelId": "b96dd010-5c7a-11ed-80b3-6e033f3e188c", + "createdTime": "2022-11-04T19:56:08Z", + "lastUpdatedTime": "2022-11-04T19:56:09Z", + "modelInfo": { + "dataSource": "\u003Cyour data source\u003E", + "dataSchema": "MultiTable", + "startTime": "2021-01-02T00:00:00Z", + "endTime": "2021-01-02T05:00:00Z", + "displayName": "Devops-MultiAD", + "slidingWindow": 200, + "alignPolicy": { + "alignMode": "Outer", + "fillNAMethod": "Linear", + "paddingValue": 0.0 + }, + "status": "FAILED", + "errors": [ + { + "code": "GetDataError", + "message": "FailToAccessBlobURLInvalidIdentityError(\u0027Failed to get system assigned managed identity. Please enable system assigned managed identity and grant \u0027Storage Blob Data Reader\u0027 role to your Anomaly Detector to resolve this problem.\u0027, inner_exception=None)" + } + ], + "diagnosticsInfo": { + "modelState": { + "epochIds": [], + "trainLosses": [], + "validationLosses": [], + "latenciesInSeconds": [] + }, + "variableStates": [] + } + } + } + ], + "currentCount": 2, + "maxCount": 1000, + "nextLink": "" + } + } + ], + "Variables": {} +} diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/node/anomalydetectorclient/recording_should_detect_changes.json b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/node/anomalydetectorclient/recording_should_detect_changes.json new file mode 100644 index 000000000000..864eb31d69ee --- /dev/null +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/node/anomalydetectorclient/recording_should_detect_changes.json @@ -0,0 +1,326 @@ +{ + "Entries": [ + { + "RequestUri": "https://endpoint/anomalydetector/v1.1/timeseries/changepoint/detect", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip,deflate", + "Connection": "keep-alive", + "Content-Length": "2760", + "Content-Type": "application/json; charset=UTF-8", + "Ocp-Apim-Subscription-Key": "fake_key", + "User-Agent": "azsdk-js-ai-anomaly-detector-rest/1.0.0-beta.1 core-rest-pipeline/1.10.1 Node/v16.14.2 OS/(x64-Linux-5.4.0-1094-azure)", + "x-ms-client-request-id": "da0f2328-07c3-4103-a60c-95e3af8cce01" + }, + "RequestBody": { + "series": [ + { + "timestamp": "2018-03-01T00:00:00.000Z", + "value": 32858923 + }, + { + "timestamp": "2018-03-02T00:00:00.000Z", + "value": 29615278 + }, + { + "timestamp": "2018-03-03T00:00:00.000Z", + "value": 22839355 + }, + { + "timestamp": "2018-03-04T00:00:00.000Z", + "value": 25948736 + }, + { + "timestamp": "2018-03-05T00:00:00.000Z", + "value": 34139159 + }, + { + "timestamp": "2018-03-06T00:00:00.000Z", + "value": 33843985 + }, + { + "timestamp": "2018-03-07T00:00:00.000Z", + "value": 33637661 + }, + { + "timestamp": "2018-03-08T00:00:00.000Z", + "value": 32627350 + }, + { + "timestamp": "2018-03-09T00:00:00.000Z", + "value": 29881076 + }, + { + "timestamp": "2018-03-10T00:00:00.000Z", + "value": 22681575 + }, + { + "timestamp": "2018-03-11T00:00:00.000Z", + "value": 24629393 + }, + { + "timestamp": "2018-03-12T00:00:00.000Z", + "value": 34010679 + }, + { + "timestamp": "2018-03-13T00:00:00.000Z", + "value": 33893888 + }, + { + "timestamp": "2018-03-14T00:00:00.000Z", + "value": 33760076 + }, + { + "timestamp": "2018-03-15T00:00:00.000Z", + "value": 33093515 + }, + { + "timestamp": "2018-03-16T00:00:00.000Z", + "value": 29945555 + }, + { + "timestamp": "2018-03-17T00:00:00.000Z", + "value": 22676212 + }, + { + "timestamp": "2018-03-18T00:00:00.000Z", + "value": 25262514 + }, + { + "timestamp": "2018-03-19T00:00:00.000Z", + "value": 33631649 + }, + { + "timestamp": "2018-03-20T00:00:00.000Z", + "value": 34468310 + }, + { + "timestamp": "2018-03-21T00:00:00.000Z", + "value": 34212281 + }, + { + "timestamp": "2018-03-22T00:00:00.000Z", + "value": 38144434 + }, + { + "timestamp": "2018-03-23T00:00:00.000Z", + "value": 34662949 + }, + { + "timestamp": "2018-03-24T00:00:00.000Z", + "value": 24623684 + }, + { + "timestamp": "2018-03-25T00:00:00.000Z", + "value": 26530491 + }, + { + "timestamp": "2018-03-26T00:00:00.000Z", + "value": 35445003 + }, + { + "timestamp": "2018-03-27T00:00:00.000Z", + "value": 34250789 + }, + { + "timestamp": "2018-03-28T00:00:00.000Z", + "value": 33423012 + }, + { + "timestamp": "2018-03-29T00:00:00.000Z", + "value": 30744783 + }, + { + "timestamp": "2018-03-30T00:00:00.000Z", + "value": 25825128 + }, + { + "timestamp": "2018-03-31T00:00:00.000Z", + "value": 21244209 + }, + { + "timestamp": "2018-04-01T00:00:00.000Z", + "value": 22576956 + }, + { + "timestamp": "2018-04-02T00:00:00.000Z", + "value": 31957221 + }, + { + "timestamp": "2018-04-03T00:00:00.000Z", + "value": 33841228 + }, + { + "timestamp": "2018-04-04T00:00:00.000Z", + "value": 33554483 + }, + { + "timestamp": "2018-04-05T00:00:00.000Z", + "value": 32383350 + }, + { + "timestamp": "2018-04-06T00:00:00.000Z", + "value": 29494850 + }, + { + "timestamp": "2018-04-07T00:00:00.000Z", + "value": 22815534 + }, + { + "timestamp": "2018-04-08T00:00:00.000Z", + "value": 25557267 + }, + { + "timestamp": "2018-04-09T00:00:00.000Z", + "value": 34858252 + }, + { + "timestamp": "2018-04-10T00:00:00.000Z", + "value": 34750597 + }, + { + "timestamp": "2018-04-11T00:00:00.000Z", + "value": 34717956 + }, + { + "timestamp": "2018-04-12T00:00:00.000Z", + "value": 34132534 + }, + { + "timestamp": "2018-04-13T00:00:00.000Z", + "value": 30762236 + }, + { + "timestamp": "2018-04-14T00:00:00.000Z", + "value": 22504059 + }, + { + "timestamp": "2018-04-15T00:00:00.000Z", + "value": 26149060 + }, + { + "timestamp": "2018-04-16T00:00:00.000Z", + "value": 35250105 + } + ], + "granularity": "daily" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "59873498-e32d-4409-8778-f74ee89752af", + "Content-Length": "1273", + "Content-Type": "application/json", + "csp-billing-usage": "CognitiveServices.AnomalyDetector.DataPoints=1", + "Date": "Sat, 05 Nov 2022 04:07:31 GMT", + "model-id": "60", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "16", + "x-ms-region": "West US 2" + }, + "ResponseBody": { + "confidenceScores": [ + 0.0, + 3.4933177600615167e-15, + 1.7466588800307583e-15, + 0.0001802983311627988, + 0.0002403977748819851, + 0.0002086171040525728, + 0.0004417101783327612, + 0.0010305134967024988, + 0.0013739797059854765, + 0.005995423102374702, + 0.010929176182266976, + 0.020736184312260576, + 0.02762108928222397, + 0.04096486521868273, + 0.05074252142699788, + 0.06319334137835343, + 0.07254566198477644, + 0.07858313707325576, + 0.08303129787041359, + 0.09363036130108665, + 0.12394107974251839, + 3.4933177600615167e-15, + 5.239976640092275e-15, + 0.0013637783433381966, + 0.001818371124454422, + 0.013534416450583547, + 0.02127575206397004, + 0.24776417093336886, + 0.0, + 0.07819891257886404, + 0.09383869509464103, + 0.03537183760959472, + 0.005846103682923545, + 0.04728275644955462, + 0.0769611816254694, + 0.03696191671373943, + 0.01010854483125586, + 0.02221533780077826, + 0.04472300712079572, + 0.0718394462852747, + 0.09129890160472946, + 0.06895302781018517, + 0.051193691220218364, + 0.02253817060044379, + 0.00038398714742631163, + 0.02105755538267086, + 0.03779147258669402 + ], + "isChangePoint": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + ], + "period": 7 + } + } + ], + "Variables": {} +} diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/node/anomalydetectorclient/recording_should_get_multivariate_models.json b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/node/anomalydetectorclient/recording_should_get_multivariate_models.json new file mode 100644 index 000000000000..7b034a110daf --- /dev/null +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/recordings/node/anomalydetectorclient/recording_should_get_multivariate_models.json @@ -0,0 +1,104 @@ +{ + "Entries": [ + { + "RequestUri": "https://endpoint/anomalydetector/v1.1/multivariate/models?skip=0\u0026top=10", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip,deflate", + "Connection": "keep-alive", + "Ocp-Apim-Subscription-Key": "fake_key", + "User-Agent": "azsdk-js-ai-anomaly-detector-rest/1.0.0-beta.1 core-rest-pipeline/1.10.1 Node/v16.14.2 OS/(x64-Linux-5.4.0-1094-azure)", + "x-ms-client-request-id": "4ff02736-e48b-48b5-aa79-b1d05c96ca8b" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "777929de-bbcb-4475-9a9e-595db1028ef2", + "Content-Length": "1856", + "Content-Type": "application/json", + "Date": "Sat, 05 Nov 2022 04:07:32 GMT", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "46", + "x-ms-region": "West US 2" + }, + "ResponseBody": { + "models": [ + { + "modelId": "e471dd74-5c7a-11ed-8b9c-f2c260c1bff1", + "createdTime": "2022-11-04T19:57:20Z", + "lastUpdatedTime": "2022-11-04T19:57:23Z", + "modelInfo": { + "dataSource": "\u003Cyour data source\u003E", + "dataSchema": "MultiTable", + "startTime": "2021-01-02T00:00:00Z", + "endTime": "2021-01-02T05:00:00Z", + "displayName": "Devops-MultiAD", + "slidingWindow": 200, + "alignPolicy": { + "alignMode": "Outer", + "fillNAMethod": "Linear", + "paddingValue": 0.0 + }, + "status": "FAILED", + "errors": [ + { + "code": "GetDataError", + "message": "FailToAccessBlobURLInvalidIdentityError(\u0027Failed to get system assigned managed identity. Please enable system assigned managed identity and grant \u0027Storage Blob Data Reader\u0027 role to your Anomaly Detector to resolve this problem.\u0027, inner_exception=None)" + } + ], + "diagnosticsInfo": { + "modelState": { + "epochIds": [], + "trainLosses": [], + "validationLosses": [], + "latenciesInSeconds": [] + }, + "variableStates": [] + } + } + }, + { + "modelId": "b96dd010-5c7a-11ed-80b3-6e033f3e188c", + "createdTime": "2022-11-04T19:56:08Z", + "lastUpdatedTime": "2022-11-04T19:56:09Z", + "modelInfo": { + "dataSource": "\u003Cyour data source\u003E", + "dataSchema": "MultiTable", + "startTime": "2021-01-02T00:00:00Z", + "endTime": "2021-01-02T05:00:00Z", + "displayName": "Devops-MultiAD", + "slidingWindow": 200, + "alignPolicy": { + "alignMode": "Outer", + "fillNAMethod": "Linear", + "paddingValue": 0.0 + }, + "status": "FAILED", + "errors": [ + { + "code": "GetDataError", + "message": "FailToAccessBlobURLInvalidIdentityError(\u0027Failed to get system assigned managed identity. Please enable system assigned managed identity and grant \u0027Storage Blob Data Reader\u0027 role to your Anomaly Detector to resolve this problem.\u0027, inner_exception=None)" + } + ], + "diagnosticsInfo": { + "modelState": { + "epochIds": [], + "trainLosses": [], + "validationLosses": [], + "latenciesInSeconds": [] + }, + "variableStates": [] + } + } + } + ], + "currentCount": 2, + "maxCount": 1000, + "nextLink": "" + } + } + ], + "Variables": {} +} diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/sample.env b/sdk/anomalydetector/ai-anomaly-detector-rest/sample.env index 672847a3fea0..07fb106bf447 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/sample.env +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/sample.env @@ -1,4 +1,3 @@ # App registration secret for AAD authentication -AZURE_CLIENT_SECRET= -AZURE_CLIENT_ID= -AZURE_TENANT_ID= \ No newline at end of file +ANOMALY_DETECTOR_API_KEY= +ANOMALY_DETECTOR_ENDPOINT= diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_change_point.ts b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_change_point.ts index 99dc07eff972..49c5daf02e06 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_change_point.ts +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_change_point.ts @@ -25,7 +25,6 @@ dotenv.config(); const apiKey = process.env["ANOMALY_DETECTOR_API_KEY"] || ""; const endpoint = process.env["ANOMALY_DETECTOR_ENDPOINT"] || ""; -const apiVersion = "v1.1"; const timeSeriesDataPath = "./samples-dev/example-data/request-data.csv"; function read_series_from_file(path: string): Array { @@ -40,7 +39,7 @@ function read_series_from_file(path: string): Array { export async function main() { const credential = new AzureKeyCredential(apiKey); - const client = AnomalyDetector(endpoint, credential, { apiVersion }); + const client = AnomalyDetector(endpoint, credential); const options: DetectUnivariateChangePointParameters = { body: { granularity: "daily", diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_entire_series_anomaly.ts b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_entire_series_anomaly.ts index 5ced5049b736..9f7baef95d34 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_entire_series_anomaly.ts +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_entire_series_anomaly.ts @@ -24,7 +24,6 @@ dotenv.config(); // You will need to set this environment variables or edit the following values const apiKey = process.env["ANOMALY_DETECTOR_API_KEY"] || ""; const endpoint = process.env["ANOMALY_DETECTOR_ENDPOINT"] || ""; -const apiVersion = "v1.1"; const timeSeriesDataPath = "./samples-dev/example-data/request-data.csv"; function read_series_from_file(path: string): Array { @@ -40,7 +39,7 @@ function read_series_from_file(path: string): Array { export async function main() { // create client const credential = new AzureKeyCredential(apiKey); - const client = AnomalyDetector(endpoint, credential, { apiVersion }); + const client = AnomalyDetector(endpoint, credential); // construct request const options: DetectUnivariateEntireSeriesParameters = { diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_last_point_anomaly.ts b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_last_point_anomaly.ts index e0f548349ae7..0e0e2b5e249a 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_last_point_anomaly.ts +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_detect_last_point_anomaly.ts @@ -24,7 +24,6 @@ dotenv.config(); // You will need to set this environment variables or edit the following values const apiKey = process.env["ANOMALY_DETECTOR_API_KEY"] || ""; const endpoint = process.env["ANOMALY_DETECTOR_ENDPOINT"] || ""; -const apiVersion = "v1.1"; const timeSeriesDataPath = "./samples-dev/example-data/request-data.csv"; function read_series_from_file(path: string): Array { @@ -40,7 +39,7 @@ function read_series_from_file(path: string): Array { export async function main() { // create client const credential = new AzureKeyCredential(apiKey); - const client = AnomalyDetector(endpoint, credential, { apiVersion }); + const client = AnomalyDetector(endpoint, credential); // construct request const options: DetectUnivariateLastPointParameters = { diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_multivariate_detection.ts b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_multivariate_detection.ts index e02490879c05..83f9affe8bcc 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_multivariate_detection.ts +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/samples-dev/sample_multivariate_detection.ts @@ -23,7 +23,6 @@ dotenv.config(); // You will need to set this environment variables or edit the following values const apiKey = process.env["ANOMALY_DETECTOR_API_KEY"] || ""; const endpoint = process.env["ANOMALY_DETECTOR_ENDPOINT"] || ""; -const apiVersion = "v1.1"; const dataSource = ""; function sleep(time: number): Promise { @@ -33,7 +32,7 @@ function sleep(time: number): Promise { export async function main() { // create client const credential = new AzureKeyCredential(apiKey); - const client = AnomalyDetector(endpoint, credential, { apiVersion }); + const client = AnomalyDetector(endpoint, credential); // Already available models const options: ListMultivariateModelsParameters = { diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/anomalydetector.spec.ts b/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/anomalydetector.spec.ts index d46f700ce855..d1311cd586b0 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/anomalydetector.spec.ts +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/anomalydetector.spec.ts @@ -3,13 +3,17 @@ import { Recorder } from "@azure-tools/test-recorder"; import { Context } from "mocha"; -import { createRecorder } from "./utils/recordedClient"; +import { createClient, createRecorder } from "./utils/recordedClient"; +import { AnomalyDetectorRestClient, isUnexpected } from "../../src"; +import { assert } from "chai"; describe("AnomalyDetectorClient", () => { let recorder: Recorder; + let client: AnomalyDetectorRestClient; beforeEach(async function (this: Context) { recorder = await createRecorder(this); + client = await createClient(recorder); }); afterEach(async function () { @@ -18,7 +22,80 @@ describe("AnomalyDetectorClient", () => { } }); - it("sample test", async function () { - console.log("Hi, I'm a test!"); + it("should detect changes", async function () { + const series = [ + { timestamp: "2018-03-01T00:00:00.000Z", value: 32858923 }, + { timestamp: "2018-03-02T00:00:00.000Z", value: 29615278 }, + { timestamp: "2018-03-03T00:00:00.000Z", value: 22839355 }, + { timestamp: "2018-03-04T00:00:00.000Z", value: 25948736 }, + { timestamp: "2018-03-05T00:00:00.000Z", value: 34139159 }, + { timestamp: "2018-03-06T00:00:00.000Z", value: 33843985 }, + { timestamp: "2018-03-07T00:00:00.000Z", value: 33637661 }, + { timestamp: "2018-03-08T00:00:00.000Z", value: 32627350 }, + { timestamp: "2018-03-09T00:00:00.000Z", value: 29881076 }, + { timestamp: "2018-03-10T00:00:00.000Z", value: 22681575 }, + { timestamp: "2018-03-11T00:00:00.000Z", value: 24629393 }, + { timestamp: "2018-03-12T00:00:00.000Z", value: 34010679 }, + { timestamp: "2018-03-13T00:00:00.000Z", value: 33893888 }, + { timestamp: "2018-03-14T00:00:00.000Z", value: 33760076 }, + { timestamp: "2018-03-15T00:00:00.000Z", value: 33093515 }, + { timestamp: "2018-03-16T00:00:00.000Z", value: 29945555 }, + { timestamp: "2018-03-17T00:00:00.000Z", value: 22676212 }, + { timestamp: "2018-03-18T00:00:00.000Z", value: 25262514 }, + { timestamp: "2018-03-19T00:00:00.000Z", value: 33631649 }, + { timestamp: "2018-03-20T00:00:00.000Z", value: 34468310 }, + { timestamp: "2018-03-21T00:00:00.000Z", value: 34212281 }, + { timestamp: "2018-03-22T00:00:00.000Z", value: 38144434 }, + { timestamp: "2018-03-23T00:00:00.000Z", value: 34662949 }, + { timestamp: "2018-03-24T00:00:00.000Z", value: 24623684 }, + { timestamp: "2018-03-25T00:00:00.000Z", value: 26530491 }, + { timestamp: "2018-03-26T00:00:00.000Z", value: 35445003 }, + { timestamp: "2018-03-27T00:00:00.000Z", value: 34250789 }, + { timestamp: "2018-03-28T00:00:00.000Z", value: 33423012 }, + { timestamp: "2018-03-29T00:00:00.000Z", value: 30744783 }, + { timestamp: "2018-03-30T00:00:00.000Z", value: 25825128 }, + { timestamp: "2018-03-31T00:00:00.000Z", value: 21244209 }, + { timestamp: "2018-04-01T00:00:00.000Z", value: 22576956 }, + { timestamp: "2018-04-02T00:00:00.000Z", value: 31957221 }, + { timestamp: "2018-04-03T00:00:00.000Z", value: 33841228 }, + { timestamp: "2018-04-04T00:00:00.000Z", value: 33554483 }, + { timestamp: "2018-04-05T00:00:00.000Z", value: 32383350 }, + { timestamp: "2018-04-06T00:00:00.000Z", value: 29494850 }, + { timestamp: "2018-04-07T00:00:00.000Z", value: 22815534 }, + { timestamp: "2018-04-08T00:00:00.000Z", value: 25557267 }, + { timestamp: "2018-04-09T00:00:00.000Z", value: 34858252 }, + { timestamp: "2018-04-10T00:00:00.000Z", value: 34750597 }, + { timestamp: "2018-04-11T00:00:00.000Z", value: 34717956 }, + { timestamp: "2018-04-12T00:00:00.000Z", value: 34132534 }, + { timestamp: "2018-04-13T00:00:00.000Z", value: 30762236 }, + { timestamp: "2018-04-14T00:00:00.000Z", value: 22504059 }, + { timestamp: "2018-04-15T00:00:00.000Z", value: 26149060 }, + { timestamp: "2018-04-16T00:00:00.000Z", value: 35250105 }, + ]; + + const result = await client.path("/timeseries/changepoint/detect").post({ + body: { + series, + granularity: "daily", + }, + }); + + if (isUnexpected(result)) { + throw result.body; + } + + assert.deepEqual(result.body.isChangePoint?.filter((p) => p).length, 2); + }); + + it("should get multivariate models", async () => { + const result = await client + .path("/multivariate/models") + .get({ queryParameters: { skip: 0, top: 10 } }); + + if (isUnexpected(result)) { + throw result.body; + } + + assert.lengthOf(result.body.models, 2); }); }); diff --git a/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/utils/recordedClient.ts b/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/utils/recordedClient.ts index 6cc58bc15e11..9f59503781fb 100644 --- a/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/utils/recordedClient.ts +++ b/sdk/anomalydetector/ai-anomaly-detector-rest/test/public/utils/recordedClient.ts @@ -2,15 +2,19 @@ // Licensed under the MIT license. import { Context } from "mocha"; -import { Recorder, RecorderStartOptions } from "@azure-tools/test-recorder"; +import { + Recorder, + RecorderStartOptions, + assertEnvironmentVariable, +} from "@azure-tools/test-recorder"; import "./env"; +import AnomalyDetector, { AnomalyDetectorRestClient } from "../../../src"; +import { AzureKeyCredential } from "@azure/core-auth"; const envSetupForPlayback: Record = { - ENDPOINT: "https://endpoint", - AZURE_CLIENT_ID: "azure_client_id", - AZURE_CLIENT_SECRET: "azure_client_secret", - AZURE_TENANT_ID: "88888888-8888-8888-8888-888888888888", - SUBSCRIPTION_ID: "azure_subscription_id", + ANOMALY_DETECTOR_ENDPOINT: "https://endpoint", + ANOMALY_DETECTOR_API_KEY: "fake_key", + ANOMALY_DETECTOR_DATA_URL: "https://endpoint-docs/data", }; const recorderEnvSetup: RecorderStartOptions = { @@ -27,3 +31,10 @@ export async function createRecorder(context: Context): Promise { await recorder.start(recorderEnvSetup); return recorder; } + +export async function createClient(recorder: Recorder): Promise { + const endpoint = assertEnvironmentVariable("ANOMALY_DETECTOR_ENDPOINT"); + const key = assertEnvironmentVariable("ANOMALY_DETECTOR_API_KEY"); + const credential = new AzureKeyCredential(key); + return AnomalyDetector(endpoint, credential, recorder.configureClientOptions({})); +} diff --git a/sdk/anomalydetector/ci.yml b/sdk/anomalydetector/ci.yml index 7bff3e08930f..4bdb480e0626 100644 --- a/sdk/anomalydetector/ci.yml +++ b/sdk/anomalydetector/ci.yml @@ -29,4 +29,6 @@ extends: ServiceDirectory: anomalydetector Artifacts: - name: azure-ai-anomaly-detector - safeName: aianomalydetector \ No newline at end of file + safeName: aianomalydetector + - name: azure-rest-ai-anomaly-detector + safeName: aianomalydetectorrest