Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,18 @@ State machine-related issues often require several data checks and conditional l
2. [Building a Monitor](./docs/monitor.md)
1. [Sample Monitor](./docs/sample_monitor.md)
3. [Querying data from databases](./docs/querying.md)
4. [Registering a monitor](./docs/monitor_registering.md)
5. Deployment
4. [Validating a monitor](./docs/monitor_validating.md)
5. [Registering a monitor](./docs/monitor_registering.md)
6. Deployment
1. [Configuration](./docs/configuration.md)
2. [Configuration file](./docs/configuration_file.md)
3. [How to run](./docs/how_to_run.md)
6. [Monitoring Sentinela](./docs/monitoring_sentinela.md)
7. [Plugins](./docs/plugins/plugins.md)
7. [Monitoring Sentinela](./docs/monitoring_sentinela.md)
8. [Plugins](./docs/plugins/plugins.md)
1. [AWS](./docs/plugins/aws.md)
2. [Postgres](./docs/plugins/postgres.md)
2. [Slack](./docs/plugins/slack.md)
8. Interacting with Sentinela
9. Interacting with Sentinela
1. [HTTP server](./docs/http_server.md)
9. Special cases
10. Special cases
1. [Dropping issues](./docs/dropping_issues.md)
93 changes: 87 additions & 6 deletions docs/http_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,113 @@ Exposes Prometheus-formatted metrics, enabling external monitoring and observabi
# Interaction routes
These routes are available only when the container deployment includes the **Controller** component.

## List monitors
**`GET /monitors/list`**

Returns a list of all monitors currently registered with the `id`, `name` and `enabled` fields for each monitor.

Response example:
```json
[
{
"id": 123,
"name": "monitor_name",
"enabled": true
},
{
"id": 124,
"name": "another_monitor",
"enabled": false
}
]
```

## Get monitor
**`GET /monitor/{monitor_name}`**

Returns the monitor details for the monitor with the provided `monitor_name`.

Response example:
```json
{
"id": 123,
"name": "monitor_name",
"enabled": true,
"code": "...",
"additional_files": {"file_name.txt": "..."}
}
```

## Disable monitor
**`POST /{monitor_name}/disable`**
**`POST /monitor/{monitor_name}/disable`**

Disable the monitor with the provided `monitor_name`.

## Enable monitor
**`POST /{monitor_name}/enable`**
**`POST /monitor/{monitor_name}/enable`**

Enable the monitor with the provided `monitor_name`.

## Validate monitor
**`POST /monitor/validate`**

Validate the monitor code provided without registering it.

For more information, check the [Validating a monitor](./monitor_validating.md) documentation.

Request body example:
```json
{
"monitor_code": "...",
}
```

Response example:
```json
{
"status": "monitor_validated"
}
```

## Register monitor
**`POST /monitor/register/{monitor_name}`**

Register the monitor with the provided `monitor_name`.

For more information, check the [Registering a monitor](./monitor_registering.md) documentation.

Request body example:
```json
{
"monitor_code": "...",
"additional_files": {"file_name.txt": "..."}
}
```

Response example:
```json
{
"status": "monitor_registered",
"monitor_id": 123
}
```

## Acknowledge alert
**`POST /{alert_id}/acknowledge`**
**`POST /alert/{alert_id}/acknowledge`**

Acknowledge the alert with the provided `alert_id`.

## Lock alert
**`POST /{alert_id}/lock`**
**`POST /alert/{alert_id}/lock`**

Lock the alert with the provided `alert_id`.

## Solve alert
**`POST /{alert_id}/solve`**
**`POST /alert/{alert_id}/solve`**

Solve the alert with the provided `alert_id`.

## Drop issue
**`POST /{issue_id}/drop`**
**`POST /issue/{issue_id}/drop`**

Drop the issue with the provided `issue_id`.
38 changes: 30 additions & 8 deletions docs/monitor_registering.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ A monitor consists of:
- **Optional Additional Files**: Supporting resources used during the monitor's execution, such as SQL query files or other data files.

## Registration Process
To register a monitor, use the POST method with the `monitors/register/` route, providing all the required information in the request.
```
POST monitors/register/{monitor_name}
```

