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

Potential adjustments to helpers/linux/printk.py #368

Open
vbendel opened this issue Nov 9, 2023 · 2 comments
Open

Potential adjustments to helpers/linux/printk.py #368

vbendel opened this issue Nov 9, 2023 · 2 comments

Comments

@vbendel
Copy link

vbendel commented Nov 9, 2023

Hello,

Recently I implemented a dmesg -T (print human readable timestamps) to a project I'm collaborating on and originally followed what the comment says:

If you need to format the log buffer differently,
use :func:get_printk_records() and format it yourself.

However, I started to wonder whether drgn would be interested in having such functionality?

My current implementation (see excerpt below) has some caveats which might be undesirable for drgn as backend-lib, namely:
-) importing of datetime and timezone from datetime python lib
-) needing to be supplied with a boot_time integer, ideally in form of "seconds since epoch"

But if there would be interest from drgn to have this, we can discuss how to approach it. Please let me know. :)

def get_dmesg_human_ts(prog: Program, boot_time_s: int) -> str:
    lines = []
    for record in get_printk_records(prog):
        ts = (datetime
              .fromtimestamp(boot_time_s + (record.timestamp // 1000000000), timezone.utc)
              .astimezone()
              .strftime("%a %b %e %T %Z %Y"))
        lines.append(f"[{ts}] {record.text.decode(errors="replace")}")
    lines.append("")  # So we get a trailing newline.
    return "\n".join(lines)

Note this is not an Issue in particular, but just asking whether to spend time on preparing and opening a potential PR.

Thanks and regards,
-Vratislav

@osandov
Copy link
Owner

osandov commented Nov 29, 2023

Hi! This would be nice to add as an option to drgn's get_dmesg() helper (maybe as a keyword-only boolean parameter named ctime or human_readable_time or something like that), but only if we can avoid the need to pass in the boot time explicitly. I'd assume that information is in the kernel somewhere, right?

@vbendel
Copy link
Author

vbendel commented Jan 11, 2024

I'd assume that information (boot time) is in the kernel somewhere, right?

Well, yes and no - it's not there directly, but can be derived as current time - jiffies. However it is version specific w.r.t kernel's timekeeper structures. Which is why I originally decided to let the caller specify the boot time.

To give you some idea, this is how we get boot time in the project I'm collaborating on:

def get_timekeeper(ctx: Context):    
    if ctx.symbol_exists("tk_core"):
        timekeeper = ctx.prog["tk_core"].timekeeper
    elif ctx.symbol_exists("timekeeper"):
        timekeeper = ctx.prog["timekeeper"]
    else:
        raise NotImplementedError("Timekeeping structure is not supported")

    return timekeeper


def get_uptime_ns(ctx: Context):
    timekeeper = get_timekeeper(ctx)
    if not contains(timekeeper, "tkr_mono"):
        jiffies = ctx.prog["jiffies"].value_()
        wrapped = jiffies & 0xFFFFFFFF00000000
        if wrapped:
            wrapped -= 0x100000000
            jiffies &= 0x00000000FFFFFFFF
            jiffies |= wrapped
        jiffies += 300 * ctx.config_hz
        uptime_ns = jiffies * (1_000 // ctx.config_hz) * 1_000_000
    elif not contains(timekeeper.tkr_mono.base, "tv64"):
        uptime_ns = (timekeeper.tkr_mono.base + timekeeper.offs_boot).value_()
    else:
        uptime_ns = (timekeeper.tkr_mono.base.tv64 + timekeeper.offs_boot.tv64).value_()
    return uptime_ns

def main():
    timekeeper = get_timekeeper(cmd.ctx)
    uptime_ns = get_uptime_ns(cmd.ctx)
    uptime_s = uptime_ns // 1_000_000_000
    boot_time_s = timekeeper.xtime_sec.value_() - uptime_s
    print(get_dmesg_human_ts(boot_time_s))    # shared in initial comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants