Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5.7.3 - Allow disabling log forwarding #277

Merged
merged 1 commit into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:

- run: |
mk python-release owner=vkottler \
repo=runtimepy version=5.7.2
repo=runtimepy version=5.7.3
if: |
matrix.python-version == '3.12'
&& matrix.system == 'ubuntu-latest'
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
=====================================
generator=datazen
version=3.1.4
hash=618546df79dd7f387faa6f84f9a58c79
hash=ef917873929a5dc6a70367fde7f1447f
=====================================
-->

# runtimepy ([5.7.2](https://pypi.org/project/runtimepy/))
# runtimepy ([5.7.3](https://pypi.org/project/runtimepy/))

[![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
Expand Down
2 changes: 1 addition & 1 deletion local/variables/package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
major: 5
minor: 7
patch: 2
patch: 3
entry: runtimepy
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"

[project]
name = "runtimepy"
version = "5.7.2"
version = "5.7.3"
description = "A framework for implementing Python services."
readme = "README.md"
requires-python = ">=3.11"
Expand Down
4 changes: 2 additions & 2 deletions runtimepy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# =====================================
# generator=datazen
# version=3.1.4
# hash=0a0c607a8f78dc35cf48427539c9bafa
# hash=37a32f51e0bf04276100ce27658b7f8f
# =====================================

"""
Expand All @@ -10,7 +10,7 @@

DESCRIPTION = "A framework for implementing Python services."
PKG_NAME = "runtimepy"
VERSION = "5.7.2"
VERSION = "5.7.3"

# runtimepy-specific content.
METRICS_NAME = "metrics"
Expand Down
29 changes: 26 additions & 3 deletions runtimepy/mixins/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

# third-party
import aiofiles
from vcorelib.logging import LoggerMixin, LoggerType
from vcorelib.logging import ListLogger, LoggerMixin, LoggerType
from vcorelib.paths import Pathlike, normalize

# internal
Expand Down Expand Up @@ -66,6 +66,25 @@ def setup_level_channel(


LogPaths = Iterable[tuple[LogLevellike, Pathlike]]
EXT_LOG_EXTRA = {"external": True}


def handle_safe_log(
logger: LoggerType, level: int, data: str, safe_to_log: bool
) -> None:
"""handle a log filtering scenario."""

if safe_to_log:
logger.log(level, data, extra=EXT_LOG_EXTRA)
else:
record = logging.LogRecord(
logger.name, level, __file__, -1, data, (), None
)
record.external = True

for handler in logger.handlers: # type: ignore
if isinstance(handler, ListLogger):
handler.emit(record)


class LogCaptureMixin:
Expand All @@ -76,7 +95,10 @@ class LogCaptureMixin:
# Open aiofiles handles.
streams: list[tuple[int, Any]]

ext_log_extra = {"external": True}
# Set false to only forward to ListLogger handlers. Required for when the
# system log / process-management logs are being forwarded (otherwise also
# logging would lead to infinite spam).
safe_to_log = True

async def init_log_capture(
self, stack: AsyncExitStack, log_paths: LogPaths
Expand All @@ -98,7 +120,8 @@ async def init_log_capture(

def log_line(self, level: int, data: str) -> None:
"""Log a line for output."""
self.logger.log(level, data, extra=self.ext_log_extra)

handle_safe_log(self.logger, level, data, self.safe_to_log)

async def dispatch_log_capture(self) -> None:
"""Get the next line from this log stream."""
Expand Down
4 changes: 3 additions & 1 deletion runtimepy/net/server/app/env/tab/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ def compose(self, parent: Element) -> None:
logs = div(
tag="textarea",
parent=div(parent=vert_container, class_str="form-floating"),
class_str=(f"form-control rounded-0 {TEXT} text-logs"),
class_str=(
f"form-control rounded-0 {TEXT} text-body-emphasis text-logs"
),
id=self.get_id("logs"),
title=f"Text logs for {self.name}.",
)
Expand Down
23 changes: 0 additions & 23 deletions tasks/dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,6 @@ includes:
- dev_no_wait.yaml
- ../tests/data/valid/connection_arbiter/test_ssl.yaml

factories:
- {name: tasks.tlm.LogCapture}
tasks:
- name: root_log
factory: log_capture
period_s: 0.1
markdown: |
*something isn't looking right...*

**why's it looking like that...**

***why's it looking like THAT...***

`nice mono stuff there`

*`nice slanted mono yeah`*

**`nice mono bold type shit there`**

***`nice mono bold type slant shit there`***

ligature type shit \_\_\_|\_\_\_ ligature type shit

port_overrides:
runtimepy_https_server: 8443

Expand Down
38 changes: 0 additions & 38 deletions tasks/tlm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@

# built-in
import asyncio
import os
from pathlib import Path

# internal
from runtimepy.mixins.logging import LogCaptureMixin
from runtimepy.net.arbiter import AppInfo
from runtimepy.net.arbiter.task import ArbiterTask as _ArbiterTask
from runtimepy.net.arbiter.task import TaskFactory as _TaskFactory


async def sample_app(app: AppInfo) -> int:
Expand All @@ -24,36 +19,3 @@ async def sample_app(app: AppInfo) -> int:
await asyncio.sleep(0.01)

return 0


class LogCaptureTask(_ArbiterTask, LogCaptureMixin):
"""
A task that captures all log messages emitted by this program instance.
"""

auto_finalize = True

async def init(self, app: AppInfo) -> None:
"""Initialize this task with application information."""

await super().init(app)

# See above comment, we can probably keep the mixin class but delete
# this one - unless we want a separate "Linux" task to run / handle
# this (we might want to increase the housekeeping task rate to reduce
# async command latency + connection processing?).
await self.init_log_capture(
app.stack, [("info", Path(os.sep, "var", "log", "syslog"))]
)

async def dispatch(self) -> bool:
"""Dispatch an iteration of this task."""

await self.dispatch_log_capture()
return True


class LogCapture(_TaskFactory[LogCaptureTask]):
"""A factory for the syslog capture task."""

kind = LogCaptureTask
15 changes: 13 additions & 2 deletions tests/mixins/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,31 @@

# built-in
from contextlib import AsyncExitStack
import logging

# third-party
from pytest import mark
from vcorelib.logging import LoggerMixin
from vcorelib.logging import ListLogger, LoggerMixin
from vcorelib.paths.context import tempfile

# module under test
from runtimepy.mixins.logging import LogCaptureMixin
from runtimepy.mixins.logging import LogCaptureMixin, handle_safe_log


class SampleLogger(LoggerMixin, LogCaptureMixin):
"""A sample class."""


def test_handle_safe_log_basic():
"""Test basic scenarios for the 'handle_safe_log' method."""

logger = logging.getLogger(__name__)
logger.addHandler(ListLogger.create())

handle_safe_log(logger, logging.INFO, "message", True)
handle_safe_log(logger, logging.INFO, "message", False)


@mark.asyncio
async def test_log_capture_mixin_basic():
"""Test basic interactions with a log capture."""
Expand Down
Loading