# What this PR does
Before:
<img width="281" alt="Screenshot 2023-03-23 at 16 56 42"
src="https://user-images.githubusercontent.com/20116910/227279464-c883ec05-a964-4360-bda2-3443409ca90a.png">
After:
<img width="338" alt="Screenshot 2023-03-23 at 16 57 41"
src="https://user-images.githubusercontent.com/20116910/227279476-468bffba-922a-45ea-b400-5f34d6bf0534.png">
- Add scores for overloaded users, e.g. `(+25% avg)` which means the
user is scheduled to be on-call 25% more than average for given
schedule.
- Add score for gaps, e.g. `Schedule has gaps (29% not covered)` which
means 29% of time no one is scheduled to be on-call.
- Make things easier to understand when there are gaps in the schedule,
add `(see overloaded users)` text.
- Consider events for next 52 weeks (~1 year) instead of 90 days (~3
months), so the quality report is more accurate. Also treat any balance
quality >95% as perfectly balanced. These two changes (period change and
adding 95% threshold) should help eliminate false positives for _most_
schedules.
- Modify backend & frontend so the backend returns all necessary user
information to render without using the user store.
- Move quality report generation to `OnCallSchedule` model, add more
tests.
## Which issue(s) this PR fixes
Related to https://github.com/grafana/oncall/issues/1552
## Checklist
- [x] Tests updated
- [x] `CHANGELOG.md` updated
(public docs will be added in a separate PR)
# What this PR does
## Which issue(s) this PR fixes
## Checklist
- [ ] Unit, integration, and e2e (if applicable) tests updated (N/A)
- [ ] Documentation added (or `pr:no public docs` PR label added if not
required) (N/A)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
# What this PR does
This PR, overrides Django URLValidator with a CustomURLValidator. It
just removes tld_re part from the regex, and the other behaviour remains
the same.
The CustomURLValidator is defined in common.api_helpers.utils.py file
and is utilized in custom_button.py.
Please inform me if it needs to be defined somewhere else or be
implemented with some other methods.
## Which issue(s) this PR fixes
Currently, URLValidator raises exception for URLs that don't have TLD.
This leads to not being able to use containers URL for outgoing webhooks
as they usually don't have TLD.
## Checklist
- [x] Tests updated
- [ ] Documentation added
- [x] `CHANGELOG.md` updated
---------
Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
Co-authored-by: Joey Orlando <joseph.t.orlando@gmail.com>
# What this PR does
Adds mobile app settings support to OnCall backend.
- Adds a new Django model `MobileAppUserSettings` to store push
notification settings
- Adds a new endpoint `/mobile_app/v1/user_settings` to fetch/update
settings from the mobile app
Some additional info on implementation: at first I wanted to extend the
messaging backend system to allow storing / retrieving per-user data and
implement mobile app settings based on those changes. After some thought
I decided not to extend the messaging backend system and have this as
functionality specific to the `mobile_app` Django app. Currently the
messaging backend system is used by the backend and plugin UI, but
mobile app settings are specific only to the mobile app and not
configurable in the plugin UI.
**tldr: wanted to extend messaging backend system, but decided not to do
that**
# Usage
## Get settings via API
`GET /mobile_app/v1/user_settings`
Example response:
```json
{
"default_notification_sound_name": "default_sound", # sound name without file extension
"default_notification_volume_type": "constant",
"default_notification_volume": 0.8,
"default_notification_volume_override": false,
"important_notification_sound_name": "default_sound_important", # sound name without file extension
"important_notification_volume_type": "constant",
"important_notification_volume": 0.8,
"important_notification_override_dnd": true
}
```
## Update settings via API
`PUT /mobile_app/v1/user_settings` - see example response above for
payload shape.
Note that sound names must be passed without file extension. When
sending push notifications, the backend will add `.mp3` to sound names
and pass it to push notification data for Android. For iOS, sound names
will be suffixed with `.aiff` to be used by APNS.
## Get settings from notification data for Android
All the settings from example response will be available in push
notification data (along with `orgId`, `alertGroupId`, `title`, etc.).
Fields `default_notification_volume`,
`default_notification_volume_override` and
`important_notification_volume` , `important_notification_override_dnd`
will be converted to strings due to FCM limitations.
Fields `default_notification_sound_name` and
`important_notification_sound_name` will be suffixed with `.mp3` in push
notification data.
## iOS limitations
While Android push notifications are handled purely on the mobile app
side, iOS notifications are sent via APNS which imposes some
limitations.
- Notification volume cannot be overridden for non-critical
notifications (so fields `default_notification_volume_override` and
`default_notification_volume` will be disregarded for iOS notifications)
- It's not possible to control volume type (i.e. "constant" vs
"intensifying") via APNS. A possible workaround is to have different
sound files for "constant" and "intensifying" and pass that as
`default_notification_sound_name` / `important_notification_sound_name`.
# Which issue(s) this PR fixes
Related to https://github.com/grafana/oncall-private/issues/1602
# Checklist
- [x] Tests updated
- [x] No changelog updates since the changes are not user-facing
# What this PR does
* api returns all the resources available to the user by default
* substitutes `team switcher` with `multi-select team filter`
* allow referencing between integrations - escalations chains -
[schedules, outgoing webhooks] across teams
https://user-images.githubusercontent.com/2262529/225634581-2d2e8af2-15ce-4c01-a90e-8267d98f5a23.mov
## Which issue(s) this PR fixes
## Checklist
- [ ] Tests updated
- [ ] Documentation added
- [ ] `CHANGELOG.md` updated
---------
Co-authored-by: Maxim <maxim.mordasov@grafana.com>
Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
Track all webhook responses data, and allow using this between
alertgroup-related webhooks (e.g. use firing webhook response data when
templating the acknowledge webhook request data).
NOTE: dropping the table is not backwards compatible but the feature is
not enabled (and in any case it would drop log entries only used for
status display)
# Which issue(s) this PR fixes
Previously if you had an Escalation Chain named "Something Critical" and
tried searching for "Critical", it would return no results. This was
because the backend was using a "starts-with" search on the `name`
attribute.
This PR changes that to use "partial searching" + adds a few e2e test
cases.
## Checklist
- [x] Tests updated
- [ ] Documentation added (N/A)
- [x] `CHANGELOG.md` updated
# What this PR does
This PR:
- modifies the `check_escalation_finished_task` celery task to:
- do stricter escalation validation based on the alert group's
escalation snapshot (see the `audit_alert_group_escalation` method in
`engine/apps/alerts/tasks/check_escalation_finished.py` for the
validation logic)
- use a read-only database for querying alert-groups if one is
configured, otherwise use the "default" one
- ping a configurable heartbeat (new env var
`ALERT_GROUP_ESCALATION_AUDITOR_CELERY_TASK_HEARTBEAT_URL` added)
- increase the task frequency from every 10 to every 13 minutes (this
can be configured via an env variable)
- adds public documentation on how to configure this auditor task
- modifies the local celery startup command to properly take into
consideration all celery related env vars (similar to the ones we use in
`engine/celery_with_exporter.sh`; this made it easier to enable `celery
beat` locally for testing)
- removes the following code:
- removes references to `AlertGroup.estimate_escalation_finish_time` and
marks the model field as deprecated using the [`django-deprecate-fields`
library](https://pypi.org/project/django-deprecate-fields/). This field
was only used for the previous version of this validation task
- `EscalationSnapshotMixin.calculate_eta_for_finish_escalation` was only
used to calculate the value for
`AlertGroup.estimate_escalation_finish_time`
- `calculate_escalation_finish_time` celery task
## Which issue(s) this PR fixes
https://github.com/grafana/oncall-private/issues/1558
## Checklist
- [x] Tests updated
- [x] Documentation added
- [x] `CHANGELOG.md` updated
# What this PR does
Allows passing `null` as a value for `escalation_chain` when creating
routes via the public API.
## Which issue(s) this PR fixes
This is needed to unblock https://github.com/grafana/oncall/pull/1555 +
creating a route without an escalation chain is possible in the web UI,
so this PR makes the public API more consistent with the web UI.
## Checklist
- [x] Tests updated
- [x] Documentation added
- [x] `CHANGELOG.md` updated
This PR add Inbound Email integration.
It designed to support some variety of ESPs, but in prod we will use
Mailgun, so locally I tested it only with mailgun ESP.
**Important:**
To make it work on different clusters I'm planning to provide different
email domains for different regions, like ....@us.oncall.grafana.net,
...@eu.oncall.grafana.net
---------
Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
# What this PR does
Adds a new filter on alert groups page that allows to filter alert
groups by escalation chain.
<img width="1204" alt="Screenshot 2023-03-13 at 22 42 00"
src="https://user-images.githubusercontent.com/20116910/224848730-ef753856-a050-4acb-ba36-498d2bca2b4f.png">
## Which issue(s) this PR fixes
This should be useful on it's own as it's giving more filtering
capabilities, but it also could be useful for
https://github.com/grafana/oncall/issues/1300, if PD rulesets are
migrated to a single integration with multiple escalation chains.
## Checklist
- [x] Tests updated
- [x] `CHANGELOG.md` updated
Related to #828
- Enable web UI for API/Terraform schedules to add overrides
- Refactor backend to add a flag toggling between web-based and
iCal-based overrides (these options are mutually exclusive)
Also updated read-only tooltips (related to #1483)
# What this PR does
This PR modify is_insight_logs_enabled to check for a stack cluster
instead of DynamicSetting
## Checklist
- [ ] Tests updated
- [ ] Documentation added
- [ ] `CHANGELOG.md` updated
# What this PR does
Emails fails if the alert title has a newline char
## Which issue(s) this PR fixes
Grafana tickets : 81244
## Checklist
- [x] Tests updated
- [x] `CHANGELOG.md` updated
---------
Co-authored-by: Vadim Stepanov <vadimkerr@gmail.com>
# Which issue(s) this PR fixes
Solves the (rare) issue where a user could potentially have > 1
mobileapp auth token, leading to 500 errors when trying to interact w/
the authtoken (ex. disconnect a mobile app from a user's profile):
```shell
2023-03-07 10:12:13 source=engine:app google_trace_id=e14bf933d634068a48caf093ce43c7f5/5550677047491218352 logger=django.request Internal Server Error: /api/internal/v1/users/U6WJ3BRLM1TR7/unlink_backend
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/etc/app/apps/api/views/user.py", line 453, in unlink_backend
backend.unlink_user(user)
File "/etc/app/apps/mobile_app/backend.py", line 34, in unlink_user
token = MobileAppAuthToken.objects.get(user=user)
File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 439, in get
raise self.model.MultipleObjectsReturned(
apps.mobile_app.models.MobileAppAuthToken.MultipleObjectsReturned: get() returned more than one MobileAppAuthToken -- it returned 2!
```
## Checklist
- [x] Tests updated
- [ ] Documentation added (N/A)
- [x] `CHANGELOG.md` updated
# What this PR does
Prohibits creating & updating overrides in the past when using the web
UI.
## Which issue(s) this PR fixes
https://github.com/grafana/oncall/issues/1221
## Checklist
- [x] Tests updated
- [x] `CHANGELOG.md` updated
It's a duplicate of LICENSE env var
**What this PR does**:
Remove OSS_INSTALLATION env var in favour of LICENSE env var. Also, I
refactored features tests a little. From my point of view it makes
little sense to test if all features are disabled or enabled. Better to
test specific use-case (e.g. oss installation).
Also to test that all features are disabled it is needed to set LICENSE
equals cloud license, which makes test confusing.
**Checklist**
- [x] Tests updated
- [ ] Documentation added
- [ ] `CHANGELOG.md` updated