Skip to content

Run Check minimal#30

Closed
tgubler9 wants to merge 33 commits intomasterfrom
run_checks_minimal
Closed

Run Check minimal#30
tgubler9 wants to merge 33 commits intomasterfrom
run_checks_minimal

Conversation

@tgubler9
Copy link
Collaborator

@tgubler9 tgubler9 commented Nov 17, 2025

Overview

Tasks

  • Minimal implementation of run_checks
  • Tests for Dynamo DB passing
  • Tests for Logs passing

@tgubler9 tgubler9 self-assigned this Nov 17, 2025
@tgubler9 tgubler9 added the enhancement New feature or request label Nov 17, 2025
@codecov
Copy link

codecov bot commented Dec 24, 2025

Codecov Report

❌ Patch coverage is 95.13889% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.54%. Comparing base (2607688) to head (2a8bebe).

Files with missing lines Patch % Lines
src/critic/tasks.py 90.19% 3 Missing and 2 partials ⚠️
src/critic/libs/ddb.py 85.71% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #30      +/-   ##
==========================================
+ Coverage   90.06%   91.54%   +1.48%     
==========================================
  Files          13       14       +1     
  Lines         292      426     +134     
  Branches       20       29       +9     
==========================================
+ Hits          263      390     +127     
- Misses         24       28       +4     
- Partials        5        8       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tgubler9 tgubler9 marked this pull request as ready for review January 14, 2026 23:06
Copy link
Owner

@calebsyring calebsyring left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Left some more comments. If you want to discuss in a Slack huddle, let me know.

Comment on lines +95 to +98
if uptime_log.resp_code is None:
uptime_log.resp_code = 0
if uptime_log.latency_secs is None:
uptime_log.latency_secs = -1
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting. If we don't have a response code or latency secs (because there was some kind of error that means we didn't get a response), just setting response code to zero and latency secs to -1 doesn't give the user much information.

I think I'd like to put some kind of string representation of the exception in an attribute on UptimeLog.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is also a whole nother feature that should be done when we implement the check assertions feature

) # this will handle exceptions from http, but not 404 or other errors


def run_checks(monitor: UptimeMonitorModel, http_client: httpx.Client):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be an invokable mu task. See https://github.com/level12/mu/blob/master/examples/tasker/app.py

Keep in mind that we can't pass UptimeMonitorModel objects through the AWS infrastructure, so this probably just needs to take a project_id and slug and get the uptime monitor from the db.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should work better now

pyproject.toml Outdated
'hatch',
'ruff',
"pytest-httpx>=0.36.0",
"ruff==0.14.14",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why pin ruff?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting an issue with nox, when I didnt do this, but I can revert this

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please revert the ruff pin.



class UptimeLog(BaseModel):
monitor_id: str # for now we just combine the monitor and slug
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment should say "combine the project_id and slug"

Comment on lines 39 to 49
monitor_table = dynamodb.Table(UptimeMonitorTable.namespace(UPTIME_MONITOR))

monitor.next_due_at = monitor.next_due_at + timedelta(minutes=monitor.frequency_mins)

# if paused update the time and return
if monitor.state == MonitorState.paused:
monitor_table.update_item(
Key={'project_id': monitor.project_id, 'slug': monitor.slug},
UpdateExpression='SET next_due_at = :n',
ExpressionAttributeValues={':n': monitor.next_due_at.isoformat()},
)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the point of the ddb lib / tables file is to keep query syntax out of logic files.

Let's add an update_item method to the Table base class in the ddb lib.

monitor_id: str = monitor.project_id + monitor.slug
uptime_log = UptimeLog(
monitor_id=(monitor_id),
timestamp=logtime_stamp,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's all normalized to UTC, so this can just be timestamp=datetime.now(UTC). You don't need to take into the next_due_at timezone.

return cls.model(**deserialize(item))

@classmethod
def query(cls, partition_value: str | int) -> list[BaseModel]:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is necessary. It may be in the future. But where you use it below it looks like you could just use the get method.

Copy link
Collaborator Author

@tgubler9 tgubler9 Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot because I need the sort key which is generated in the run_checks , i supposed I might be able to mock it, but I dont see its important to do it that way and get rid of a potentially useful util. I imagine you will eventually be using query sometime in the future

Comment on lines 1 to 7
from polyfactory.factories.pydantic_factory import ModelFactory

from critic.models import UptimeMonitorModel


class UptimeMonitorFactory(ModelFactory[UptimeMonitorModel]):
__model__ = UptimeMonitorModel
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete this. We'll use libs/testing.py instead.

Comment on lines +72 to +86
in_data = {
'project_id': '6033aa47-a9f7-4d7f-b7ff-a11ba9b34474',
'slug': 'my-monitor',
'url': 'https://example.com/health',
'frequency_mins': 5,
'consecutive_fails': 0,
'next_due_at': '2025-11-10T20:35:00Z',
'timeout_secs': 30,
'assertions': {'status_code': 200, 'body_contains': 'OK'},
'failures_before_alerting': 2,
'alert_slack_channels': ['#ops'],
'alert_emails': ['alerts@example.com'],
'realert_interval_mins': 60,
}
in_data = UptimeMonitorModel(**in_data)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this file we should probably be using UptimeMonitorFactory.build instead of these dicts. Initially the dicts functioned as a sort of model test, but model tests should be separate.

But I think you're going to end up removing this test if you remove the unnecessary query method anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but this can be addressed on another pr

@@ -0,0 +1,108 @@
import logging
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests should go in test_tasks.py

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to modularize the tests. It seems neater and if there are more tasks added, that file is going to be way too big

@tgubler9 tgubler9 requested a review from calebsyring January 30, 2026 02:24
@calebsyring calebsyring mentioned this pull request Jan 30, 2026
@calebsyring
Copy link
Owner

Closing in favor of #61

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants