• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SamhammerAG / sag_py_logging_logstash / 19758108154

28 Nov 2025 08:21AM UTC coverage: 29.831% (+2.7%) from 27.099%
19758108154

push

github

web-flow
Kit 4554 Introduce ruff (#12)

* KIT-4207 Handle network errors raised by "requests" in HttpTransport (#75)

* KIT-4207 Use context manager to manage sessions instead of handling it by ourself

* KIT-4207 Ensure that no log entries are written by the library during logger shutdown

* KIT-4207 Ensure that no log entries are written by the library during logger shutdown

* KIT-4207 Improve logging

* KIT-4207 Remove unused imports

* KIT-4207 Minor logging adjustments

* KIT-4207 Adjust unit tests

* KIT-4207 updated version in setup

* KIT-4207 updated version in setup

* KIT-4554 introduced ruff

* KIT-4554 removed pylint

* Bump version

---------

Co-authored-by: Stefan Rom <41320207+devRoemer@users.noreply.github.com>
Co-authored-by: aott <ottalexanderdev@gmail.com>

29 of 109 new or added lines in 7 files covered. (26.61%)

9 existing lines in 4 files now uncovered.

159 of 533 relevant lines covered (29.83%)

0.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.02
/sag_py_logging_logstash/memory_cache.py
1
# -*- coding: utf-8 -*-
2
#
3
# This software may be modified and distributed under the terms
4
# of the MIT license.  See the LICENSE file for details.
5

6
import uuid
1✔
7
from datetime import datetime, timedelta
1✔
8

9
from sag_py_logging_logstash.cache import Cache
1✔
10
from sag_py_logging_logstash.constants import constants
1✔
11

12

13
class MemoryCache(Cache):
1✔
14
    """Backend implementation for python-logstash-async. Keeps messages in a local, in-memory cache
15
    while attempting to publish them to logstash. Does not persist through process restarts. Also,
16
    does not write to disk.
17

18
    :param cache: Usually just an empty dictionary
19
    :param event_ttl: Optional parameter used to expire events in the cache after a time
20
    """
21

22
    # ----------------------------------------------------------------------
23
    def __init__(self, safe_logger, cache, event_ttl=None):
1✔
24
        self._cache = cache
1✔
25
        self._event_ttl = event_ttl
1✔
26
        self._safe_logger = safe_logger
1✔
27

28
    # ----------------------------------------------------------------------
29
    def add_event(self, event):
1✔
30
        event_id = uuid.uuid4()
1✔
31
        self._cache[event_id] = {
1✔
32
            "event_text": event,
33
            "pending_delete": False,
34
            "entry_date": datetime.now(),
35
            "id": event_id,
36
        }
37

38
    # ----------------------------------------------------------------------
39
    def get_queued_events(self):
1✔
40
        events = []
1✔
41
        event_count = 0
1✔
42
        for event in self._cache.values():
1✔
43
            if not event["pending_delete"]:
1✔
44
                events.append(event)
1✔
45
                event["pending_delete"] = True
1✔
46

47
                event_count += 1
1✔
48
                if event_count >= constants.QUEUED_EVENTS_BATCH_SIZE:
1✔
49
                    break
1✔
50
        return events
1✔
51

52
    # ----------------------------------------------------------------------
53
    def requeue_queued_events(self, events):
1✔
54
        for event in events:
1✔
55
            event_to_queue = self._cache.get(event["id"], None)
1✔
56
            # If they gave us an event which is not in the cache,
57
            # there is really nothing for us to do. Right now
58
            # this use-case does not raise an error. Instead, we
59
            # just log the message.
60
            if event_to_queue:
1✔
61
                event_to_queue["pending_delete"] = False
1✔
62
            else:
NEW
63
                self._safe_logger.log(
×
64
                    "warning",
65
                    "Could not requeue event with id {}. It does not appear to be in the cache.".format(
66
                        event["id"]
67
                    ),
68
                )
69

70
    # ----------------------------------------------------------------------
71
    def delete_queued_events(self):
1✔
72
        ids_to_delete = [
1✔
73
            event["id"] for event in self._cache.values() if event["pending_delete"]
74
        ]
75
        self._delete_events(ids_to_delete)
1✔
76

77
    # ----------------------------------------------------------------------
78
    def expire_events(self):
1✔
79
        if self._event_ttl is None:
1✔
80
            return
×
81

82
        delete_time = datetime.now() - timedelta(seconds=self._event_ttl)
1✔
83
        ids_to_delete = [
1✔
84
            event["id"]
85
            for event in self._cache.values()
86
            if event["entry_date"] < delete_time
87
        ]
88
        self._delete_events(ids_to_delete)
1✔
89

90
    # ----------------------------------------------------------------------
91
    def _delete_events(self, ids_to_delete):
1✔
92
        for event_id in ids_to_delete:
1✔
93
            # If the event is not in the cache, is there anything
94
            # that we can do. This currently doesn't throw an error.
95
            event = self._cache.pop(event_id, None)
1✔
96
            if not event:
1✔
NEW
97
                self._safe_logger.log(
×
98
                    "warning",
99
                    "Could not delete event with id {}. It does not appear to be in the cache.".format(
100
                        event_id
101
                    ),
102
                )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc