Commit Graph

1068 Commits

Author SHA1 Message Date
Klaas van Schelven
615d2da4c8 Chache stored_event_count (on Issue and Projet)
"possibly expensive" turned out to be "actually expensive". On 'emu', with 1.5M
events, the counts take 85 and 154 ms for Project and Issue respectively;
bottlenecking our digestion to ~3 events/s.

Note: this is single-issue, single-project (presumably, the cost would be lower
for more spread-out cases)

Note on indexes: Event already has indexes for both Project & Issue (though as
the first item in a multi-column index). Without checking further: that appears
to not "magically solve counting".

This commit also optimizes the .count() on the issue-detail event list (via
Paginator).

This commit also slightly changes the value passed as `stored_event_count` to
be used for `get_random_irrelevance` to be the post-evication value. That won't
matter much in practice, but is slightly more correct IMHO.
2025-02-06 16:24:25 +01:00
Klaas van Schelven
d0f2a0c686 immediate_semaphore.acquire 10s timeout
as explained in the comment
2025-02-06 14:24:06 +01:00
Klaas van Schelven
415da94093 transaction semaphore: release in a finally block
transaction.commit can fail (in fact: e.g. FK checks _only_ happen on-commit)
such failures _must_  release the semaphore, otherwise the next request
will be stuck forever.
2025-02-06 14:18:46 +01:00
Klaas van Schelven
95e8aba23e make_consistent: set never_evict
"in normal environments" this shouldn't be necessary. But I recently played with
(backwards) migrations, and thus violated the expectation that "adding RunPython to the
squashed migrations will not be necessary because no one will be having events _and_
using the squashed migration. (I still think that general idea holds, but it won't if
you move back in time through the migrations explicitly).

