Coverage for src/local_deep_research/database/models/logs.py: 94%

17 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-06 15:42 +0000

1""" 

2Logging model for storing application logs. 

3 

4The ``Journal`` model used to live here too but was moved to 

5``journal.py`` for discoverability — it's unrelated to the 

6``ResearchLog`` table this file owns. Compat imports of 

7``from ...database.models.logs import Journal`` still work via the 

8re-export below. 

9""" 

10 

11from sqlalchemy import ( 

12 Column, 

13 ForeignKey, 

14 Index, 

15 Integer, 

16 Sequence, 

17 String, 

18 Text, 

19) 

20from sqlalchemy_utc import UtcDateTime, utcnow 

21 

22from .base import Base 

23from .journal import Journal # noqa: F401 — compat re-export 

24 

25 

26class ResearchLog(Base): 

27 """ 

28 Logging table for all research operations. 

29 

30 All logging from research operations, including debug messages, 

31 errors, and milestones are stored here. 

32 """ 

33 

34 __tablename__ = "app_logs" 

35 __table_args__ = ( 

36 Index( 

37 "ix_app_logs_research_id_timestamp_id", 

38 "research_id", 

39 "timestamp", 

40 "id", 

41 ), 

42 ) 

43 

44 id = Column(Integer, Sequence("reseach_log_id_seq"), primary_key=True) 

45 

46 timestamp = Column(UtcDateTime, server_default=utcnow(), nullable=False) 

47 message = Column(Text, nullable=False) 

48 # Module that the log message came from. 

49 module = Column(Text, nullable=False) 

50 # Function that the log message came from. 

51 function = Column(Text, nullable=False) 

52 # Line number that the log message came from. 

53 line_no = Column(Integer, nullable=False) 

54 # Log level. 

55 level = Column(String(32), nullable=False) 

56 research_id = Column( 

57 String(36), # UUID as string 

58 ForeignKey("research_history.id", ondelete="CASCADE"), 

59 nullable=True, 

60 index=True, 

61 ) 

62 

63 def __repr__(self): 

64 return f"<ResearchLog({self.level}: '{self.message[:50]}...')>"