1. **Request URL**:
Format the URL as `monitors/register/{monitor_name}`, where `{monitor_name}` is the name of the monitor being created or updated.
Example: `monitors/register/my_monitor`
Parameters:
- `{monitor_name}` is the name of the monitor being created or updated.

2. **Request Payload**:
The payload should include the following fields:
- `monitor_code`: The content of the monitor’s main `.py` file content.
- `additional_files`: Optional field with an object where the keys are the names of additional files, and the values are their content.
The payload should include the following fields:
- `monitor_code`: The content of the monitor’s main `.py` file content.
- `additional_files`: Optional field with an object where the keys are the names of additional files, and the values are their content.

Example:
```json
Expand All @@ -30,6 +30,28 @@ Example:
}
```

## Responses
The response will contain the status of the registration process. The field `status` will be set to `monitor_registered` if the monitor was successfully registered and the monitor id will be in the `monitor_id` field.

Example:
```json
{
"status": "monitor_registered",
"monitor_id": 123
}
```

If the registration fails, the `status` field will be set to `error` and the field `message` will contain the error message. Depending on the error, additional fields may be present to help diagnose the issue.

Example:
```json
{
"status": "error",
"message": "Module didn't pass check",
"error": "Monitor 'my_monitor' has the following errors:\n 'monitor_options' is required"
}
```

## Monitor register tool
To simplify the registration process, a Python script is available in the `tools` folder.

Expand Down
38 changes: 38 additions & 0 deletions docs/monitor_validating.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Validating a monitor
Validating a monitor is a important step before registering it. This process ensures that the monitor code is correct and can be executed by Sentinela. This is useful when using a deployment pipeline to ensure that the monitor is correctly implemented before being deployed.

## Validation Process
```
POST monitors/validate/
```

The payload should include the following fields:
- `monitor_code`: The content of the monitor’s main `.py` file content.

Example:
```json
{
"monitor_code": "...",
}
```

## Responses
The response will contain the status of the validation process. The field `status` will be set to `monitor_validated` if the monitor was successfully validated.

Example:
```json
{
"status": "monitor_validated",
}
```

If the validation fails, the `status` field will be set to `error` and the field `message` will contain the error message. Depending on the error, additional fields may be present to help diagnose the issue.

Example:
```json
{
"status": "error",
"message": "Module didn't pass check",
"error": "Monitor has the following errors:\n 'monitor_options' is required"
}
```
2 changes: 1 addition & 1 deletion src/components/http_server/monitor_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ async def monitor_validate(request: Request) -> Response:
error_response = {
"status": "error",
"message": "Module didn't pass check",
"error": e.get_error_message(),
"error": e.get_error_message(include_monitor_name=False),
}
return web.json_response(error_response, status=400)
except Exception as e:
Expand Down
7 changes: 5 additions & 2 deletions src/components/monitors_loader/monitors_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ def __init__(self, monitor_name: str, errors_found: list[str], *args: object) ->
self.monitor_name = monitor_name
self.errors_found = errors_found

def get_error_message(self) -> str:
def get_error_message(self, include_monitor_name: bool = True) -> str:
"""Get the error message for the module validation errors"""
error_message = f"Monitor '{self.monitor_name}' has the following errors:\n "
if include_monitor_name:
error_message = f"Monitor '{self.monitor_name}' has the following errors:\n "
else:
error_message = "Monitor has the following errors:\n "
error_message += "\n ".join(self.errors_found)
return error_message

Expand Down
6 changes: 2 additions & 4 deletions tests/components/http_server/test_monitor_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,8 @@ async def test_monitor_validate_dataclass_validation_error():
}


async def test_monitor_validate_check_fail(mocker):
async def test_monitor_validate_check_fail():
"""The 'monitor validate' route should return an error if the provided module code is invalid"""
check_monitor_spy: MagicMock = mocker.spy(monitors_loader, "check_monitor")

monitor_code = "import time"

request_payload = {"monitor_code": monitor_code}
Expand All @@ -279,7 +277,7 @@ async def test_monitor_validate_check_fail(mocker):
"message": "Module didn't pass check",
"error": "\n".join(
[
f"Monitor '{check_monitor_spy.call_args[0][0]}' has the following errors:",
"Monitor has the following errors:",
" 'monitor_options' is required",
" 'issue_options' is required",
" 'IssueDataType' is required",
Expand Down