From dcf3a6124714cba4099fd2c823df58e8d008eaf1 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 14:04:13 +0200 Subject: [PATCH 1/9] First draft --- apl/aggregation-function/sample-distinct.mdx | 159 +++++++++++++++++ apl/aggregation-function/sort-by.mdx | 163 ++++++++++++++++++ apl/apl-features.mdx | 5 + apl/scalar-functions/string-functions.mdx | 1 + .../string-functions/string-size.mdx | 156 +++++++++++++++++ apl/scalar-functions/time-series/overview.mdx | 2 + .../time-series/series-cos.mdx | 154 +++++++++++++++++ .../time-series/series-sin.mdx | 157 +++++++++++++++++ docs.json | 11 +- 9 files changed, 805 insertions(+), 3 deletions(-) create mode 100644 apl/aggregation-function/sample-distinct.mdx create mode 100644 apl/aggregation-function/sort-by.mdx create mode 100644 apl/scalar-functions/string-functions/string-size.mdx create mode 100644 apl/scalar-functions/time-series/series-cos.mdx create mode 100644 apl/scalar-functions/time-series/series-sin.mdx diff --git a/apl/aggregation-function/sample-distinct.mdx b/apl/aggregation-function/sample-distinct.mdx new file mode 100644 index 00000000..8c0f24e3 --- /dev/null +++ b/apl/aggregation-function/sample-distinct.mdx @@ -0,0 +1,159 @@ +--- +title: sample-distinct +description: 'This page explains how to use the sample-distinct operator in APL.' +--- + +The `sample-distinct` operator returns a random sample of distinct values from a dataset. You can use it when you want to quickly explore representative subsets of unique values without scanning the full dataset. This is useful in scenarios such as exploratory data analysis, performance testing, or when you need a small but diverse set of unique values for validation. + +Unlike `sample`, which randomly selects rows, `sample-distinct` ensures that only distinct values for the chosen column are included in the output. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +In Splunk SPL, you typically use the `sample` command to return a subset of events, but it does not guarantee uniqueness. To get distinct values, you combine commands like `dedup` and `sample`. In APL, `sample-distinct` combines both operations into one: it first deduplicates values and then samples from them. + + +```sql Splunk example +... | dedup uri | sample 5 +```` + +```kusto APL equivalent +['sample-http-logs'] +| sample-distinct 5 of uri +``` + + + + + + +In SQL, you use `SELECT DISTINCT` to get unique values and combine it with `TABLESAMPLE` or `ORDER BY RAND()` to get a random sample. In APL, `sample-distinct` does both in a single operator. + + +```sql SQL example +SELECT DISTINCT uri +FROM sample_http_logs +ORDER BY RAND() +LIMIT 5; +``` + +```kusto APL equivalent +['sample-http-logs'] +| sample-distinct 5 of uri +``` + + + + + + +## Usage + +### Syntax + +```kusto +T | sample-distinct NumberOfRows [of Column] +``` + +### Parameters + +| Parameter | Type | Description | +| -------------- | ------ | ------------------------------------------------------------------------------------------------------------ | +| `NumberOfRows` | int | The number of distinct values to return. | +| `Column` | string | (Optional) The column from which to select distinct values. If omitted, all columns are considered together. | + +### Returns + +A table with up to the specified number of distinct values. The rows are chosen randomly. + +## Use case examples + + + + +When you want to see a random subset of unique URLs that users accessed in your logs, you can use `sample-distinct`. + +**Query** + +```kusto +['sample-http-logs'] +| sample-distinct 5 of uri +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 5 of uri%22%7D) + +**Output** + +| uri | +| -------------- | +| /products/view | +| /cart/add | +| /checkout | +| /home | +| /login | + +This query returns 5 random distinct URLs (`uri`) from the HTTP logs, which helps you explore a representative subset of endpoints. + + + + +You can use `sample-distinct` to explore unique services in your distributed traces. + +**Query** + +```kusto +['otel-demo-traces'] +| sample-distinct 3 of ['service.name'] +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sample-distinct 3 of \['service.name']%22%7D) + +**Output** + +| service.name | +| --------------- | +| frontend | +| cartservice | +| checkoutservice | + +This query returns 3 random distinct services from your traces, helping you quickly see which parts of your system are represented. + + + + +You can use `sample-distinct` to view a random selection of unique status codes in security logs. + +**Query** + +```kusto +['sample-http-logs'] +| sample-distinct 4 of status +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 4 of status%22%7D) + +**Output** + +| status | +| ------ | +| 200 | +| 401 | +| 403 | +| 500 | + +This query helps you quickly identify a variety of HTTP status codes that appear in your logs without scanning the entire dataset. + + + + +## List of related operators + +* [sample](/apl/tabular-operators/sample-operator): Returns a random sample of rows but does not ensure uniqueness. +* [distinct](/apl/tabular-operators/distinct-operator): Returns all unique values without sampling. +* [take](/apl/tabular-operators/take-operator): Returns the first *n* rows from a dataset without randomization or uniqueness. +* [top](/apl/tabular-operators/top-operator): Returns the first *n* rows sorted by a specified expression. +* [summarize](/apl/tabular-operators/summarize-operator): Groups rows and computes aggregates, often used with `distinct` for deduplication. diff --git a/apl/aggregation-function/sort-by.mdx b/apl/aggregation-function/sort-by.mdx new file mode 100644 index 00000000..2b5dfcd4 --- /dev/null +++ b/apl/aggregation-function/sort-by.mdx @@ -0,0 +1,163 @@ +--- +title: sort-by +description: 'This page explains how to use the sort-by operator in APL.' +--- + +The `sort-by` operator in APL orders the rows of a dataset by one or more columns. You can specify whether each column is sorted in ascending or descending order. Use `sort-by` when you want to bring the most relevant rows to the top, such as the longest-running requests, the most recent log entries, or the highest error counts. Sorting helps you quickly identify trends and anomalies in your data. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +In Splunk SPL, you use the `sort` command to order results. In APL, the `sort-by` operator provides the same functionality, but you specify the order (ascending or descending) directly after each column. + + +```sql Splunk example +... | sort - req_duration_ms +```` + +```kusto APL equivalent +['sample-http-logs'] +| sort-by req_duration_ms desc +``` + + + + + + +In ANSI SQL, you use the `ORDER BY` clause to sort query results. In APL, you achieve the same result with the `sort-by` operator. The syntax is similar, but instead of keywords like `ORDER BY`, you use the operator with column names and order modifiers. + + +```sql SQL example +SELECT * +FROM sample_http_logs +ORDER BY req_duration_ms DESC +``` + +```kusto APL equivalent +['sample-http-logs'] +| sort-by req_duration_ms desc +``` + + + + + + +## Usage + +### Syntax + +```kusto +T | sort-by ColumnName [asc | desc] [, ColumnName [asc | desc] ...] +``` + +### Parameters + +* `T`: The input tabular dataset. +* `ColumnName`: The name of the column to sort by. +* `asc`: Optional keyword for ascending order. This is the default. +* `desc`: Optional keyword for descending order. + +### Returns + +The operator returns the input dataset, with rows reordered according to the specified columns and sort directions. + +## Use case examples + + + + +You want to find the slowest requests in your web server logs. + +**Query** + +```kusto +['sample-http-logs'] +| sort-by req_duration_ms desc +| take 5 +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sort-by req\_duration\_ms desc | take 5%22%7D) + +**Output** + +| \_time | req\_duration\_ms | id | status | uri | method | geo.city | geo.country | +| ------------------- | ----------------- | --- | ------ | ------------ | ------ | -------- | ----------- | +| 2024-05-21T12:31:22 | 920 | u45 | 200 | /checkout | POST | Berlin | DE | +| 2024-05-21T12:29:04 | 910 | u38 | 200 | /cart | GET | Paris | FR | +| 2024-05-21T12:28:44 | 905 | u22 | 500 | /product/123 | GET | London | GB | +| 2024-05-21T12:26:15 | 880 | u15 | 200 | /login | POST | Madrid | ES | +| 2024-05-21T12:25:32 | 870 | u09 | 404 | /unknown | GET | Rome | IT | + +This query sorts log entries by request duration in descending order and returns the five slowest requests. + + + + +You want to identify the longest spans across services to investigate potential bottlenecks. + +**Query** + +```kusto +['otel-demo-traces'] +| sort-by duration desc +| take 5 +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sort-by duration desc | take 5%22%7D) + +**Output** + +| \_time | duration | span\_id | trace\_id | service.name | kind | status\_code | +| ------------------- | -------- | -------- | --------- | --------------------- | -------- | ------------ | +| 2024-05-21T13:40:01 | 00:00:09 | s789 | t123 | checkoutservice | server | 200 | +| 2024-05-21T13:39:50 | 00:00:08 | s456 | t123 | productcatalogservice | client | 200 | +| 2024-05-21T13:39:32 | 00:00:08 | s321 | t789 | frontend | server | 500 | +| 2024-05-21T13:38:20 | 00:00:07 | s654 | t456 | cartservice | server | 200 | +| 2024-05-21T13:37:15 | 00:00:07 | s987 | t321 | frontendproxy | internal | 200 | + +This query sorts spans by duration in descending order and lists the five longest-running spans. + + + + +You want to find the most recent failed requests to monitor suspicious activity. + +**Query** + +```kusto +['sample-http-logs'] +| where status == '401' or status == '403' +| sort-by _time desc +| take 5 +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '401' or status == '403' | sort-by \_time desc | take 5%22%7D) + +**Output** + +| \_time | req\_duration\_ms | id | status | uri | method | geo.city | geo.country | +| ------------------- | ----------------- | --- | ------ | --------- | ------ | -------- | ----------- | +| 2024-05-21T12:35:10 | 220 | u19 | 403 | /admin | GET | Berlin | DE | +| 2024-05-21T12:34:48 | 150 | u27 | 401 | /checkout | POST | Paris | FR | +| 2024-05-21T12:33:20 | 300 | u45 | 401 | /login | POST | Rome | IT | +| 2024-05-21T12:32:44 | 180 | u33 | 403 | /settings | GET | Madrid | ES | +| 2024-05-21T12:31:55 | 210 | u11 | 401 | /cart | GET | London | GB | + +This query filters security-related failed requests, sorts them by timestamp in descending order, and shows the five most recent suspicious entries. + + + + +## List of related operators + +* [top](/apl/tabular-operators/top-operator): Returns the first N rows after sorting, which is more efficient if you need only a subset rather than the fully sorted dataset. +* [take](/apl/tabular-operators/take-operator): Returns the first N rows without sorting. Use this when order does not matter. +* [summarize](/apl/tabular-operators/summarize-operator): Aggregates and groups data before you sort by aggregated values. +* [order](/apl/tabular-operators/order-operator): An alias of `sort-by`. Both work identically, but `sort-by` is the preferred syntax. +* [project](/apl/tabular-operators/project-operator): Selects specific columns, often used together with `sort-by` to simplify result sets. diff --git a/apl/apl-features.mdx b/apl/apl-features.mdx index 4821e95c..06f9e793 100644 --- a/apl/apl-features.mdx +++ b/apl/apl-features.mdx @@ -28,6 +28,8 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Aggregation function | [percentileif](/apl/aggregation-function/percentileif) | Calculates the requested percentiles of the field for the rows where the predicate evaluates to true. | | Aggregation function | [percentiles_array](/apl/aggregation-function/percentiles-array) | Returns an array of numbers where each element is the value at the corresponding percentile. | | Aggregation function | [percentiles_arrayif](/apl/aggregation-function/percentiles-arrayif) | Returns an array of percentile values for the records that satisfy the condition. | +| Aggregation function | [sample-distinct](/apl/aggregation-function/sample-distinct) | Returns a random sample of distinct values. | +| Aggregation function | [sort-by](/apl/aggregation-function/sort-by) | Sorts the values in a group. | | Aggregation function | [rate](/apl/aggregation-function/rate) | Calculates the rate of values in a group per second. | | Aggregation function | [spotlight](/apl/aggregation-function/spotlight) | Compares a selected set of events against a baseline and surface the most significant differences. | | Aggregation function | [stdev](/apl/aggregation-function/stdev) | Calculates the standard deviation of an expression across the group. | @@ -218,6 +220,7 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | String function | [strcat_delim](/apl/scalar-functions/string-functions#strcat-delim) | Concatenates 2–64 arguments with a delimiter. | | String function | [strcat](/apl/scalar-functions/string-functions#strcat) | Concatenates 1–64 arguments. | | String function | [strcmp](/apl/scalar-functions/string-functions#strcmp) | Compares two strings. | +| String function | [string-size](/apl/scalar-functions/string-functions/string-size) | Returns the length, in characters, of the input string. | | String function | [strlen](/apl/scalar-functions/string-functions#strlen) | Returns the length of a string. | | String function | [strrep](/apl/scalar-functions/string-functions#strrep) | Repeats a string a given number of times. | | String function | [substring](/apl/scalar-functions/string-functions#substring) | Extracts a substring. | @@ -298,6 +301,8 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Time series function | [series_acos](/apl/scalar-functions/time-series/series-acos) | Returns the inverse cosine (arccos) of a series. | | Time series function | [series_asin](/apl/scalar-functions/time-series/series-asin) | Returns the inverse sine (arcsin) of a series. | | Time series function | [series_atan](/apl/scalar-functions/time-series/series-atan) | Returns the inverse tangent (arctan) of a series. | +| Time series function | [series_cos](/apl/scalar-functions/time-series/series-cos) | Returns the cosine of a series. | +| Time series function | [series_sin](/apl/scalar-functions/time-series/series-sin) | Returns the sine of a series. | | Type function | [iscc](/apl/scalar-functions/type-functions/iscc) | Checks whether a value is a valid credit card (CC) number. | | Type function | [isimei](/apl/scalar-functions/type-functions/isimei) | Checks whether a value is a valid International Mobile Equipment Identity (IMEI) number. | | Type function | [ismap](/apl/scalar-functions/type-functions/ismap) | Checks whether a value is of the `dynamic` type and represents a mapping. | diff --git a/apl/scalar-functions/string-functions.mdx b/apl/scalar-functions/string-functions.mdx index 8ef7dc38..fb19ae73 100644 --- a/apl/scalar-functions/string-functions.mdx +++ b/apl/scalar-functions/string-functions.mdx @@ -41,6 +41,7 @@ The table summarizes the string functions available in APL. | [strcat_delim](#strcat-delim) | Concatenates between 2 and 64 arguments, with delimiter, provided as first argument. | | [strcat](#strcat) | Concatenates between 1 and 64 arguments. | | [strcmp](#strcmp) | Compares two strings. | +| [string-size](/apl/scalar-functions/string-functions/string-size) | Returns the length, in characters, of the input string. | | [strlen](#strlen) | Returns the length, in characters, of the input string. | | [strrep](#strrep) | Repeats given string provided number of times (default = 1). | | [substring](#substring) | Extracts a substring from a source string. | diff --git a/apl/scalar-functions/string-functions/string-size.mdx b/apl/scalar-functions/string-functions/string-size.mdx new file mode 100644 index 00000000..378dc8d5 --- /dev/null +++ b/apl/scalar-functions/string-functions/string-size.mdx @@ -0,0 +1,156 @@ +--- +title: string_size +description: 'This page explains how to use the string_size function in APL.' +--- + +The `string_size` function returns the number of characters in a string. You use it when you want to measure the length of text fields such as user IDs, URLs, or status codes. This function is useful for detecting anomalies, filtering out unusually long values, or analyzing patterns in textual data. + +For example, you can use `string_size` to detect requests with excessively long URIs, identify outlier user IDs, or monitor payload lengths in traces. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +In Splunk SPL, you typically use the `len` function to calculate the number of characters in a string. In APL, you use `string_size`. + + +```sql Splunk example +... | eval uri_length=len(uri) +```` + +```kusto APL equivalent +['sample-http-logs'] +| extend uri_length = string_size(uri) +``` + + + + + + +In ANSI SQL, you use the `LENGTH` or `CHAR_LENGTH` function to calculate string length. In APL, the equivalent is `string_size`. + + +```sql SQL example +SELECT LENGTH(uri) AS uri_length +FROM sample_http_logs; +``` + +```kusto APL equivalent +['sample-http-logs'] +| extend uri_length = string_size(uri) +``` + + + + + + +## Usage + +### Syntax + +```kusto +string_size(source) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | -------- | ---------------------------- | +| `source` | `string` | The input string expression. | + +### Returns + +An integer representing the number of characters in the string. If the string is empty, the function returns `0`. + +## Use case examples + + + + +You can use `string_size` to detect unusually long URIs that might indicate an attempted exploit or malformed request. + +**Query** + +```kusto +['sample-http-logs'] +| extend uri_length = string_size(uri) +| where uri_length > 100 +| project _time, method, uri, uri_length, status +``` + +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20uri_length%20%3D%20string_size%28uri%29%20%7C%20where%20uri_length%20%3E%20100%20%7C%20project%20_time%2C%20method%2C%20uri%2C%20uri_length%2C%20status%22%7D) + +**Output** + +| \_time | method | uri | uri\_length | status | +| -------------------- | ------ | --------------------------------- | ----------- | ------ | +| 2025-09-11T10:01:45Z | GET | /search/products?q=... | 142 | 200 | +| 2025-09-11T10:02:13Z | POST | /checkout/submit/order/details... | 187 | 400 | + +This query finds all HTTP requests with URIs longer than 100 characters and lists their details. + + + + +You can measure the length of trace IDs or span IDs to ensure data consistency and identify malformed identifiers. + +**Query** + +```kusto +['otel-demo-traces'] +| extend trace_length = string_size(trace_id) +| summarize avg_length = avg(trace_length) by ['service.name'] +``` + +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20extend%20trace_length%20%3D%20string_size%28trace_id%29%20%7C%20summarize%20avg_length%20%3D%20avg%28trace_length%29%20by%20%5B'service.name'%5D%22%7D) + +**Output** + +| service.name | avg\_length | +| --------------- | ----------- | +| frontend | 32 | +| checkoutservice | 32 | +| loadgenerator | 31.8 | + +This query calculates the average trace ID length per service to verify identifier consistency across the system. + + + + +You can check for anomalous user IDs by looking at the length of the `id` field. Very short or very long IDs may signal invalid or suspicious activity. + +**Query** + +```kusto +['sample-http-logs'] +| extend id_length = string_size(id) +| where id_length < 5 or id_length > 20 +| project _time, id, id_length, status, geo.country +``` + +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20id_length%20%3D%20string_size%28id%29%20%7C%20where%20id_length%20%3C%205%20or%20id_length%20%3E%2020%20%7C%20project%20_time%2C%20id%2C%20id_length%2C%20status%2C%20geo.country%22%7D) + +**Output** + +| \_time | id | id\_length | status | geo.country | +| -------------------- | ----------------------------- | ---------- | ------ | ----------- | +| 2025-09-11T09:55:01Z | a12 | 3 | 401 | US | +| 2025-09-11T09:58:42Z | user\_long\_id\_example\_test | 24 | 200 | DE | + +This query detects requests with suspiciously short or long user IDs, which might indicate invalid credentials or malicious activity. + + + + +## List of related functions + +* [strlen](/apl/string-functions/strlen): An alias for `string_size`, provided for compatibility. Use `string_size` for consistency with APL naming conventions. +* [substring](/apl/string-functions/substring): Extracts a portion of a string. Use it when you need part of a string rather than its length. +* [indexof](/apl/string-functions/indexof): Returns the position of a substring in a string. Use it when you want to locate substrings rather than measure total length. +* [replace](/apl/string-functions/replace): Replaces part of a string with another string. Use it to modify strings instead of measuring them. +* [tostring](/apl/conversion-functions/tostring): Converts values to strings. Use it before `string_size` if your input is not already a string. diff --git a/apl/scalar-functions/time-series/overview.mdx b/apl/scalar-functions/time-series/overview.mdx index 4fffa2cb..9e8194bd 100644 --- a/apl/scalar-functions/time-series/overview.mdx +++ b/apl/scalar-functions/time-series/overview.mdx @@ -12,3 +12,5 @@ The table summarizes the time series functions available in APL. | [series_acos](/apl/scalar-functions/time-series/series-acos) | Returns the inverse cosine (arccos) of a series. | | [series_asin](/apl/scalar-functions/time-series/series-asin) | Returns the inverse sine (arcsin) of a series. | | [series_atan](/apl/scalar-functions/time-series/series-atan) | Returns the inverse tangent (arctan) of a series. | +| [series_cos](/apl/scalar-functions/time-series/series-cos) | Returns the cosine of a series. | +| [series_sin](/apl/scalar-functions/time-series/series-sin) | Returns the sine of a series. | diff --git a/apl/scalar-functions/time-series/series-cos.mdx b/apl/scalar-functions/time-series/series-cos.mdx new file mode 100644 index 00000000..2cf7f85d --- /dev/null +++ b/apl/scalar-functions/time-series/series-cos.mdx @@ -0,0 +1,154 @@ +--- +title: series_cos +description: 'This page explains how to use the series_cos function in APL.' +--- + +The `series_cos` function returns the cosine of each element in a numeric array. You can use it to apply trigonometric transformations across entire time series or vectorized data in one step. This function is useful when you want to analyze periodic patterns, normalize angles, or apply mathematical transformations to series data such as request durations, response times, or trace latencies. + +You often use `series_cos` together with other series functions like `series_sin` and `series_tan` to perform mathematical modeling, anomaly detection, or seasonality analysis in logs and telemetry data. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +In Splunk SPL, trigonometric functions like `cos` operate on single field values, not on arrays. To compute cosine across multiple values, you typically expand the values into events and then apply the `eval cos(field)` transformation. In APL, `series_cos` works natively on dynamic arrays, so you can directly transform an entire series in one call. + + +```sql Splunk example +... | eval cos_val=cos(angle) +```` + +```kusto APL equivalent +print arr=dynamic([0, 1.57, 3.14]) +| extend cos_arr=series_cos(arr) +``` + + + + + + +ANSI SQL does not provide direct support for array-wide trigonometric functions. The `COS()` function only works on single numeric values. To achieve array-like functionality, you usually need to unnest arrays and apply `COS()` row by row. In APL, `series_cos` eliminates this need by directly accepting an array and returning a transformed array. + + +```sql SQL example +SELECT COS(angle) AS cos_val +FROM Angles; +``` + +```kusto APL equivalent +print arr=dynamic([0, 1.57, 3.14]) +| extend cos_arr=series_cos(arr) +``` + + + + + + +## Usage + +### Syntax + +```kusto +series_cos(array) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | -------------------------- | --------------------------- | +| `array` | dynamic (array of numbers) | An array of numeric values. | + +### Returns + +A dynamic array where each element is the cosine of the corresponding input element. + +## Use case examples + + + + +You want to model periodic patterns in request durations by applying the cosine function to the values. This is useful if you want to normalize cyclical metrics for further analysis. + +**Query** + +```kusto +['sample-http-logs'] +| summarize durations=make_list(req_duration_ms) by id +| extend cos_durations=series_cos(durations) +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations=make\_list(req\_duration\_ms) by id | extend cos\_durations=series\_cos(durations)%22%7D) + +**Output** + +| id | durations | cos\_durations | +| -- | ---------------- | ------------------------ | +| u1 | \[120, 300, 450] | \[0.814, -0.990, -0.737] | +| u2 | \[50, 250, 400] | \[0.965, -0.801, -0.966] | + +This query collects request durations per user ID and applies the cosine transformation to the entire array. + + + + +You want to apply trigonometric transformations to span durations to explore cyclical behavior in distributed traces. + +**Query** + +```kusto +['otel-demo-traces'] +| summarize spans=make_list(duration) by ['service.name'] +| extend cos_spans=series_cos(spans) +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans=make\_list(duration) by \['service.name'] | extend cos\_spans=series\_cos(spans)%22%7D) + +**Output** + +| service.name | spans | cos\_spans | +| --------------- | --------------------- | ----------------- | +| frontend | \[00:00:01, 00:00:03] | \[0.540, -0.990] | +| checkoutservice | \[00:00:02, 00:00:04] | \[-0.416, -0.653] | + +This query groups spans by service and computes the cosine for each span duration, which can be used in advanced mathematical modeling of latency patterns. + + + + +You want to explore whether cosine transformations reveal patterns in request durations for suspicious traffic sources. + +**Query** + +```kusto +['sample-http-logs'] +| where status == '403' +| summarize blocked_durations=make_list(req_duration_ms) by ['geo.country'] +| extend cos_blocked=series_cos(blocked_durations) +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize blocked\_durations=make\_list(req\_duration\_ms) by \['geo.country'] | extend cos\_blocked=series\_cos(blocked\_durations)%22%7D) + +**Output** + +| geo.country | blocked\_durations | cos\_blocked | +| ----------- | ------------------ | ------------------------ | +| US | \[200, 400, 600] | \[-0.416, -0.653, 0.960] | +| DE | \[100, 250, 500] | \[0.540, -0.801, 0.284] | + +This query applies the cosine function to blocked request durations grouped by country, which can help highlight periodic access attempts from malicious sources. + + + + +## List of related functions + +* [series\_sin](/apl/array-functions/series_sin): Returns the sine of each element in an array. Use it when analyzing cyclical data with a phase shift. +* [series\_tan](/apl/array-functions/series_tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. +* [series\_exp](/apl/array-functions/series_exp): Applies the exponential function to each element in an array. Use it for exponential growth or decay modeling. +* [series\_log](/apl/array-functions/series_log): Returns the natural logarithm of each element in an array. Use it for logarithmic transformations of series data. +* [series\_abs](/apl/array-functions/series_abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. diff --git a/apl/scalar-functions/time-series/series-sin.mdx b/apl/scalar-functions/time-series/series-sin.mdx new file mode 100644 index 00000000..d20441f7 --- /dev/null +++ b/apl/scalar-functions/time-series/series-sin.mdx @@ -0,0 +1,157 @@ +--- +title: series_sin +description: 'This page explains how to use the series_sin function in APL.' +--- + +The `series_sin` function in APL returns the sine of each element in a numeric array. It applies the mathematical sine function element by element, producing a new array of the same length. + +You use `series_sin` when you want to transform numeric sequences into their trigonometric equivalents. This is useful for signal processing, data transformations, or preparing time series data for statistical and mathematical analysis. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +Splunk SPL does not provide a direct equivalent to `series_sin` for arrays. Instead, you typically use the `eval` command with the `sin()` function to compute the sine of a single numeric value. In APL, `series_sin` applies `sin()` across an array in one step. + + +```sql Splunk example +... | eval sin_val=sin(duration) +```` + +```kusto APL equivalent +datatable(arr: dynamic) +[ + dynamic([0, 1.57, 3.14]) +] +| extend sin_values = series_sin(arr) +``` + + + + + + +ANSI SQL provides the `SIN()` function, but it operates on single values rather than arrays. In APL, `series_sin` is vectorized and works directly on arrays without requiring iteration. + + +```sql SQL example +SELECT SIN(duration) AS sin_val +FROM traces; +``` + +```kusto APL equivalent +datatable(arr: dynamic) +[ + dynamic([0, 1.57, 3.14]) +] +| extend sin_values = series_sin(arr) +``` + + + + + + +## Usage + +### Syntax + +```kusto +series_sin(arr) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------- | --------------------------- | +| `arr` | dynamic | An array of numeric values. | + +### Returns + +A dynamic array where each element is the sine of the corresponding input element. + +## Use case examples + + + + +You can use `series_sin` to transform request durations into trigonometric values for advanced analysis, such as periodicity detection. + +**Query** + +```kusto +['sample-http-logs'] +| summarize arr = make_list(req_duration_ms, 10) +| extend sin_arr = series_sin(arr) +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize arr = make\_list(req\_duration\_ms, 10) | extend sin\_arr = series\_sin(arr)%22%7D) + +**Output** + +| arr | sin\_arr | +| --------------------- | ---------------------------- | +| \[120, 250, 500, 750] | \[−0.58, −0.97, −0.52, 0.94] | + +This query collects a sample of request durations and applies `series_sin` to generate a transformed series for analysis. + + + + +You can use `series_sin` to apply trigonometric transformation to span durations for modeling or feature extraction. + +**Query** + +```kusto +['otel-demo-traces'] +| summarize arr = make_list(toint(duration), 10) by ['service.name'] +| extend sin_arr = series_sin(arr) +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize arr = make\_list(toint(duration), 10) by \['service.name'] | extend sin\_arr = series\_sin(arr)%22%7D) + +**Output** + +| service.name | arr | sin\_arr | +| ------------ | ---------------- | --------------------- | +| frontend | \[200, 400, 600] | \[0.91, −0.73, −0.28] | + +This query groups spans by service, aggregates durations into arrays, and transforms them using `series_sin`. + + + + +You can use `series_sin` to apply mathematical transformations to response times in security-related traffic to detect unusual patterns. + +**Query** + +```kusto +['sample-http-logs'] +| where status == '403' +| summarize arr = make_list(req_duration_ms, 10) by geo.country +| extend sin_arr = series_sin(arr) +``` + +\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize arr = make\_list(req\_duration\_ms, 10) by geo.country | extend sin\_arr = series\_sin(arr)%22%7D) + +**Output** + +| geo.country | arr | sin\_arr | +| ----------- | ---------------- | ---------------------- | +| US | \[180, 360, 540] | \[−0.80, −0.99, −0.84] | + +This query filters failed requests (`403`) by country, aggregates durations, and applies `series_sin` to identify periodic anomalies. + + + + +## List of related functions + +* [series\_cos](/apl/array-functions/series_cos): Returns the cosine of each array element. Use when you want the cosine instead of sine. +* [series\_tan](/apl/array-functions/series_tan): Returns the tangent of each array element. Use when analyzing angular relationships. +* [series\_exp](/apl/array-functions/series_exp): Returns the exponential of each array element. Useful for growth and scaling analysis. +* [series\_log](/apl/array-functions/series_log): Returns the natural logarithm of each array element. Useful for reducing skew in data distributions. +* [series\_abs](/apl/array-functions/series_abs): Returns the absolute value of each array element. Use when you want non-negative transformations. diff --git a/docs.json b/docs.json index b07a2d6e..00dc0d10 100644 --- a/docs.json +++ b/docs.json @@ -354,10 +354,11 @@ "apl/scalar-functions/string-functions/parse-path", "apl/scalar-functions/string-functions/quote", "apl/scalar-functions/string-functions/regex-quote", + "apl/scalar-functions/string-functions/string-size", "apl/scalar-functions/string-functions/translate", + "apl/scalar-functions/string-functions/trim-space", "apl/scalar-functions/string-functions/unicode-codepoints-from-string", - "apl/scalar-functions/string-functions/unicode-codepoints-to-string", - "apl/scalar-functions/string-functions/trim-space" + "apl/scalar-functions/string-functions/unicode-codepoints-to-string" ] }, "apl/scalar-functions/sql-functions", @@ -368,7 +369,9 @@ "apl/scalar-functions/time-series/series-abs", "apl/scalar-functions/time-series/series-acos", "apl/scalar-functions/time-series/series-asin", - "apl/scalar-functions/time-series/series-atan" + "apl/scalar-functions/time-series/series-atan", + "apl/scalar-functions/time-series/series-cos", + "apl/scalar-functions/time-series/series-sin" ] }, { @@ -411,6 +414,8 @@ "apl/aggregation-function/percentiles-array", "apl/aggregation-function/percentiles-arrayif", "apl/aggregation-function/rate", + "apl/aggregation-function/sample-distinct", + "apl/aggregation-function/sort-by", "apl/aggregation-function/spotlight", "apl/aggregation-function/stdev", "apl/aggregation-function/stdevif", From 42b82484068baf4aba6a034df7f4ae528e3926a9 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 14:19:06 +0200 Subject: [PATCH 2/9] Fixes --- apl/aggregation-function/sample-distinct.mdx | 16 ++++----- apl/aggregation-function/sort-by.mdx | 30 ++++++++-------- .../string-functions/string-size.mdx | 18 +++++----- .../time-series/series-cos.mdx | 34 +++++++++---------- .../time-series/series-sin.mdx | 28 +++++++-------- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/apl/aggregation-function/sample-distinct.mdx b/apl/aggregation-function/sample-distinct.mdx index 8c0f24e3..e7512878 100644 --- a/apl/aggregation-function/sample-distinct.mdx +++ b/apl/aggregation-function/sample-distinct.mdx @@ -84,7 +84,7 @@ When you want to see a random subset of unique URLs that users accessed in your | sample-distinct 5 of uri ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 5 of uri%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 5 of uri%22%7D) **Output** @@ -110,7 +110,7 @@ You can use `sample-distinct` to explore unique services in your distributed tra | sample-distinct 3 of ['service.name'] ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sample-distinct 3 of \['service.name']%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sample-distinct 3 of ['service.name']%22%7D) **Output** @@ -134,7 +134,7 @@ You can use `sample-distinct` to view a random selection of unique status codes | sample-distinct 4 of status ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 4 of status%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 4 of status%22%7D) **Output** @@ -152,8 +152,8 @@ This query helps you quickly identify a variety of HTTP status codes that appear ## List of related operators -* [sample](/apl/tabular-operators/sample-operator): Returns a random sample of rows but does not ensure uniqueness. -* [distinct](/apl/tabular-operators/distinct-operator): Returns all unique values without sampling. -* [take](/apl/tabular-operators/take-operator): Returns the first *n* rows from a dataset without randomization or uniqueness. -* [top](/apl/tabular-operators/top-operator): Returns the first *n* rows sorted by a specified expression. -* [summarize](/apl/tabular-operators/summarize-operator): Groups rows and computes aggregates, often used with `distinct` for deduplication. +- [sample](/apl/tabular-operators/sample-operator): Returns a random sample of rows but does not ensure uniqueness. +- [distinct](/apl/tabular-operators/distinct-operator): Returns all unique values without sampling. +- [take](/apl/tabular-operators/take-operator): Returns the first *n* rows from a dataset without randomization or uniqueness. +- [top](/apl/tabular-operators/top-operator): Returns the first *n* rows sorted by a specified expression. +- [summarize](/apl/tabular-operators/summarize-operator): Groups rows and computes aggregates, often used with `distinct` for deduplication. diff --git a/apl/aggregation-function/sort-by.mdx b/apl/aggregation-function/sort-by.mdx index 2b5dfcd4..a5f70978 100644 --- a/apl/aggregation-function/sort-by.mdx +++ b/apl/aggregation-function/sort-by.mdx @@ -58,10 +58,10 @@ T | sort-by ColumnName [asc | desc] [, ColumnName [asc | desc] ...] ### Parameters -* `T`: The input tabular dataset. -* `ColumnName`: The name of the column to sort by. -* `asc`: Optional keyword for ascending order. This is the default. -* `desc`: Optional keyword for descending order. +- `T`: The input tabular dataset. +- `ColumnName`: The name of the column to sort by. +- `asc`: Optional keyword for ascending order. This is the default. +- `desc`: Optional keyword for descending order. ### Returns @@ -82,11 +82,11 @@ You want to find the slowest requests in your web server logs. | take 5 ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sort-by req\_duration\_ms desc | take 5%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sort-by req_duration_ms desc | take 5%22%7D) **Output** -| \_time | req\_duration\_ms | id | status | uri | method | geo.city | geo.country | +| _time | req_duration_ms | id | status | uri | method | geo.city | geo.country | | ------------------- | ----------------- | --- | ------ | ------------ | ------ | -------- | ----------- | | 2024-05-21T12:31:22 | 920 | u45 | 200 | /checkout | POST | Berlin | DE | | 2024-05-21T12:29:04 | 910 | u38 | 200 | /cart | GET | Paris | FR | @@ -109,11 +109,11 @@ You want to identify the longest spans across services to investigate potential | take 5 ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sort-by duration desc | take 5%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sort-by duration desc | take 5%22%7D) **Output** -| \_time | duration | span\_id | trace\_id | service.name | kind | status\_code | +| _time | duration | span_id | trace_id | service.name | kind | status_code | | ------------------- | -------- | -------- | --------- | --------------------- | -------- | ------------ | | 2024-05-21T13:40:01 | 00:00:09 | s789 | t123 | checkoutservice | server | 200 | | 2024-05-21T13:39:50 | 00:00:08 | s456 | t123 | productcatalogservice | client | 200 | @@ -137,11 +137,11 @@ You want to find the most recent failed requests to monitor suspicious activity. | take 5 ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '401' or status == '403' | sort-by \_time desc | take 5%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '401' or status == '403' | sort-by _time desc | take 5%22%7D) **Output** -| \_time | req\_duration\_ms | id | status | uri | method | geo.city | geo.country | +| _time | req_duration_ms | id | status | uri | method | geo.city | geo.country | | ------------------- | ----------------- | --- | ------ | --------- | ------ | -------- | ----------- | | 2024-05-21T12:35:10 | 220 | u19 | 403 | /admin | GET | Berlin | DE | | 2024-05-21T12:34:48 | 150 | u27 | 401 | /checkout | POST | Paris | FR | @@ -156,8 +156,8 @@ This query filters security-related failed requests, sorts them by timestamp in ## List of related operators -* [top](/apl/tabular-operators/top-operator): Returns the first N rows after sorting, which is more efficient if you need only a subset rather than the fully sorted dataset. -* [take](/apl/tabular-operators/take-operator): Returns the first N rows without sorting. Use this when order does not matter. -* [summarize](/apl/tabular-operators/summarize-operator): Aggregates and groups data before you sort by aggregated values. -* [order](/apl/tabular-operators/order-operator): An alias of `sort-by`. Both work identically, but `sort-by` is the preferred syntax. -* [project](/apl/tabular-operators/project-operator): Selects specific columns, often used together with `sort-by` to simplify result sets. +- [top](/apl/tabular-operators/top-operator): Returns the first N rows after sorting, which is more efficient if you need only a subset rather than the fully sorted dataset. +- [take](/apl/tabular-operators/take-operator): Returns the first N rows without sorting. Use this when order does not matter. +- [summarize](/apl/tabular-operators/summarize-operator): Aggregates and groups data before you sort by aggregated values. +- [order](/apl/tabular-operators/order-operator): An alias of `sort-by`. Both work identically, but `sort-by` is the preferred syntax. +- [project](/apl/tabular-operators/project-operator): Selects specific columns, often used together with `sort-by` to simplify result sets. diff --git a/apl/scalar-functions/string-functions/string-size.mdx b/apl/scalar-functions/string-functions/string-size.mdx index 378dc8d5..cdcd9fd7 100644 --- a/apl/scalar-functions/string-functions/string-size.mdx +++ b/apl/scalar-functions/string-functions/string-size.mdx @@ -87,7 +87,7 @@ You can use `string_size` to detect unusually long URIs that might indicate an a **Output** -| \_time | method | uri | uri\_length | status | +| _time | method | uri | uri_length | status | | -------------------- | ------ | --------------------------------- | ----------- | ------ | | 2025-09-11T10:01:45Z | GET | /search/products?q=... | 142 | 200 | | 2025-09-11T10:02:13Z | POST | /checkout/submit/order/details... | 187 | 400 | @@ -111,7 +111,7 @@ You can measure the length of trace IDs or span IDs to ensure data consistency a **Output** -| service.name | avg\_length | +| service.name | avg_length | | --------------- | ----------- | | frontend | 32 | | checkoutservice | 32 | @@ -137,10 +137,10 @@ You can check for anomalous user IDs by looking at the length of the `id` field. **Output** -| \_time | id | id\_length | status | geo.country | +| _time | id | id_length | status | geo.country | | -------------------- | ----------------------------- | ---------- | ------ | ----------- | | 2025-09-11T09:55:01Z | a12 | 3 | 401 | US | -| 2025-09-11T09:58:42Z | user\_long\_id\_example\_test | 24 | 200 | DE | +| 2025-09-11T09:58:42Z | user_long_id_example_test | 24 | 200 | DE | This query detects requests with suspiciously short or long user IDs, which might indicate invalid credentials or malicious activity. @@ -149,8 +149,8 @@ This query detects requests with suspiciously short or long user IDs, which migh ## List of related functions -* [strlen](/apl/string-functions/strlen): An alias for `string_size`, provided for compatibility. Use `string_size` for consistency with APL naming conventions. -* [substring](/apl/string-functions/substring): Extracts a portion of a string. Use it when you need part of a string rather than its length. -* [indexof](/apl/string-functions/indexof): Returns the position of a substring in a string. Use it when you want to locate substrings rather than measure total length. -* [replace](/apl/string-functions/replace): Replaces part of a string with another string. Use it to modify strings instead of measuring them. -* [tostring](/apl/conversion-functions/tostring): Converts values to strings. Use it before `string_size` if your input is not already a string. +- [strlen](/apl/string-functions/strlen): An alias for `string_size`, provided for compatibility. Use `string_size` for consistency with APL naming conventions. +- [substring](/apl/string-functions/substring): Extracts a portion of a string. Use it when you need part of a string rather than its length. +- [indexof](/apl/string-functions/indexof): Returns the position of a substring in a string. Use it when you want to locate substrings rather than measure total length. +- [replace](/apl/string-functions/replace): Replaces part of a string with another string. Use it to modify strings instead of measuring them. +- [tostring](/apl/conversion-functions/tostring): Converts values to strings. Use it before `string_size` if your input is not already a string. diff --git a/apl/scalar-functions/time-series/series-cos.mdx b/apl/scalar-functions/time-series/series-cos.mdx index 2cf7f85d..6e00cebb 100644 --- a/apl/scalar-functions/time-series/series-cos.mdx +++ b/apl/scalar-functions/time-series/series-cos.mdx @@ -82,14 +82,14 @@ You want to model periodic patterns in request durations by applying the cosine | extend cos_durations=series_cos(durations) ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations=make\_list(req\_duration\_ms) by id | extend cos\_durations=series\_cos(durations)%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations=make_list(req_duration_ms) by id | extend cos_durations=series_cos(durations)%22%7D) **Output** -| id | durations | cos\_durations | +| id | durations | cos_durations | | -- | ---------------- | ------------------------ | -| u1 | \[120, 300, 450] | \[0.814, -0.990, -0.737] | -| u2 | \[50, 250, 400] | \[0.965, -0.801, -0.966] | +| u1 | [120, 300, 450] | [0.814, -0.990, -0.737] | +| u2 | [50, 250, 400] | [0.965, -0.801, -0.966] | This query collects request durations per user ID and applies the cosine transformation to the entire array. @@ -106,14 +106,14 @@ You want to apply trigonometric transformations to span durations to explore cyc | extend cos_spans=series_cos(spans) ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans=make\_list(duration) by \['service.name'] | extend cos\_spans=series\_cos(spans)%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans=make_list(duration) by ['service.name'] | extend cos_spans=series_cos(spans)%22%7D) **Output** -| service.name | spans | cos\_spans | +| service.name | spans | cos_spans | | --------------- | --------------------- | ----------------- | -| frontend | \[00:00:01, 00:00:03] | \[0.540, -0.990] | -| checkoutservice | \[00:00:02, 00:00:04] | \[-0.416, -0.653] | +| frontend | [00:00:01, 00:00:03] | [0.540, -0.990] | +| checkoutservice | [00:00:02, 00:00:04] | [-0.416, -0.653] | This query groups spans by service and computes the cosine for each span duration, which can be used in advanced mathematical modeling of latency patterns. @@ -131,14 +131,14 @@ You want to explore whether cosine transformations reveal patterns in request du | extend cos_blocked=series_cos(blocked_durations) ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize blocked\_durations=make\_list(req\_duration\_ms) by \['geo.country'] | extend cos\_blocked=series\_cos(blocked\_durations)%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize blocked_durations=make_list(req_duration_ms) by ['geo.country'] | extend cos_blocked=series_cos(blocked_durations)%22%7D) **Output** -| geo.country | blocked\_durations | cos\_blocked | +| geo.country | blocked_durations | cos_blocked | | ----------- | ------------------ | ------------------------ | -| US | \[200, 400, 600] | \[-0.416, -0.653, 0.960] | -| DE | \[100, 250, 500] | \[0.540, -0.801, 0.284] | +| US | [200, 400, 600] | [-0.416, -0.653, 0.960] | +| DE | [100, 250, 500] | [0.540, -0.801, 0.284] | This query applies the cosine function to blocked request durations grouped by country, which can help highlight periodic access attempts from malicious sources. @@ -147,8 +147,8 @@ This query applies the cosine function to blocked request durations grouped by c ## List of related functions -* [series\_sin](/apl/array-functions/series_sin): Returns the sine of each element in an array. Use it when analyzing cyclical data with a phase shift. -* [series\_tan](/apl/array-functions/series_tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. -* [series\_exp](/apl/array-functions/series_exp): Applies the exponential function to each element in an array. Use it for exponential growth or decay modeling. -* [series\_log](/apl/array-functions/series_log): Returns the natural logarithm of each element in an array. Use it for logarithmic transformations of series data. -* [series\_abs](/apl/array-functions/series_abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. +- [series_sin](/apl/array-functions/series_sin): Returns the sine of each element in an array. Use it when analyzing cyclical data with a phase shift. +- [series_tan](/apl/array-functions/series_tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. +- [series_exp](/apl/array-functions/series_exp): Applies the exponential function to each element in an array. Use it for exponential growth or decay modeling. +- [series_log](/apl/array-functions/series_log): Returns the natural logarithm of each element in an array. Use it for logarithmic transformations of series data. +- [series_abs](/apl/array-functions/series_abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. diff --git a/apl/scalar-functions/time-series/series-sin.mdx b/apl/scalar-functions/time-series/series-sin.mdx index d20441f7..370c42fc 100644 --- a/apl/scalar-functions/time-series/series-sin.mdx +++ b/apl/scalar-functions/time-series/series-sin.mdx @@ -88,13 +88,13 @@ You can use `series_sin` to transform request durations into trigonometric value | extend sin_arr = series_sin(arr) ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize arr = make\_list(req\_duration\_ms, 10) | extend sin\_arr = series\_sin(arr)%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize arr = make_list(req_duration_ms, 10) | extend sin_arr = series_sin(arr)%22%7D) **Output** -| arr | sin\_arr | +| arr | sin_arr | | --------------------- | ---------------------------- | -| \[120, 250, 500, 750] | \[−0.58, −0.97, −0.52, 0.94] | +| [120, 250, 500, 750] | [−0.58, −0.97, −0.52, 0.94] | This query collects a sample of request durations and applies `series_sin` to generate a transformed series for analysis. @@ -111,13 +111,13 @@ You can use `series_sin` to apply trigonometric transformation to span durations | extend sin_arr = series_sin(arr) ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize arr = make\_list(toint(duration), 10) by \['service.name'] | extend sin\_arr = series\_sin(arr)%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize arr = make_list(toint(duration), 10) by ['service.name'] | extend sin_arr = series_sin(arr)%22%7D) **Output** -| service.name | arr | sin\_arr | +| service.name | arr | sin_arr | | ------------ | ---------------- | --------------------- | -| frontend | \[200, 400, 600] | \[0.91, −0.73, −0.28] | +| frontend | [200, 400, 600] | [0.91, −0.73, −0.28] | This query groups spans by service, aggregates durations into arrays, and transforms them using `series_sin`. @@ -135,13 +135,13 @@ You can use `series_sin` to apply mathematical transformations to response times | extend sin_arr = series_sin(arr) ``` -\[Run in Playground]\([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22\['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize arr = make\_list(req\_duration\_ms, 10) by geo.country | extend sin\_arr = series\_sin(arr)%22%7D) +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize arr = make_list(req_duration_ms, 10) by geo.country | extend sin_arr = series_sin(arr)%22%7D) **Output** -| geo.country | arr | sin\_arr | +| geo.country | arr | sin_arr | | ----------- | ---------------- | ---------------------- | -| US | \[180, 360, 540] | \[−0.80, −0.99, −0.84] | +| US | [180, 360, 540] | [−0.80, −0.99, −0.84] | This query filters failed requests (`403`) by country, aggregates durations, and applies `series_sin` to identify periodic anomalies. @@ -150,8 +150,8 @@ This query filters failed requests (`403`) by country, aggregates durations, and ## List of related functions -* [series\_cos](/apl/array-functions/series_cos): Returns the cosine of each array element. Use when you want the cosine instead of sine. -* [series\_tan](/apl/array-functions/series_tan): Returns the tangent of each array element. Use when analyzing angular relationships. -* [series\_exp](/apl/array-functions/series_exp): Returns the exponential of each array element. Useful for growth and scaling analysis. -* [series\_log](/apl/array-functions/series_log): Returns the natural logarithm of each array element. Useful for reducing skew in data distributions. -* [series\_abs](/apl/array-functions/series_abs): Returns the absolute value of each array element. Use when you want non-negative transformations. +- [series_cos](/apl/array-functions/series_cos): Returns the cosine of each array element. Use when you want the cosine instead of sine. +- [series_tan](/apl/array-functions/series_tan): Returns the tangent of each array element. Use when analyzing angular relationships. +- [series_exp](/apl/array-functions/series_exp): Returns the exponential of each array element. Useful for growth and scaling analysis. +- [series_log](/apl/array-functions/series_log): Returns the natural logarithm of each array element. Useful for reducing skew in data distributions. +- [series_abs](/apl/array-functions/series_abs): Returns the absolute value of each array element. Use when you want non-negative transformations. From c9e870c563ef4dfebd1f2b26fcd100e565ec7b45 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 14:34:39 +0200 Subject: [PATCH 3/9] Fix sort-by --- apl/aggregation-function/sort-by.mdx | 163 ------------------ apl/apl-features.mdx | 4 +- apl/scalar-functions/time-series/overview.mdx | 1 + .../time-series/series-tan.mdx | 160 +++++++++++++++++ apl/tabular-operators/overview.mdx | 1 + .../sample-distinct.mdx | 6 +- docs.json | 6 +- 7 files changed, 170 insertions(+), 171 deletions(-) delete mode 100644 apl/aggregation-function/sort-by.mdx create mode 100644 apl/scalar-functions/time-series/series-tan.mdx rename apl/{aggregation-function => tabular-operators}/sample-distinct.mdx (94%) diff --git a/apl/aggregation-function/sort-by.mdx b/apl/aggregation-function/sort-by.mdx deleted file mode 100644 index a5f70978..00000000 --- a/apl/aggregation-function/sort-by.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: sort-by -description: 'This page explains how to use the sort-by operator in APL.' ---- - -The `sort-by` operator in APL orders the rows of a dataset by one or more columns. You can specify whether each column is sorted in ascending or descending order. Use `sort-by` when you want to bring the most relevant rows to the top, such as the longest-running requests, the most recent log entries, or the highest error counts. Sorting helps you quickly identify trends and anomalies in your data. - -## For users of other query languages - -If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. - - - - -In Splunk SPL, you use the `sort` command to order results. In APL, the `sort-by` operator provides the same functionality, but you specify the order (ascending or descending) directly after each column. - - -```sql Splunk example -... | sort - req_duration_ms -```` - -```kusto APL equivalent -['sample-http-logs'] -| sort-by req_duration_ms desc -``` - - - - - - -In ANSI SQL, you use the `ORDER BY` clause to sort query results. In APL, you achieve the same result with the `sort-by` operator. The syntax is similar, but instead of keywords like `ORDER BY`, you use the operator with column names and order modifiers. - - -```sql SQL example -SELECT * -FROM sample_http_logs -ORDER BY req_duration_ms DESC -``` - -```kusto APL equivalent -['sample-http-logs'] -| sort-by req_duration_ms desc -``` - - - - - - -## Usage - -### Syntax - -```kusto -T | sort-by ColumnName [asc | desc] [, ColumnName [asc | desc] ...] -``` - -### Parameters - -- `T`: The input tabular dataset. -- `ColumnName`: The name of the column to sort by. -- `asc`: Optional keyword for ascending order. This is the default. -- `desc`: Optional keyword for descending order. - -### Returns - -The operator returns the input dataset, with rows reordered according to the specified columns and sort directions. - -## Use case examples - - - - -You want to find the slowest requests in your web server logs. - -**Query** - -```kusto -['sample-http-logs'] -| sort-by req_duration_ms desc -| take 5 -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sort-by req_duration_ms desc | take 5%22%7D) - -**Output** - -| _time | req_duration_ms | id | status | uri | method | geo.city | geo.country | -| ------------------- | ----------------- | --- | ------ | ------------ | ------ | -------- | ----------- | -| 2024-05-21T12:31:22 | 920 | u45 | 200 | /checkout | POST | Berlin | DE | -| 2024-05-21T12:29:04 | 910 | u38 | 200 | /cart | GET | Paris | FR | -| 2024-05-21T12:28:44 | 905 | u22 | 500 | /product/123 | GET | London | GB | -| 2024-05-21T12:26:15 | 880 | u15 | 200 | /login | POST | Madrid | ES | -| 2024-05-21T12:25:32 | 870 | u09 | 404 | /unknown | GET | Rome | IT | - -This query sorts log entries by request duration in descending order and returns the five slowest requests. - - - - -You want to identify the longest spans across services to investigate potential bottlenecks. - -**Query** - -```kusto -['otel-demo-traces'] -| sort-by duration desc -| take 5 -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sort-by duration desc | take 5%22%7D) - -**Output** - -| _time | duration | span_id | trace_id | service.name | kind | status_code | -| ------------------- | -------- | -------- | --------- | --------------------- | -------- | ------------ | -| 2024-05-21T13:40:01 | 00:00:09 | s789 | t123 | checkoutservice | server | 200 | -| 2024-05-21T13:39:50 | 00:00:08 | s456 | t123 | productcatalogservice | client | 200 | -| 2024-05-21T13:39:32 | 00:00:08 | s321 | t789 | frontend | server | 500 | -| 2024-05-21T13:38:20 | 00:00:07 | s654 | t456 | cartservice | server | 200 | -| 2024-05-21T13:37:15 | 00:00:07 | s987 | t321 | frontendproxy | internal | 200 | - -This query sorts spans by duration in descending order and lists the five longest-running spans. - - - - -You want to find the most recent failed requests to monitor suspicious activity. - -**Query** - -```kusto -['sample-http-logs'] -| where status == '401' or status == '403' -| sort-by _time desc -| take 5 -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '401' or status == '403' | sort-by _time desc | take 5%22%7D) - -**Output** - -| _time | req_duration_ms | id | status | uri | method | geo.city | geo.country | -| ------------------- | ----------------- | --- | ------ | --------- | ------ | -------- | ----------- | -| 2024-05-21T12:35:10 | 220 | u19 | 403 | /admin | GET | Berlin | DE | -| 2024-05-21T12:34:48 | 150 | u27 | 401 | /checkout | POST | Paris | FR | -| 2024-05-21T12:33:20 | 300 | u45 | 401 | /login | POST | Rome | IT | -| 2024-05-21T12:32:44 | 180 | u33 | 403 | /settings | GET | Madrid | ES | -| 2024-05-21T12:31:55 | 210 | u11 | 401 | /cart | GET | London | GB | - -This query filters security-related failed requests, sorts them by timestamp in descending order, and shows the five most recent suspicious entries. - - - - -## List of related operators - -- [top](/apl/tabular-operators/top-operator): Returns the first N rows after sorting, which is more efficient if you need only a subset rather than the fully sorted dataset. -- [take](/apl/tabular-operators/take-operator): Returns the first N rows without sorting. Use this when order does not matter. -- [summarize](/apl/tabular-operators/summarize-operator): Aggregates and groups data before you sort by aggregated values. -- [order](/apl/tabular-operators/order-operator): An alias of `sort-by`. Both work identically, but `sort-by` is the preferred syntax. -- [project](/apl/tabular-operators/project-operator): Selects specific columns, often used together with `sort-by` to simplify result sets. diff --git a/apl/apl-features.mdx b/apl/apl-features.mdx index 06f9e793..e3c6356e 100644 --- a/apl/apl-features.mdx +++ b/apl/apl-features.mdx @@ -28,8 +28,6 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Aggregation function | [percentileif](/apl/aggregation-function/percentileif) | Calculates the requested percentiles of the field for the rows where the predicate evaluates to true. | | Aggregation function | [percentiles_array](/apl/aggregation-function/percentiles-array) | Returns an array of numbers where each element is the value at the corresponding percentile. | | Aggregation function | [percentiles_arrayif](/apl/aggregation-function/percentiles-arrayif) | Returns an array of percentile values for the records that satisfy the condition. | -| Aggregation function | [sample-distinct](/apl/aggregation-function/sample-distinct) | Returns a random sample of distinct values. | -| Aggregation function | [sort-by](/apl/aggregation-function/sort-by) | Sorts the values in a group. | | Aggregation function | [rate](/apl/aggregation-function/rate) | Calculates the rate of values in a group per second. | | Aggregation function | [spotlight](/apl/aggregation-function/spotlight) | Compares a selected set of events against a baseline and surface the most significant differences. | | Aggregation function | [stdev](/apl/aggregation-function/stdev) | Calculates the standard deviation of an expression across the group. | @@ -290,6 +288,7 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Tabular operator | [project](/apl/tabular-operators/project-operator) | Returns a dataset containing only the specified fields. | | Tabular operator | [redact](/apl/tabular-operators/redact-operator) | Returns the input dataset with sensitive data replaced or hashed. | | Tabular operator | [sample](/apl/tabular-operators/sample-operator) | Returns a table containing the specified number of rows, selected randomly from the input dataset. | +| Tabular operator | [sample-distinct](/apl/tabular-operators/sample-distinct) | Returns a random sample of distinct values. | | Tabular operator | [search](/apl/tabular-operators/search-operator) | Returns all rows where the specified keyword appears in any field. | | Tabular operator | [sort](/apl/tabular-operators/sort-operator) | Returns a table with rows ordered based on the specified fields. | | Tabular operator | [summarize](/apl/tabular-operators/summarize-operator) | Returns a table where each row represents a unique combination of values from the by fields, with the aggregated results calculated for the other fields. | @@ -303,6 +302,7 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Time series function | [series_atan](/apl/scalar-functions/time-series/series-atan) | Returns the inverse tangent (arctan) of a series. | | Time series function | [series_cos](/apl/scalar-functions/time-series/series-cos) | Returns the cosine of a series. | | Time series function | [series_sin](/apl/scalar-functions/time-series/series-sin) | Returns the sine of a series. | +| Time series function | [series_tan](/apl/scalar-functions/time-series/series-tan) | Returns the tangent of a series. | | Type function | [iscc](/apl/scalar-functions/type-functions/iscc) | Checks whether a value is a valid credit card (CC) number. | | Type function | [isimei](/apl/scalar-functions/type-functions/isimei) | Checks whether a value is a valid International Mobile Equipment Identity (IMEI) number. | | Type function | [ismap](/apl/scalar-functions/type-functions/ismap) | Checks whether a value is of the `dynamic` type and represents a mapping. | diff --git a/apl/scalar-functions/time-series/overview.mdx b/apl/scalar-functions/time-series/overview.mdx index 9e8194bd..95bcb4f4 100644 --- a/apl/scalar-functions/time-series/overview.mdx +++ b/apl/scalar-functions/time-series/overview.mdx @@ -14,3 +14,4 @@ The table summarizes the time series functions available in APL. | [series_atan](/apl/scalar-functions/time-series/series-atan) | Returns the inverse tangent (arctan) of a series. | | [series_cos](/apl/scalar-functions/time-series/series-cos) | Returns the cosine of a series. | | [series_sin](/apl/scalar-functions/time-series/series-sin) | Returns the sine of a series. | +| [series_tan](/apl/scalar-functions/time-series/series-tan) | Returns the tangent of a series. | diff --git a/apl/scalar-functions/time-series/series-tan.mdx b/apl/scalar-functions/time-series/series-tan.mdx new file mode 100644 index 00000000..0ead3725 --- /dev/null +++ b/apl/scalar-functions/time-series/series-tan.mdx @@ -0,0 +1,160 @@ +--- +title: series_tan +description: 'This page explains how to use the series_tan function in APL.' +--- + +The `series_tan` function computes the tangent of each numeric element in a dynamic array. You use it when you work with time series or other array-based datasets and want to transform values using the trigonometric tangent. For example, you can convert request durations, latency values, or span durations into their tangent values for mathematical modeling, anomaly detection, or visualization. + +This function is useful when you want to: + +- Apply trigonometric transformations to time series data. +- Prepare data for advanced mathematical or statistical analysis. +- Detect periodic or angular patterns in logs, traces, or security events. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +Splunk SPL does not include a direct `tan` function for arrays. In SPL, you often use `eval` with `tan()` on scalar values. In APL, `series_tan` applies the tangent function element-wise to an entire array, which makes it better suited for time series or dynamic arrays. + + +```sql Splunk example +... | eval tan_val=tan(duration) +```` + +```kusto APL equivalent +['sample-http-logs'] +| extend series = pack_array(req_duration_ms, req_duration_ms*2, req_duration_ms*3) +| extend tan_series = series_tan(series) +``` + + + + + + +In ANSI SQL, you use the `TAN()` function on scalar values, but there is no native array type or array-wide trigonometric function. In APL, `series_tan` applies `tan` to each array element, which makes it easy to work with time series data. + + +```sql SQL example +SELECT TAN(duration) AS tan_val +FROM otel_demo_traces; +``` + +```kusto APL equivalent +['otel-demo-traces'] +| extend series = pack_array(duration, duration*2, duration*3) +| extend tan_series = series_tan(series) +``` + + + + + + +## Usage + +### Syntax + +```kusto +series_tan(array) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | --------------------------------- | ------------------------------------------------------------- | +| `array` | dynamic (array of numeric values) | The array of numeric values to apply the tangent function to. | + +### Returns + +A dynamic array where each element is the tangent of the corresponding input element. + +## Use case examples + + + + +You want to analyze request durations and apply a trigonometric transformation to highlight periodic anomalies. + +**Query** + +```kusto +['sample-http-logs'] +| summarize durations = make_list(req_duration_ms) by id +| extend tan_series = series_tan(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by id | extend tan_series = series_tan(durations)%22%7D) + +**Output** + +| id | durations | tan_series | +| ---- | ---------------- | --------------------- | +| A123 | [100, 200, 300] | [1.56, -2.19, -0.14] | +| B456 | [150, 250, 350] | [14.10, -0.75, 0.51] | + +This query groups request durations by user ID, transforms them into arrays, and applies the tangent function element-wise. + + + + +You want to transform span durations for mathematical modeling of system behavior. + +**Query** + +```kusto +['otel-demo-traces'] +| summarize spans = make_list(duration) by ['service.name'] +| extend tan_series = series_tan(spans) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans = make_list(duration) by ['service.name'] | extend tan_series = series_tan(spans)%22%7D) + +**Output** + +| service.name | spans | tan_series | +| ------------ | --------------------- | ------------------- | +| frontend | [50ms, 100ms, 150ms] | [0.05, 0.10, 0.15] | +| cartservice | [75ms, 125ms, 175ms] | [0.07, 0.13, 0.18] | + +This query collects span durations for each service, builds arrays, and applies tangent transformation for further modeling. + + + + +You want to detect anomalies in request durations for failed HTTP requests by applying the tangent transformation. + +**Query** + +```kusto +['sample-http-logs'] +| where status != '200' +| summarize durations = make_list(req_duration_ms) by geo.country +| extend tan_series = series_tan(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status != '200' | summarize durations = make_list(req_duration_ms) by geo.country | extend tan_series = series_tan(durations)%22%7D) + +**Output** + +| geo.country | durations | tan_series | +| ----------- | ---------------- | -------------------- | +| US | [120, 220, 320] | [2.57, -1.37, 0.73] | +| UK | [140, 240, 340] | [9.96, -0.46, 0.28] | + +This query filters failed requests, groups their durations by country, and applies tangent transformation to detect anomalies. + + + + +## List of related functions + +- [series_sin](/apl/series-functions/series_sin): Computes the sine of each element in an array. Use when you want sine instead of tangent. +- [series_cos](/apl/series-functions/series_cos): Computes the cosine of each element in an array. Use when you want cosine instead of tangent. +- [series_asin](/apl/series-functions/series_asin): Computes the arcsine of each element in an array. Use when you want the inverse sine. +- [series_acos](/apl/series-functions/series_acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. +- [series_atan](/apl/series-functions/series_atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. diff --git a/apl/tabular-operators/overview.mdx b/apl/tabular-operators/overview.mdx index 2fc4a171..63bc7e60 100644 --- a/apl/tabular-operators/overview.mdx +++ b/apl/tabular-operators/overview.mdx @@ -26,6 +26,7 @@ The table summarizes the tabular operators available in APL. | [project-reorder](/apl/tabular-operators/project-reorder-operator) | Returns a table with the specified fields reordered as requested followed by any unspecified fields in their original order. | | [redact](/apl/tabular-operators/redact-operator) | Returns the input dataset with sensitive data replaced or hashed. | | [sample](/apl/tabular-operators/sample-operator) | Returns a table containing the specified number of rows, selected randomly from the input dataset. | +| [sample-distinct](/apl/tabular-operators/sample-distinct) | Returns a random sample of distinct values. | | [search](/apl/tabular-operators/search-operator) | Returns all rows where the specified keyword appears in any field. | | [sort](/apl/tabular-operators/sort-operator) | Returns a table with rows ordered based on the specified fields. | | [summarize](/apl/tabular-operators/summarize-operator) | Returns a table where each row represents a unique combination of values from the by fields, with the aggregated results calculated for the other fields. | diff --git a/apl/aggregation-function/sample-distinct.mdx b/apl/tabular-operators/sample-distinct.mdx similarity index 94% rename from apl/aggregation-function/sample-distinct.mdx rename to apl/tabular-operators/sample-distinct.mdx index e7512878..7fa189d1 100644 --- a/apl/aggregation-function/sample-distinct.mdx +++ b/apl/tabular-operators/sample-distinct.mdx @@ -5,7 +5,7 @@ description: 'This page explains how to use the sample-distinct operator in APL. The `sample-distinct` operator returns a random sample of distinct values from a dataset. You can use it when you want to quickly explore representative subsets of unique values without scanning the full dataset. This is useful in scenarios such as exploratory data analysis, performance testing, or when you need a small but diverse set of unique values for validation. -Unlike `sample`, which randomly selects rows, `sample-distinct` ensures that only distinct values for the chosen column are included in the output. +Unlike `sample`, which randomly selects rows, `sample-distinct` ensures that only distinct values for the chosen field are included in the output. ## For users of other query languages @@ -56,7 +56,7 @@ LIMIT 5; ### Syntax ```kusto -T | sample-distinct NumberOfRows [of Column] +sample-distinct NumberOfRows [of Field] ``` ### Parameters @@ -64,7 +64,7 @@ T | sample-distinct NumberOfRows [of Column] | Parameter | Type | Description | | -------------- | ------ | ------------------------------------------------------------------------------------------------------------ | | `NumberOfRows` | int | The number of distinct values to return. | -| `Column` | string | (Optional) The column from which to select distinct values. If omitted, all columns are considered together. | +| `Field` | string | (Optional) The field from which to select distinct values. If omitted, all fields are considered together. | ### Returns diff --git a/docs.json b/docs.json index 00dc0d10..6fd4fa5c 100644 --- a/docs.json +++ b/docs.json @@ -371,7 +371,8 @@ "apl/scalar-functions/time-series/series-asin", "apl/scalar-functions/time-series/series-atan", "apl/scalar-functions/time-series/series-cos", - "apl/scalar-functions/time-series/series-sin" + "apl/scalar-functions/time-series/series-sin", + "apl/scalar-functions/time-series/series-tan" ] }, { @@ -414,8 +415,6 @@ "apl/aggregation-function/percentiles-array", "apl/aggregation-function/percentiles-arrayif", "apl/aggregation-function/rate", - "apl/aggregation-function/sample-distinct", - "apl/aggregation-function/sort-by", "apl/aggregation-function/spotlight", "apl/aggregation-function/stdev", "apl/aggregation-function/stdevif", @@ -453,6 +452,7 @@ "apl/tabular-operators/project-reorder-operator", "apl/tabular-operators/redact-operator", "apl/tabular-operators/sample-operator", + "apl/tabular-operators/sample-distinct", "apl/tabular-operators/search-operator", "apl/tabular-operators/sort-operator", "apl/tabular-operators/summarize-operator", From ac65ba0471f1f3fbf411b2dcd1e40fa58f9c17fb Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 14:41:03 +0200 Subject: [PATCH 4/9] Remove sample-distinct --- apl/apl-features.mdx | 1 - .../time-series/series-tan copy.mdx | 160 ++++++++++++++++++ apl/tabular-operators/overview.mdx | 1 - apl/tabular-operators/sample-distinct.mdx | 159 ----------------- docs.json | 1 - 5 files changed, 160 insertions(+), 162 deletions(-) create mode 100644 apl/scalar-functions/time-series/series-tan copy.mdx delete mode 100644 apl/tabular-operators/sample-distinct.mdx diff --git a/apl/apl-features.mdx b/apl/apl-features.mdx index e3c6356e..a1af7087 100644 --- a/apl/apl-features.mdx +++ b/apl/apl-features.mdx @@ -288,7 +288,6 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Tabular operator | [project](/apl/tabular-operators/project-operator) | Returns a dataset containing only the specified fields. | | Tabular operator | [redact](/apl/tabular-operators/redact-operator) | Returns the input dataset with sensitive data replaced or hashed. | | Tabular operator | [sample](/apl/tabular-operators/sample-operator) | Returns a table containing the specified number of rows, selected randomly from the input dataset. | -| Tabular operator | [sample-distinct](/apl/tabular-operators/sample-distinct) | Returns a random sample of distinct values. | | Tabular operator | [search](/apl/tabular-operators/search-operator) | Returns all rows where the specified keyword appears in any field. | | Tabular operator | [sort](/apl/tabular-operators/sort-operator) | Returns a table with rows ordered based on the specified fields. | | Tabular operator | [summarize](/apl/tabular-operators/summarize-operator) | Returns a table where each row represents a unique combination of values from the by fields, with the aggregated results calculated for the other fields. | diff --git a/apl/scalar-functions/time-series/series-tan copy.mdx b/apl/scalar-functions/time-series/series-tan copy.mdx new file mode 100644 index 00000000..0ead3725 --- /dev/null +++ b/apl/scalar-functions/time-series/series-tan copy.mdx @@ -0,0 +1,160 @@ +--- +title: series_tan +description: 'This page explains how to use the series_tan function in APL.' +--- + +The `series_tan` function computes the tangent of each numeric element in a dynamic array. You use it when you work with time series or other array-based datasets and want to transform values using the trigonometric tangent. For example, you can convert request durations, latency values, or span durations into their tangent values for mathematical modeling, anomaly detection, or visualization. + +This function is useful when you want to: + +- Apply trigonometric transformations to time series data. +- Prepare data for advanced mathematical or statistical analysis. +- Detect periodic or angular patterns in logs, traces, or security events. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +Splunk SPL does not include a direct `tan` function for arrays. In SPL, you often use `eval` with `tan()` on scalar values. In APL, `series_tan` applies the tangent function element-wise to an entire array, which makes it better suited for time series or dynamic arrays. + + +```sql Splunk example +... | eval tan_val=tan(duration) +```` + +```kusto APL equivalent +['sample-http-logs'] +| extend series = pack_array(req_duration_ms, req_duration_ms*2, req_duration_ms*3) +| extend tan_series = series_tan(series) +``` + + + + + + +In ANSI SQL, you use the `TAN()` function on scalar values, but there is no native array type or array-wide trigonometric function. In APL, `series_tan` applies `tan` to each array element, which makes it easy to work with time series data. + + +```sql SQL example +SELECT TAN(duration) AS tan_val +FROM otel_demo_traces; +``` + +```kusto APL equivalent +['otel-demo-traces'] +| extend series = pack_array(duration, duration*2, duration*3) +| extend tan_series = series_tan(series) +``` + + + + + + +## Usage + +### Syntax + +```kusto +series_tan(array) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | --------------------------------- | ------------------------------------------------------------- | +| `array` | dynamic (array of numeric values) | The array of numeric values to apply the tangent function to. | + +### Returns + +A dynamic array where each element is the tangent of the corresponding input element. + +## Use case examples + + + + +You want to analyze request durations and apply a trigonometric transformation to highlight periodic anomalies. + +**Query** + +```kusto +['sample-http-logs'] +| summarize durations = make_list(req_duration_ms) by id +| extend tan_series = series_tan(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by id | extend tan_series = series_tan(durations)%22%7D) + +**Output** + +| id | durations | tan_series | +| ---- | ---------------- | --------------------- | +| A123 | [100, 200, 300] | [1.56, -2.19, -0.14] | +| B456 | [150, 250, 350] | [14.10, -0.75, 0.51] | + +This query groups request durations by user ID, transforms them into arrays, and applies the tangent function element-wise. + + + + +You want to transform span durations for mathematical modeling of system behavior. + +**Query** + +```kusto +['otel-demo-traces'] +| summarize spans = make_list(duration) by ['service.name'] +| extend tan_series = series_tan(spans) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans = make_list(duration) by ['service.name'] | extend tan_series = series_tan(spans)%22%7D) + +**Output** + +| service.name | spans | tan_series | +| ------------ | --------------------- | ------------------- | +| frontend | [50ms, 100ms, 150ms] | [0.05, 0.10, 0.15] | +| cartservice | [75ms, 125ms, 175ms] | [0.07, 0.13, 0.18] | + +This query collects span durations for each service, builds arrays, and applies tangent transformation for further modeling. + + + + +You want to detect anomalies in request durations for failed HTTP requests by applying the tangent transformation. + +**Query** + +```kusto +['sample-http-logs'] +| where status != '200' +| summarize durations = make_list(req_duration_ms) by geo.country +| extend tan_series = series_tan(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status != '200' | summarize durations = make_list(req_duration_ms) by geo.country | extend tan_series = series_tan(durations)%22%7D) + +**Output** + +| geo.country | durations | tan_series | +| ----------- | ---------------- | -------------------- | +| US | [120, 220, 320] | [2.57, -1.37, 0.73] | +| UK | [140, 240, 340] | [9.96, -0.46, 0.28] | + +This query filters failed requests, groups their durations by country, and applies tangent transformation to detect anomalies. + + + + +## List of related functions + +- [series_sin](/apl/series-functions/series_sin): Computes the sine of each element in an array. Use when you want sine instead of tangent. +- [series_cos](/apl/series-functions/series_cos): Computes the cosine of each element in an array. Use when you want cosine instead of tangent. +- [series_asin](/apl/series-functions/series_asin): Computes the arcsine of each element in an array. Use when you want the inverse sine. +- [series_acos](/apl/series-functions/series_acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. +- [series_atan](/apl/series-functions/series_atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. diff --git a/apl/tabular-operators/overview.mdx b/apl/tabular-operators/overview.mdx index 63bc7e60..2fc4a171 100644 --- a/apl/tabular-operators/overview.mdx +++ b/apl/tabular-operators/overview.mdx @@ -26,7 +26,6 @@ The table summarizes the tabular operators available in APL. | [project-reorder](/apl/tabular-operators/project-reorder-operator) | Returns a table with the specified fields reordered as requested followed by any unspecified fields in their original order. | | [redact](/apl/tabular-operators/redact-operator) | Returns the input dataset with sensitive data replaced or hashed. | | [sample](/apl/tabular-operators/sample-operator) | Returns a table containing the specified number of rows, selected randomly from the input dataset. | -| [sample-distinct](/apl/tabular-operators/sample-distinct) | Returns a random sample of distinct values. | | [search](/apl/tabular-operators/search-operator) | Returns all rows where the specified keyword appears in any field. | | [sort](/apl/tabular-operators/sort-operator) | Returns a table with rows ordered based on the specified fields. | | [summarize](/apl/tabular-operators/summarize-operator) | Returns a table where each row represents a unique combination of values from the by fields, with the aggregated results calculated for the other fields. | diff --git a/apl/tabular-operators/sample-distinct.mdx b/apl/tabular-operators/sample-distinct.mdx deleted file mode 100644 index 7fa189d1..00000000 --- a/apl/tabular-operators/sample-distinct.mdx +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: sample-distinct -description: 'This page explains how to use the sample-distinct operator in APL.' ---- - -The `sample-distinct` operator returns a random sample of distinct values from a dataset. You can use it when you want to quickly explore representative subsets of unique values without scanning the full dataset. This is useful in scenarios such as exploratory data analysis, performance testing, or when you need a small but diverse set of unique values for validation. - -Unlike `sample`, which randomly selects rows, `sample-distinct` ensures that only distinct values for the chosen field are included in the output. - -## For users of other query languages - -If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. - - - - -In Splunk SPL, you typically use the `sample` command to return a subset of events, but it does not guarantee uniqueness. To get distinct values, you combine commands like `dedup` and `sample`. In APL, `sample-distinct` combines both operations into one: it first deduplicates values and then samples from them. - - -```sql Splunk example -... | dedup uri | sample 5 -```` - -```kusto APL equivalent -['sample-http-logs'] -| sample-distinct 5 of uri -``` - - - - - - -In SQL, you use `SELECT DISTINCT` to get unique values and combine it with `TABLESAMPLE` or `ORDER BY RAND()` to get a random sample. In APL, `sample-distinct` does both in a single operator. - - -```sql SQL example -SELECT DISTINCT uri -FROM sample_http_logs -ORDER BY RAND() -LIMIT 5; -``` - -```kusto APL equivalent -['sample-http-logs'] -| sample-distinct 5 of uri -``` - - - - - - -## Usage - -### Syntax - -```kusto -sample-distinct NumberOfRows [of Field] -``` - -### Parameters - -| Parameter | Type | Description | -| -------------- | ------ | ------------------------------------------------------------------------------------------------------------ | -| `NumberOfRows` | int | The number of distinct values to return. | -| `Field` | string | (Optional) The field from which to select distinct values. If omitted, all fields are considered together. | - -### Returns - -A table with up to the specified number of distinct values. The rows are chosen randomly. - -## Use case examples - - - - -When you want to see a random subset of unique URLs that users accessed in your logs, you can use `sample-distinct`. - -**Query** - -```kusto -['sample-http-logs'] -| sample-distinct 5 of uri -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 5 of uri%22%7D) - -**Output** - -| uri | -| -------------- | -| /products/view | -| /cart/add | -| /checkout | -| /home | -| /login | - -This query returns 5 random distinct URLs (`uri`) from the HTTP logs, which helps you explore a representative subset of endpoints. - - - - -You can use `sample-distinct` to explore unique services in your distributed traces. - -**Query** - -```kusto -['otel-demo-traces'] -| sample-distinct 3 of ['service.name'] -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | sample-distinct 3 of ['service.name']%22%7D) - -**Output** - -| service.name | -| --------------- | -| frontend | -| cartservice | -| checkoutservice | - -This query returns 3 random distinct services from your traces, helping you quickly see which parts of your system are represented. - - - - -You can use `sample-distinct` to view a random selection of unique status codes in security logs. - -**Query** - -```kusto -['sample-http-logs'] -| sample-distinct 4 of status -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | sample-distinct 4 of status%22%7D) - -**Output** - -| status | -| ------ | -| 200 | -| 401 | -| 403 | -| 500 | - -This query helps you quickly identify a variety of HTTP status codes that appear in your logs without scanning the entire dataset. - - - - -## List of related operators - -- [sample](/apl/tabular-operators/sample-operator): Returns a random sample of rows but does not ensure uniqueness. -- [distinct](/apl/tabular-operators/distinct-operator): Returns all unique values without sampling. -- [take](/apl/tabular-operators/take-operator): Returns the first *n* rows from a dataset without randomization or uniqueness. -- [top](/apl/tabular-operators/top-operator): Returns the first *n* rows sorted by a specified expression. -- [summarize](/apl/tabular-operators/summarize-operator): Groups rows and computes aggregates, often used with `distinct` for deduplication. diff --git a/docs.json b/docs.json index 6fd4fa5c..31cfb6bf 100644 --- a/docs.json +++ b/docs.json @@ -452,7 +452,6 @@ "apl/tabular-operators/project-reorder-operator", "apl/tabular-operators/redact-operator", "apl/tabular-operators/sample-operator", - "apl/tabular-operators/sample-distinct", "apl/tabular-operators/search-operator", "apl/tabular-operators/sort-operator", "apl/tabular-operators/summarize-operator", From d6742ced8258749deed8adca7c3441b703a904ea Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 14:43:47 +0200 Subject: [PATCH 5/9] Add series-sum --- apl/apl-features.mdx | 1 + apl/scalar-functions/time-series/overview.mdx | 1 + .../time-series/series-sum.mdx | 158 +++++++++++++++++ .../time-series/series-tan copy.mdx | 160 ------------------ docs.json | 1 + 5 files changed, 161 insertions(+), 160 deletions(-) create mode 100644 apl/scalar-functions/time-series/series-sum.mdx delete mode 100644 apl/scalar-functions/time-series/series-tan copy.mdx diff --git a/apl/apl-features.mdx b/apl/apl-features.mdx index a1af7087..90232ec7 100644 --- a/apl/apl-features.mdx +++ b/apl/apl-features.mdx @@ -301,6 +301,7 @@ keywords: ['axiom documentation', 'documentation', 'axiom', 'APL', 'axiom proces | Time series function | [series_atan](/apl/scalar-functions/time-series/series-atan) | Returns the inverse tangent (arctan) of a series. | | Time series function | [series_cos](/apl/scalar-functions/time-series/series-cos) | Returns the cosine of a series. | | Time series function | [series_sin](/apl/scalar-functions/time-series/series-sin) | Returns the sine of a series. | +| Time series function | [series_sum](/apl/scalar-functions/time-series/series-sum) | Returns the sum of a series. | | Time series function | [series_tan](/apl/scalar-functions/time-series/series-tan) | Returns the tangent of a series. | | Type function | [iscc](/apl/scalar-functions/type-functions/iscc) | Checks whether a value is a valid credit card (CC) number. | | Type function | [isimei](/apl/scalar-functions/type-functions/isimei) | Checks whether a value is a valid International Mobile Equipment Identity (IMEI) number. | diff --git a/apl/scalar-functions/time-series/overview.mdx b/apl/scalar-functions/time-series/overview.mdx index 95bcb4f4..83712ba3 100644 --- a/apl/scalar-functions/time-series/overview.mdx +++ b/apl/scalar-functions/time-series/overview.mdx @@ -14,4 +14,5 @@ The table summarizes the time series functions available in APL. | [series_atan](/apl/scalar-functions/time-series/series-atan) | Returns the inverse tangent (arctan) of a series. | | [series_cos](/apl/scalar-functions/time-series/series-cos) | Returns the cosine of a series. | | [series_sin](/apl/scalar-functions/time-series/series-sin) | Returns the sine of a series. | +| [series_sum](/apl/scalar-functions/time-series/series-sum) | Returns the sum of a series. | | [series_tan](/apl/scalar-functions/time-series/series-tan) | Returns the tangent of a series. | diff --git a/apl/scalar-functions/time-series/series-sum.mdx b/apl/scalar-functions/time-series/series-sum.mdx new file mode 100644 index 00000000..7eab030f --- /dev/null +++ b/apl/scalar-functions/time-series/series-sum.mdx @@ -0,0 +1,158 @@ +--- +title: series_sum +description: 'This page explains how to use the series_sum function in APL.' +--- + +The `series_sum` function in APL calculates the total of all numeric elements in a dynamic array. You use it when you have a series of values and you want to condense them into a single aggregate number. For example, if you create arrays of request durations or span times, `series_sum` lets you quickly compute the total across each series. + +This function is useful in scenarios such as: + +- Aggregating request latencies across sessions or users. +- Summing the duration of spans in distributed traces. +- Calculating total counts or values across arrays in security log analysis. + +## For users of other query languages + +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. + + + + +In Splunk SPL, you typically use the `eval` command with `mvsum` to sum values in a multivalue field. In APL, you use `series_sum` for the same purpose. Both functions collapse an array into a single scalar value. + + +```sql Splunk example +... | eval total_duration = mvsum(req_duration_ms) +```` + +```kusto APL equivalent +['sample-http-logs'] +| extend total_duration = series_sum(pack_array(req_duration_ms)) +``` + + + + + + +In SQL, you normally use `SUM()` as an aggregate over rows. If you want to sum elements inside an array, you must use functions such as `UNNEST` first. In APL, `series_sum` directly operates on dynamic arrays, so you don’t need to flatten them. + + +```sql SQL example +SELECT user_id, SUM(val) AS total +FROM my_table, UNNEST(values) AS val +GROUP BY user_id +``` + +```kusto APL equivalent +['sample-http-logs'] +| summarize total = series_sum(pack_array(req_duration_ms)) by id +``` + + + + + + +## Usage + +### Syntax + +```kusto +series_sum(array) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | --------------- | ----------------------------------- | +| `array` | dynamic (array) | The array of numeric values to sum. | + +### Returns + +A `real` value representing the sum of all numeric elements in the array. If the array is empty, the function returns `0`. + +## Use case examples + + + + +When you want to calculate the total request duration per user across multiple requests. + +**Query** + +```kusto +['sample-http-logs'] +| summarize durations = make_list(req_duration_ms) by id +| extend total_duration = series_sum(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by id | extend total_duration = series_sum(durations)%22%7D) + +**Output** + +| id | durations | total_duration | +| ---- | --------------- | --------------- | +| u123 | [120, 300, 50] | 470 | +| u456 | [200, 150] | 350 | + +This query collects request durations for each user, creates an array, and then sums the array to compute the total request time per user. + + + + +When you want to compute the total span duration per service within a trace. + +**Query** + +```kusto +['otel-demo-traces'] +| summarize durations = make_list(duration) by ['service.name'], trace_id +| extend total_span_duration = series_sum(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize durations = make_list(duration) by ['service.name'], trace_id | extend total_span_duration = series_sum(durations)%22%7D) + +**Output** + +| service.name | trace_id | durations | total_span_duration | +| --------------- | --------- | ----------------------------- | --------------------- | +| frontend | t123 | [00:00:01.2000000, 00:00:02] | 00:00:03.2000000 | +| checkoutservice | t456 | [00:00:00.5000000] | 00:00:00.5000000 | + +This query groups spans by service and trace, collects the span durations, and computes the total execution time of spans. + + + + +When you want to evaluate the total request duration for each HTTP status code. + +**Query** + +```kusto +['sample-http-logs'] +| summarize durations = make_list(req_duration_ms) by status +| extend total_duration = series_sum(durations) +``` + +[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by status | extend total_duration = series_sum(durations)%22%7D) + +**Output** + +| status | durations | total_duration | +| ------ | --------------- | --------------- | +| 200 | [100, 300, 50] | 450 | +| 500 | [250, 400] | 650 | + +This query aggregates request durations for each HTTP status code, then sums them to provide insight into the total duration of successful vs. failed requests. + + + + +## List of related functions + +- [series_avg](/apl/series-functions/series_avg): Returns the average of numeric elements in an array. Use it when you want the mean instead of the sum. +- [series_min](/apl/series-functions/series_min): Returns the smallest element in the array. Use it when you want to detect the minimum value in the series. +- [series_max](/apl/series-functions/series_max): Returns the largest element in the array. Use it when you want the maximum value. +- [series_count](/apl/series-functions/series_count): Returns the number of elements in the array. Use it to check the size of a series. +- [series_stats](/apl/series-functions/series_stats): Returns multiple descriptive statistics (sum, min, max, avg, stdev) at once. Use it for comprehensive analysis instead of a single metric. diff --git a/apl/scalar-functions/time-series/series-tan copy.mdx b/apl/scalar-functions/time-series/series-tan copy.mdx deleted file mode 100644 index 0ead3725..00000000 --- a/apl/scalar-functions/time-series/series-tan copy.mdx +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: series_tan -description: 'This page explains how to use the series_tan function in APL.' ---- - -The `series_tan` function computes the tangent of each numeric element in a dynamic array. You use it when you work with time series or other array-based datasets and want to transform values using the trigonometric tangent. For example, you can convert request durations, latency values, or span durations into their tangent values for mathematical modeling, anomaly detection, or visualization. - -This function is useful when you want to: - -- Apply trigonometric transformations to time series data. -- Prepare data for advanced mathematical or statistical analysis. -- Detect periodic or angular patterns in logs, traces, or security events. - -## For users of other query languages - -If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. - - - - -Splunk SPL does not include a direct `tan` function for arrays. In SPL, you often use `eval` with `tan()` on scalar values. In APL, `series_tan` applies the tangent function element-wise to an entire array, which makes it better suited for time series or dynamic arrays. - - -```sql Splunk example -... | eval tan_val=tan(duration) -```` - -```kusto APL equivalent -['sample-http-logs'] -| extend series = pack_array(req_duration_ms, req_duration_ms*2, req_duration_ms*3) -| extend tan_series = series_tan(series) -``` - - - - - - -In ANSI SQL, you use the `TAN()` function on scalar values, but there is no native array type or array-wide trigonometric function. In APL, `series_tan` applies `tan` to each array element, which makes it easy to work with time series data. - - -```sql SQL example -SELECT TAN(duration) AS tan_val -FROM otel_demo_traces; -``` - -```kusto APL equivalent -['otel-demo-traces'] -| extend series = pack_array(duration, duration*2, duration*3) -| extend tan_series = series_tan(series) -``` - - - - - - -## Usage - -### Syntax - -```kusto -series_tan(array) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | --------------------------------- | ------------------------------------------------------------- | -| `array` | dynamic (array of numeric values) | The array of numeric values to apply the tangent function to. | - -### Returns - -A dynamic array where each element is the tangent of the corresponding input element. - -## Use case examples - - - - -You want to analyze request durations and apply a trigonometric transformation to highlight periodic anomalies. - -**Query** - -```kusto -['sample-http-logs'] -| summarize durations = make_list(req_duration_ms) by id -| extend tan_series = series_tan(durations) -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by id | extend tan_series = series_tan(durations)%22%7D) - -**Output** - -| id | durations | tan_series | -| ---- | ---------------- | --------------------- | -| A123 | [100, 200, 300] | [1.56, -2.19, -0.14] | -| B456 | [150, 250, 350] | [14.10, -0.75, 0.51] | - -This query groups request durations by user ID, transforms them into arrays, and applies the tangent function element-wise. - - - - -You want to transform span durations for mathematical modeling of system behavior. - -**Query** - -```kusto -['otel-demo-traces'] -| summarize spans = make_list(duration) by ['service.name'] -| extend tan_series = series_tan(spans) -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans = make_list(duration) by ['service.name'] | extend tan_series = series_tan(spans)%22%7D) - -**Output** - -| service.name | spans | tan_series | -| ------------ | --------------------- | ------------------- | -| frontend | [50ms, 100ms, 150ms] | [0.05, 0.10, 0.15] | -| cartservice | [75ms, 125ms, 175ms] | [0.07, 0.13, 0.18] | - -This query collects span durations for each service, builds arrays, and applies tangent transformation for further modeling. - - - - -You want to detect anomalies in request durations for failed HTTP requests by applying the tangent transformation. - -**Query** - -```kusto -['sample-http-logs'] -| where status != '200' -| summarize durations = make_list(req_duration_ms) by geo.country -| extend tan_series = series_tan(durations) -``` - -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status != '200' | summarize durations = make_list(req_duration_ms) by geo.country | extend tan_series = series_tan(durations)%22%7D) - -**Output** - -| geo.country | durations | tan_series | -| ----------- | ---------------- | -------------------- | -| US | [120, 220, 320] | [2.57, -1.37, 0.73] | -| UK | [140, 240, 340] | [9.96, -0.46, 0.28] | - -This query filters failed requests, groups their durations by country, and applies tangent transformation to detect anomalies. - - - - -## List of related functions - -- [series_sin](/apl/series-functions/series_sin): Computes the sine of each element in an array. Use when you want sine instead of tangent. -- [series_cos](/apl/series-functions/series_cos): Computes the cosine of each element in an array. Use when you want cosine instead of tangent. -- [series_asin](/apl/series-functions/series_asin): Computes the arcsine of each element in an array. Use when you want the inverse sine. -- [series_acos](/apl/series-functions/series_acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. -- [series_atan](/apl/series-functions/series_atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. diff --git a/docs.json b/docs.json index 31cfb6bf..2aeb92bc 100644 --- a/docs.json +++ b/docs.json @@ -372,6 +372,7 @@ "apl/scalar-functions/time-series/series-atan", "apl/scalar-functions/time-series/series-cos", "apl/scalar-functions/time-series/series-sin", + "apl/scalar-functions/time-series/series-sum", "apl/scalar-functions/time-series/series-tan" ] }, From a3b5983a1e650ce3f34e8fff01b4adbf4c0afeb2 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 14:57:36 +0200 Subject: [PATCH 6/9] Fix Playground --- apl/scalar-functions/string-functions/string-size.mdx | 10 +++++----- apl/scalar-functions/time-series/series-cos.mdx | 11 +++++------ apl/scalar-functions/time-series/series-sin.mdx | 9 ++++----- apl/scalar-functions/time-series/series-sum.mdx | 6 +++--- apl/scalar-functions/time-series/series-tan.mdx | 6 +++--- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/apl/scalar-functions/string-functions/string-size.mdx b/apl/scalar-functions/string-functions/string-size.mdx index cdcd9fd7..9f656684 100644 --- a/apl/scalar-functions/string-functions/string-size.mdx +++ b/apl/scalar-functions/string-functions/string-size.mdx @@ -79,11 +79,11 @@ You can use `string_size` to detect unusually long URIs that might indicate an a ```kusto ['sample-http-logs'] | extend uri_length = string_size(uri) -| where uri_length > 100 +| where uri_length > 10 | project _time, method, uri, uri_length, status ``` -[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20uri_length%20%3D%20string_size%28uri%29%20%7C%20where%20uri_length%20%3E%20100%20%7C%20project%20_time%2C%20method%2C%20uri%2C%20uri_length%2C%20status%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20uri_length%20%3D%20string_size%28uri%29%20%7C%20where%20uri_length%20%3E%2010%20%7C%20project%20_time%2C%20method%2C%20uri%2C%20uri_length%2C%20status%22%7D) **Output** @@ -92,7 +92,7 @@ You can use `string_size` to detect unusually long URIs that might indicate an a | 2025-09-11T10:01:45Z | GET | /search/products?q=... | 142 | 200 | | 2025-09-11T10:02:13Z | POST | /checkout/submit/order/details... | 187 | 400 | -This query finds all HTTP requests with URIs longer than 100 characters and lists their details. +This query finds all HTTP requests with URIs longer than 10 characters and lists their details. @@ -130,10 +130,10 @@ You can check for anomalous user IDs by looking at the length of the `id` field. ['sample-http-logs'] | extend id_length = string_size(id) | where id_length < 5 or id_length > 20 -| project _time, id, id_length, status, geo.country +| project _time, id, id_length, status, ['geo.country'] ``` -[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20id_length%20%3D%20string_size%28id%29%20%7C%20where%20id_length%20%3C%205%20or%20id_length%20%3E%2020%20%7C%20project%20_time%2C%20id%2C%20id_length%2C%20status%2C%20geo.country%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20id_length%20%3D%20string_size(id)%20%7C%20where%20id_length%20%3C%205%20or%20id_length%20%3E%2020%20%7C%20project%20_time%2C%20id%2C%20id_length%2C%20status%2C%20%5B'geo.country'%5D%22%7D) **Output** diff --git a/apl/scalar-functions/time-series/series-cos.mdx b/apl/scalar-functions/time-series/series-cos.mdx index 6e00cebb..e29b8022 100644 --- a/apl/scalar-functions/time-series/series-cos.mdx +++ b/apl/scalar-functions/time-series/series-cos.mdx @@ -82,7 +82,7 @@ You want to model periodic patterns in request durations by applying the cosine | extend cos_durations=series_cos(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations=make_list(req_duration_ms) by id | extend cos_durations=series_cos(durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20durations%3Dmake_list(req_duration_ms)%20by%20id%20%7C%20extend%20cos_durations%3Dseries_cos(durations)%22%7D) **Output** @@ -106,7 +106,7 @@ You want to apply trigonometric transformations to span durations to explore cyc | extend cos_spans=series_cos(spans) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans=make_list(duration) by ['service.name'] | extend cos_spans=series_cos(spans)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20summarize%20spans%3Dmake_list(duration)%20by%20%5B'service.name'%5D%20%7C%20extend%20cos_spans%3Dseries_cos(spans)%22%7D) **Output** @@ -126,12 +126,11 @@ You want to explore whether cosine transformations reveal patterns in request du ```kusto ['sample-http-logs'] -| where status == '403' -| summarize blocked_durations=make_list(req_duration_ms) by ['geo.country'] -| extend cos_blocked=series_cos(blocked_durations) +| summarize durations=make_list(req_duration_ms) by ['geo.country'] +| extend cos_blocked=series_cos(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize blocked_durations=make_list(req_duration_ms) by ['geo.country'] | extend cos_blocked=series_cos(blocked_durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20durations%3Dmake_list(req_duration_ms)%20by%20%5B'geo.country'%5D%20%7C%20extend%20cos_blocked%3Dseries_cos(durations)%22%7D) **Output** diff --git a/apl/scalar-functions/time-series/series-sin.mdx b/apl/scalar-functions/time-series/series-sin.mdx index 370c42fc..cbaa39f5 100644 --- a/apl/scalar-functions/time-series/series-sin.mdx +++ b/apl/scalar-functions/time-series/series-sin.mdx @@ -88,7 +88,7 @@ You can use `series_sin` to transform request durations into trigonometric value | extend sin_arr = series_sin(arr) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize arr = make_list(req_duration_ms, 10) | extend sin_arr = series_sin(arr)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20arr%20%3D%20make_list(req_duration_ms%2C%2010)%20%7C%20extend%20sin_arr%20%3D%20series_sin(arr)%22%7D) **Output** @@ -111,7 +111,7 @@ You can use `series_sin` to apply trigonometric transformation to span durations | extend sin_arr = series_sin(arr) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize arr = make_list(toint(duration), 10) by ['service.name'] | extend sin_arr = series_sin(arr)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20summarize%20arr%20%3D%20make_list(toint(duration)%2C%2010)%20by%20%5B'service.name'%5D%20%7C%20extend%20sin_arr%20%3D%20series_sin(arr)%22%7D) **Output** @@ -130,12 +130,11 @@ You can use `series_sin` to apply mathematical transformations to response times ```kusto ['sample-http-logs'] -| where status == '403' -| summarize arr = make_list(req_duration_ms, 10) by geo.country +| summarize arr = make_list(req_duration_ms, 10) by ['geo.country'] | extend sin_arr = series_sin(arr) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status == '403' | summarize arr = make_list(req_duration_ms, 10) by geo.country | extend sin_arr = series_sin(arr)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20arr%20%3D%20make_list(req_duration_ms%2C%2010)%20by%20%5B'geo.country'%5D%20%7C%20extend%20sin_arr%20%3D%20series_sin(arr)%22%7D) **Output** diff --git a/apl/scalar-functions/time-series/series-sum.mdx b/apl/scalar-functions/time-series/series-sum.mdx index 7eab030f..cf169cf7 100644 --- a/apl/scalar-functions/time-series/series-sum.mdx +++ b/apl/scalar-functions/time-series/series-sum.mdx @@ -87,7 +87,7 @@ When you want to calculate the total request duration per user across multiple r | extend total_duration = series_sum(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by id | extend total_duration = series_sum(durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20durations%20%3D%20make_list(req_duration_ms)%20by%20id%20%7C%20extend%20total_duration%20%3D%20series_sum(durations)%22%7D) **Output** @@ -111,7 +111,7 @@ When you want to compute the total span duration per service within a trace. | extend total_span_duration = series_sum(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize durations = make_list(duration) by ['service.name'], trace_id | extend total_span_duration = series_sum(durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20summarize%20durations%20%3D%20make_list(duration)%20by%20%5B'service.name'%5D%2C%20trace_id%20%7C%20extend%20total_span_duration%20%3D%20series_sum(durations)%22%7D) **Output** @@ -135,7 +135,7 @@ When you want to evaluate the total request duration for each HTTP status code. | extend total_duration = series_sum(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by status | extend total_duration = series_sum(durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20durations%20%3D%20make_list(req_duration_ms)%20by%20status%20%7C%20extend%20total_duration%20%3D%20series_sum(durations)%22%7D) **Output** diff --git a/apl/scalar-functions/time-series/series-tan.mdx b/apl/scalar-functions/time-series/series-tan.mdx index 0ead3725..71c781b1 100644 --- a/apl/scalar-functions/time-series/series-tan.mdx +++ b/apl/scalar-functions/time-series/series-tan.mdx @@ -88,7 +88,7 @@ You want to analyze request durations and apply a trigonometric transformation t | extend tan_series = series_tan(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | summarize durations = make_list(req_duration_ms) by id | extend tan_series = series_tan(durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20summarize%20durations%20%3D%20make_list(req_duration_ms)%20by%20id%20%7C%20extend%20tan_series%20%3D%20series_tan(durations)%22%7D) **Output** @@ -112,7 +112,7 @@ You want to transform span durations for mathematical modeling of system behavio | extend tan_series = series_tan(spans) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['otel-demo-traces)'] | summarize spans = make_list(duration) by ['service.name'] | extend tan_series = series_tan(spans)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20summarize%20spans%20%3D%20make_list(duration)%20by%20%5B'service.name'%5D%20%7C%20extend%20tan_series%20%3D%20series_tan(spans)%22%7D) **Output** @@ -137,7 +137,7 @@ You want to detect anomalies in request durations for failed HTTP requests by ap | extend tan_series = series_tan(durations) ``` -[Run in Playground]([https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22['sample-http-logs)'] | where status != '200' | summarize durations = make_list(req_duration_ms) by geo.country | extend tan_series = series_tan(durations)%22%7D) +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20where%20status%20!%3D%20'200'%20%7C%20summarize%20durations%20%3D%20make_list(req_duration_ms)%20by%20%5B'geo.country'%5D%20%7C%20extend%20tan_series%20%3D%20series_tan(durations)%22%7D) **Output** From 5e140b31be8197ca2317fb351e769549d0f0b4f6 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Thu, 11 Sep 2025 15:06:17 +0200 Subject: [PATCH 7/9] Fix links --- apl/scalar-functions/string-functions/string-size.mdx | 8 -------- apl/scalar-functions/time-series/series-cos.mdx | 10 +++++----- apl/scalar-functions/time-series/series-sin.mdx | 10 +++++----- apl/scalar-functions/time-series/series-sum.mdx | 10 +++++----- apl/scalar-functions/time-series/series-tan.mdx | 10 +++++----- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/apl/scalar-functions/string-functions/string-size.mdx b/apl/scalar-functions/string-functions/string-size.mdx index 9f656684..b4bf0aae 100644 --- a/apl/scalar-functions/string-functions/string-size.mdx +++ b/apl/scalar-functions/string-functions/string-size.mdx @@ -146,11 +146,3 @@ This query detects requests with suspiciously short or long user IDs, which migh - -## List of related functions - -- [strlen](/apl/string-functions/strlen): An alias for `string_size`, provided for compatibility. Use `string_size` for consistency with APL naming conventions. -- [substring](/apl/string-functions/substring): Extracts a portion of a string. Use it when you need part of a string rather than its length. -- [indexof](/apl/string-functions/indexof): Returns the position of a substring in a string. Use it when you want to locate substrings rather than measure total length. -- [replace](/apl/string-functions/replace): Replaces part of a string with another string. Use it to modify strings instead of measuring them. -- [tostring](/apl/conversion-functions/tostring): Converts values to strings. Use it before `string_size` if your input is not already a string. diff --git a/apl/scalar-functions/time-series/series-cos.mdx b/apl/scalar-functions/time-series/series-cos.mdx index e29b8022..8d687112 100644 --- a/apl/scalar-functions/time-series/series-cos.mdx +++ b/apl/scalar-functions/time-series/series-cos.mdx @@ -146,8 +146,8 @@ This query applies the cosine function to blocked request durations grouped by c ## List of related functions -- [series_sin](/apl/array-functions/series_sin): Returns the sine of each element in an array. Use it when analyzing cyclical data with a phase shift. -- [series_tan](/apl/array-functions/series_tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. -- [series_exp](/apl/array-functions/series_exp): Applies the exponential function to each element in an array. Use it for exponential growth or decay modeling. -- [series_log](/apl/array-functions/series_log): Returns the natural logarithm of each element in an array. Use it for logarithmic transformations of series data. -- [series_abs](/apl/array-functions/series_abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. +- [series_abs](/apl/scalar-functions/time-series/series-abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. +- [series_acos](/apl/scalar-functions/time-series/series-acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. +- [series_atan](/apl/scalar-functions/time-series/series-atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. +- [series_sin](/apl/scalar-functions/time-series/series-sin): Returns the sine of each element in an array. Use it when analyzing cyclical data with a phase shift. +- [series_tan](/apl/scalar-functions/time-series/series-tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. diff --git a/apl/scalar-functions/time-series/series-sin.mdx b/apl/scalar-functions/time-series/series-sin.mdx index cbaa39f5..f3788ed5 100644 --- a/apl/scalar-functions/time-series/series-sin.mdx +++ b/apl/scalar-functions/time-series/series-sin.mdx @@ -149,8 +149,8 @@ This query filters failed requests (`403`) by country, aggregates durations, and ## List of related functions -- [series_cos](/apl/array-functions/series_cos): Returns the cosine of each array element. Use when you want the cosine instead of sine. -- [series_tan](/apl/array-functions/series_tan): Returns the tangent of each array element. Use when analyzing angular relationships. -- [series_exp](/apl/array-functions/series_exp): Returns the exponential of each array element. Useful for growth and scaling analysis. -- [series_log](/apl/array-functions/series_log): Returns the natural logarithm of each array element. Useful for reducing skew in data distributions. -- [series_abs](/apl/array-functions/series_abs): Returns the absolute value of each array element. Use when you want non-negative transformations. +- [series_abs](/apl/scalar-functions/time-series/series-abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. +- [series_acos](/apl/scalar-functions/time-series/series-acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. +- [series_atan](/apl/scalar-functions/time-series/series-atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. +- [series_cos](/apl/scalar-functions/time-series/series-cos): Returns the cosine of each element in an array. Use it when analyzing cyclical data with a phase shift. +- [series_tan](/apl/scalar-functions/time-series/series-tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. diff --git a/apl/scalar-functions/time-series/series-sum.mdx b/apl/scalar-functions/time-series/series-sum.mdx index cf169cf7..f68ea240 100644 --- a/apl/scalar-functions/time-series/series-sum.mdx +++ b/apl/scalar-functions/time-series/series-sum.mdx @@ -151,8 +151,8 @@ This query aggregates request durations for each HTTP status code, then sums the ## List of related functions -- [series_avg](/apl/series-functions/series_avg): Returns the average of numeric elements in an array. Use it when you want the mean instead of the sum. -- [series_min](/apl/series-functions/series_min): Returns the smallest element in the array. Use it when you want to detect the minimum value in the series. -- [series_max](/apl/series-functions/series_max): Returns the largest element in the array. Use it when you want the maximum value. -- [series_count](/apl/series-functions/series_count): Returns the number of elements in the array. Use it to check the size of a series. -- [series_stats](/apl/series-functions/series_stats): Returns multiple descriptive statistics (sum, min, max, avg, stdev) at once. Use it for comprehensive analysis instead of a single metric. +- [series_abs](/apl/scalar-functions/time-series/series-abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. +- [series_acos](/apl/scalar-functions/time-series/series-acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. +- [series_atan](/apl/scalar-functions/time-series/series-atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. +- [series_cos](/apl/scalar-functions/time-series/series-cos): Returns the cosine of each element in an array. Use it when analyzing cyclical data with a phase shift. +- [series_tan](/apl/scalar-functions/time-series/series-tan): Returns the tangent of each element in an array. Use it when you want to transform arrays with tangent-based periodicity. diff --git a/apl/scalar-functions/time-series/series-tan.mdx b/apl/scalar-functions/time-series/series-tan.mdx index 71c781b1..e4d7ab05 100644 --- a/apl/scalar-functions/time-series/series-tan.mdx +++ b/apl/scalar-functions/time-series/series-tan.mdx @@ -153,8 +153,8 @@ This query filters failed requests, groups their durations by country, and appli ## List of related functions -- [series_sin](/apl/series-functions/series_sin): Computes the sine of each element in an array. Use when you want sine instead of tangent. -- [series_cos](/apl/series-functions/series_cos): Computes the cosine of each element in an array. Use when you want cosine instead of tangent. -- [series_asin](/apl/series-functions/series_asin): Computes the arcsine of each element in an array. Use when you want the inverse sine. -- [series_acos](/apl/series-functions/series_acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. -- [series_atan](/apl/series-functions/series_atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. +- [series_abs](/apl/scalar-functions/time-series/series-abs): Returns the absolute value of each element in an array. Use it to normalize negative values in arrays. +- [series_acos](/apl/scalar-functions/time-series/series-acos): Computes the arccosine of each element in an array. Use when you want the inverse cosine. +- [series_atan](/apl/scalar-functions/time-series/series-atan): Computes the arctangent of each element in an array. Use when you want the inverse tangent. +- [series_cos](/apl/scalar-functions/time-series/series-cos): Returns the cosine of each element in an array. Use it when analyzing cyclical data with a phase shift. +- [series_sin](/apl/scalar-functions/time-series/series-sin): Returns the sine of each element in an array. Use it when analyzing cyclical data with a phase shift. From 7b6437e69d11071c623cadfcddd889134bcaaa36 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Tue, 30 Sep 2025 10:48:33 +0200 Subject: [PATCH 8/9] Implement review --- apl/scalar-functions/string-functions/string-size.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apl/scalar-functions/string-functions/string-size.mdx b/apl/scalar-functions/string-functions/string-size.mdx index b4bf0aae..c87ee34e 100644 --- a/apl/scalar-functions/string-functions/string-size.mdx +++ b/apl/scalar-functions/string-functions/string-size.mdx @@ -3,7 +3,7 @@ title: string_size description: 'This page explains how to use the string_size function in APL.' --- -The `string_size` function returns the number of characters in a string. You use it when you want to measure the length of text fields such as user IDs, URLs, or status codes. This function is useful for detecting anomalies, filtering out unusually long values, or analyzing patterns in textual data. +The `string_size` function returns the number of bytes in a string. You use it when you want to measure the length of text fields such as user IDs, URLs, or status codes. This function is useful for detecting anomalies, filtering out unusually long values, or analyzing patterns in textual data. For example, you can use `string_size` to detect requests with excessively long URIs, identify outlier user IDs, or monitor payload lengths in traces. @@ -14,7 +14,7 @@ If you come from other query languages, this section explains how to adjust your -In Splunk SPL, you typically use the `len` function to calculate the number of characters in a string. In APL, you use `string_size`. +In Splunk SPL, you typically use the `len` function to calculate the number of characters in a string. In APL, you use `string_size` to calculate the number of bytes in a string. ```sql Splunk example @@ -31,7 +31,7 @@ In Splunk SPL, you typically use the `len` function to calculate the number of c -In ANSI SQL, you use the `LENGTH` or `CHAR_LENGTH` function to calculate string length. In APL, the equivalent is `string_size`. +In ANSI SQL, you use the `LENGTH` or `CHAR_LENGTH` function to calculate string length. In APL, the equivalent is `string_size` to calculate the number of bytes in a string. ```sql SQL example @@ -65,7 +65,7 @@ string_size(source) ### Returns -An integer representing the number of characters in the string. If the string is empty, the function returns `0`. +An integer representing the number of bytes in the string. If the string is empty, the function returns `0`. ## Use case examples @@ -79,7 +79,7 @@ You can use `string_size` to detect unusually long URIs that might indicate an a ```kusto ['sample-http-logs'] | extend uri_length = string_size(uri) -| where uri_length > 10 +| where uri_length > 100 | project _time, method, uri, uri_length, status ``` From 09865d3c6c131f41ae1c0805f158dca0714a1dd6 Mon Sep 17 00:00:00 2001 From: Mano Toth Date: Tue, 30 Sep 2025 10:48:39 +0200 Subject: [PATCH 9/9] Fix Vale --- apl/scalar-functions/time-series/series-sin.mdx | 4 ++-- apl/scalar-functions/time-series/series-tan.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apl/scalar-functions/time-series/series-sin.mdx b/apl/scalar-functions/time-series/series-sin.mdx index f3788ed5..42a238c8 100644 --- a/apl/scalar-functions/time-series/series-sin.mdx +++ b/apl/scalar-functions/time-series/series-sin.mdx @@ -3,7 +3,7 @@ title: series_sin description: 'This page explains how to use the series_sin function in APL.' --- -The `series_sin` function in APL returns the sine of each element in a numeric array. It applies the mathematical sine function element by element, producing a new array of the same length. +The `series_sin` function in APL returns the sine of each element in a numeric array. It applies the mathematical sine function element by element, producing a new array of the same length. You use `series_sin` when you want to transform numeric sequences into their trigonometric equivalents. This is useful for signal processing, data transformations, or preparing time series data for statistical and mathematical analysis. @@ -14,7 +14,7 @@ If you come from other query languages, this section explains how to adjust your -Splunk SPL does not provide a direct equivalent to `series_sin` for arrays. Instead, you typically use the `eval` command with the `sin()` function to compute the sine of a single numeric value. In APL, `series_sin` applies `sin()` across an array in one step. +Splunk SPL doesn’t provide a direct equivalent to `series_sin` for arrays. Instead, you typically use the `eval` command with the `sin()` function to compute the sine of a single numeric value. In APL, `series_sin` applies `sin()` across an array in one step. ```sql Splunk example diff --git a/apl/scalar-functions/time-series/series-tan.mdx b/apl/scalar-functions/time-series/series-tan.mdx index e4d7ab05..1928861b 100644 --- a/apl/scalar-functions/time-series/series-tan.mdx +++ b/apl/scalar-functions/time-series/series-tan.mdx @@ -18,7 +18,7 @@ If you come from other query languages, this section explains how to adjust your -Splunk SPL does not include a direct `tan` function for arrays. In SPL, you often use `eval` with `tan()` on scalar values. In APL, `series_tan` applies the tangent function element-wise to an entire array, which makes it better suited for time series or dynamic arrays. +Splunk SPL doesn’t include a direct `tan` function for arrays. In SPL, you often use `eval` with `tan()` on scalar values. In APL, `series_tan` applies the tangent function element-wise to an entire array, which makes it better suited for time series or dynamic arrays. ```sql Splunk example