I considered adding a warning to the *_b_* migrations, but in the end considered it
unnessary, since I would be the only user of such a warning. (Just adding the warning to
the *_b_* migrations is enough, since moving back through the RunPython-route is already
impossible because 'backwards' is not implemented in those as per:

```
git ls-files | grep py | x grep RunPython -l
```
2025-02-06 14:04:41 +01:00
Klaas van Schelven
b6a5c75bb5 Move 'DESIGN*' docs out of repo
these were more like sketches than proper documents; if I upgrade
them to something more serious they may very well reappear in some
form
2025-02-05 09:31:20 +01:00
Klaas van Schelven
be0da355ac Move 'DESIGN' docs related to performance findings over to 'performance-tests' repo 2025-02-05 09:29:15 +01:00
Klaas van Schelven
828a696c22 Remove 'snappea design' document
superceded by https://www.bugsink.com/blog/snappea-design/
2025-02-05 09:17:14 +01:00
Klaas van Schelven
86e8c4318b Add indexes on fields on which we order and vice versa
Triggered by issue_event_list being more than 5s on "emu" (my 1,500,000 event
test-machine). Reason: sorting those events on non-indexed field. Switching
to a field-with-index solved it.

I then analysed (grepped) for "ordering" and "order_by" and set indexes
accordingly and more or less indiscriminately (i.e. even on tables that are
assumed to have relatively few rows, such as Project & Team).
2025-02-04 21:19:24 +01:00
Klaas van Schelven
24e204edcc Mention Security Policiy in CONTRIBUTING.md 2025-02-04 13:16:58 +01:00
Klaas van Schelven
0b42d3ff1e Semi-manual squash-migrations
## Goal

Reduce the number of migrations for _fresh installs_ of Bugsink. This implies: squash as
broadly as possible.

## How?

"throw-away-and-rerun". In particular, for a given app:

* throw away the migrations from some starting point up until and including the last one.
* run "makemigrations" for that app. Django will see what's missing and just redo it
* rename to 000n_b_squashed or similar.
* manually set a `replaces` list on the migration to the just-removed migrations
* manually check dependencies; check that they are:
    * as low as possible, e.g. an FK should only depend on existence. this reduces the
      risk of circular dependencies.
    * pointing to "original migrations", i.e. not to a just-created squashed migration.
      because the squashed migrations "contain a lot" they increase the risk of circular
      dependencies.
* restore (git checkout) the thrown-away migration

## Further tips:

* "Some starting point" is often not 0000, but some higher number (see e.g. the outcome
  in the present commit). Leaving the migrations for creation of base models (Event,
  Issue, Project) in place saves you from a lot of circular dependency problems.
* Move db.sqlite3 out of the way to avoid superfluous warnings.

## RunPython worries

I grepped for RunPython in the replaced migrations, with the following results:

* phonehome's create_installation_id was copied-over to the squashed migration.
* all others where ignored, because:
    * they "do something with events", i.e. only when events are present will they have
      an effect. This means they are no-ops for _new installs_.
    * for existing installs, for any given app, they will only be missed (replaced) when
      the first replaced migration is not yet executed.

I used the following command (reading from the bottom) to establish that this means only
people that did a fresh install after 8ad6059722 (June 14, 2024), but before
c01d332e18 (July 16) _and then never did any upgrades_ would be affected. There are no
such people.

git log --name-only \
    events/migrations/0004_event_irrelevance_for_retention.py \
    issues/migrations/0004_rename_event_count_issue_digested_event_count.py \
    phonehome/migrations/0001_initial.py \
    projects/migrations/0002_initial.py \
    teams/migrations/0001_initial.py

Note that the above observation still be true for the next squashmigration (assuming
squashing starting at the same starting migrations).

## Cleanup of the replaced migrations

Django says:

> Once you’ve squashed your migration, you should then commit it alongside the
> migrations it replaces and distribute this change to all running instances of your
> application, making sure that they run migrate to store the change in their database.

Given that I'm not in control of all running instances of my application, this means the
cleanup must not happen "too soon", and only after announcing a migration path ("update
to version X before updating to version Y").

## Roads not taken

Q: Why not just do squashmigrations? A: It didn't work reliably (for me), presumably b/c
of the high number of strongly interdependant apps in combination with some RunPython.

Seen after I was mostly done, not explored seriously (yet):

* https://github.com/3YOURMIND/django-replace-migrations
* https://pypi.org/project/django-squash/
* https://django-extensions.readthedocs.io/en/latest/delete_squashed_migrations.html
2025-02-03 16:06:17 +01:00
Klaas van Schelven
0ec809cbb3 Simplify migration deps and document them 2025-02-03 14:04:44 +01:00
Klaas van Schelven
fd7eae681d Remove migrations directory from modelless apps 2025-02-03 13:05:20 +01:00
Klaas van Schelven
19bb91b636 Fix: set digested_at time correctly 2025-01-31 16:23:09 +01:00
Klaas van Schelven
3dec96509b Show event.grouping.grouping_key in the event details UI 2025-01-31 16:16:47 +01:00
Klaas van Schelven
9ee623de6b Add Event.grouping field and fill it
An event always has a single (automatically calculated) Grouping associated with it.
We add this info to the Event model (we'll soon display it in the UI, and as per the
now-removed comment it's simply the consistent thing to do)
2025-01-31 16:16:07 +01:00
Klaas van Schelven
c42aa9118a Describe role of Grouping and how it relates to Issue
third time's a charm (5e5b53abed, 48307daa0f)
2025-01-31 15:25:18 +01:00
Klaas van Schelven
672bbde4ba Fix DeprecationWarning ('warn') 2025-01-31 13:18:02 +01:00
Klaas van Schelven
43a6049180 Fix warning in tests (unclosed file) 2025-01-31 13:17:20 +01:00
Klaas van Schelven
102070bf24 Show transaction in the event details 2025-01-31 13:09:54 +01:00
Klaas van Schelven
d2f4be193f Comment about logentry.* in the event details 2025-01-31 13:03:13 +01:00
Klaas van Schelven
b57ccec4c6 Show 'handled' and 'mechanism' in the event details 2025-01-31 13:02:49 +01:00
Klaas van Schelven
472c19130a typo in comment 2025-01-31 12:11:34 +01:00
Klaas van Schelven
7c142e4d8e Document security-tradeoff around ALLOWED_HOSTS 2025-01-31 10:50:51 +01:00
Klaas van Schelven
064a8b110c eat_your_own_dogfood: custom fingerprint for server-level exceptions 2025-01-31 10:04:17 +01:00
Klaas van Schelven
052a47820a Unpin development dependencies
the trade-off for reproducability/busywork is different for
development deps; for those bleeding edge is just fine, because
the bleeding will be by me and the consequences are minor.
And removing the pin removes some dependabot busywork
2025-01-30 20:52:48 +01:00
Klaas van Schelven
96da3c0336 Create SECURITY.md 2025-01-30 15:23:23 +01:00
Klaas van Schelven
2336900dcb Update requirements to ==realmajor.realminor.* pattern
Trying to balance 'upgrade fatigue', 'stale deps' and 'being undefined'

With the present pattern:

* Only 'used by me' is defined; 'transitive dependencies' are left to upgrade.
* Dependabot is responsible for the major/minor updates; this will trigger
    a PR & CI, and thus the required explicitness (but also: some work)
* Patch versions are assumed to be compatible, and are left to upgrade in the
    background ('automatically')
2025-01-30 15:12:54 +01:00
Klaas van Schelven
b5d9fbb8eb Dependabot: no npm pull requests 2025-01-30 15:04:56 +01:00
Klaas van Schelven
b80bff33fd Merge pull request #31 from bugsink/dependabot/pip/python-packages-5263e0e9c3
Bump the python-packages group with 2 updates
2025-01-30 15:02:41 +01:00
dependabot[bot]
f6ae7b1957 Bump the python-packages group with 2 updates
Updates the requirements on [jsonschema](https://github.com/python-jsonschema/jsonschema) and [pygments](https://github.com/pygments/pygments) to permit the latest version.

Updates `jsonschema` to 4.23.0
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.19.0...v4.23.0)

Updates `pygments` to 2.19.1
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.16.0...2.19.1)

---
updated-dependencies:
- dependency-name: jsonschema
  dependency-type: direct:production
  dependency-group: python-packages
- dependency-name: pygments
  dependency-type: direct:production
  dependency-group: python-packages
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-30 13:57:15 +00:00
Klaas van Schelven
630f0c029b Dependabot: pin django-tailwind to 3.6
https://github.com/timonweb/django-tailwind/issues/210
2025-01-30 14:50:59 +01:00
Klaas van Schelven
8ad4a2b522 Dependabot 'ignore django' rule: final try, using explicit version-range to ignore 2025-01-30 14:42:41 +01:00
Klaas van Schelven
4d0310c65b Dependabot 'ignore django' rule: give up, try via requirements.txt itself 2025-01-30 14:36:01 +01:00
Klaas van Schelven
7012dc07f1 Dependabot 'ignore django' rule: try lowercase
Uppercase 'Django' did not work
2025-01-30 14:21:03 +01:00
Klaas van Schelven
c9e33f93a4 Dependabot; initial setup 2025-01-30 14:12:59 +01:00
Klaas van Schelven
7d804579ff Add 3 more apps to 'sentry phonehome setup'
necessary as per the comment above 'in_app_include';
2025-01-30 09:01:42 +01:00
Klaas van Schelven
9ae6233965 Wrap 2 more BASE_URL usages with str()
In 59372aba33 a lazily evaluated BASE_URL tool was introduced.
I found 2 more cases in which BASE_URL was not "collapsed into a
string" magically by `__add__`, one of which actually causing
an `Object of type TenantBaseURL is not JSON serializable`
2025-01-30 08:52:38 +01:00
Klaas van Schelven
cf3b588eb7 Setting of value: outside 'try'
if inside, an error in self.get_tenant() results in an
non-executable finally block.

Also: make the 'del' more defensive by making it a 'pop'
2025-01-29 13:37:31 +01:00
Klaas van Schelven
01578d7829 Add print_phonehome management command
useful for:

* figuring out what phonehome will report
* getting some stats on-screen locally
2025-01-29 10:06:41 +01:00
Klaas van Schelven
452ac806b7 Raise from None
See https://www.bugsink.com/blog/using-raise-from-none-in-python/
in this case: PermissionDenied so clearly implies 'not found in db' that
the details of not finding are truly immaterial
2025-01-29 09:09:05 +01:00
Klaas van Schelven
59372aba33 First version of multi-tenant setup (EE) 2025-01-29 09:04:19 +01:00
Klaas van Schelven
d30c3ad704 Drop 'no contributions' rule; add CLA instead
CLA generated with https://contributoragreements.org/u2s/2r8vzl3ap4

Fixes #27
2025-01-24 16:12:07 +01:00
Klaas van Schelven
7f61c555a2 'This might mean' refers to 'No open issues'; make this show in the interface 2025-01-24 11:47:12 +01:00
Klaas van Schelven
705cf43fc2 Remove doc-TODO 2025-01-24 11:43:28 +01:00
Klaas van Schelven
cf23ba707e Warn about top-level settings 2025-01-24 11:40:13 +01:00
Klaas van Schelven
c6adfd7511 Remove 'slug' field from team
it was unused; probably added analogously with project (where it _is_ used)
2025-01-24 10:21:39 +01:00
Klaas van Schelven
ba7472321a Fix broken import
broken in ae9cb209a5
2025-01-23 12:30:00 +01:00
Klaas van Schelven
6c39c0b0af Reset password: as a command 2025-01-23 12:14:46 +01:00
Klaas van Schelven
ae9cb209a5 Create 'bsmain' (for bugsink-main) app to hold commands
As had been noted on some of the commands, 'ingest' was not the best place for
them.  However, [project-level apps are not supported in
Django](https://forum.djangoproject.com/t/allow-project-to-have-management-commands/5220/2)
So just create a 'main' app. I want to qualify it as 'myproject-main' though, to avoid
further unqualified global namespace pollution. And I want to avoid prefixing with 'bugsink'
b/c that's annoying for tab-completion. So 'bs' it is.

I've moved all commands over; even though a case could be made that the "feeding" commands
(raise_exception, send_json, stress_test) are somewhat related to ingestion, that's not
a very good case :-)
2025-01-23 11:55:34 +01:00
Klaas van Schelven
7727bc6168 Show dsn-as-understood when failing to authenticate in error message
status code for PermissionDenied rather than 404 also
2025-01-22 22:15:53 +01:00