diff options
| author | Paul Buetow <paul@buetow.org> | 2025-11-01 16:11:31 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-11-01 16:11:31 +0200 |
| commit | 0134ba980525cd881233f4e68242d3fece0fa2d5 (patch) | |
| tree | a43daefee6e0e3455e5cbaa27632174e0445b8fe | |
| parent | d73bcf391dee93f4bf1c11cc017f1bcf3e2a2af3 (diff) | |
Update content for md
| -rw-r--r-- | about/resources.md | 200 | ||||
| -rw-r--r-- | about/showcase.md | 6 | ||||
| -rw-r--r-- | gemfeed/2025-11-02-perl-new-features-and-foostats.md (renamed from gemfeed/DRAFT-perl-new-features-and-foostats.md) | 149 | ||||
| -rw-r--r-- | gemfeed/index.md | 1 | ||||
| -rw-r--r-- | gemfeed/stats.md | 7 | ||||
| -rw-r--r-- | index.md | 5 | ||||
| -rw-r--r-- | uptime-stats.md | 2 |
7 files changed, 211 insertions, 159 deletions
diff --git a/about/resources.md b/about/resources.md index 76149ef8..20e06077 100644 --- a/about/resources.md +++ b/about/resources.md @@ -35,109 +35,109 @@ You won't find any links on this site because, over time, the links will break. In random order: -* Perl New Features; Joshua McAdams, brian d foy; Perl School -* The Docker Book; James Turnbull; Kindle -* Data Science at the Command Line; Jeroen Janssens; O'Reilly -* Raku Fundamentals; Moritz Lenz; Apress -* Funktionale Programmierung; Peter Pepper; Springer +* 100 Go Mistakes and How to Avoid Them; Teiva Harsanyi; Manning Publications +* Effective Java; Joshua Bloch; Addison-Wesley Professional * Systems Performance Tuning; Gian-Paolo D. Musumeci and others...; O'Reilly +* Funktionale Programmierung; Peter Pepper; Springer +* DevOps And Site Reliability Engineering Handbook; Stephen Fleming; Audible +* The Docker Book; James Turnbull; Kindle +* Systemprogrammierung in Go; Frank Müller; dpunkt +* 97 things every SRE should know; Emil Stolarsky, Jaime Woo; O'Reilly +* The Go Programming Language; Alan A. A. Donovan; Addison-Wesley Professional * Effective awk programming; Arnold Robbins; O'Reilly -* Object-Oriented Programming with ANSI-C; Axel-Tobias Schreiner -* DNS and BIND; Cricket Liu; O'Reilly -* Higher Order Perl; Mark Dominus; Morgan Kaufmann -* Distributed Systems: Principles and Paradigms; Andrew S. Tanenbaum; Pearson -* 100 Go Mistakes and How to Avoid Them; Teiva Harsanyi; Manning Publications -* The DevOps Handbook; Gene Kim, Jez Humble, Patrick Debois, John Willis; Audible -* Polished Ruby Programming; Jeremy Evans; Packt Publishing +* Amazon Web Services in Action; Michael Wittig and Andreas Wittig; Manning Publications +* The Practise of System and Network Administration; Thomas A. Limoncelli, Christina J. Hogan, Strata R. Chalup; Addison-Wesley Professional Pro Git; Scott Chacon, Ben Straub; Apress +* Data Science at the Command Line; Jeroen Janssens; O'Reilly * Tmux 2: Productive Mouse-free Development; Brain P. Hogan; The Pragmatic Programmers -* Developing Games in Java; David Brackeen and others...; New Riders -* Concurrency in Go; Katherine Cox-Buday; O'Reilly -* 97 things every SRE should know; Emil Stolarsky, Jaime Woo; O'Reilly -* Kubernetes Cookbook; Sameer Naik, Sébastien Goasguen, Jonathan Michaux; O'Reilly * C++ Programming Language; Bjarne Stroustrup; -* Effective Java; Joshua Bloch; Addison-Wesley Professional +* Modern Perl; Chromatic ; Onyx Neon Press +* Programming Ruby 3.3 (5th Edition); Noel Rappin, with Dave Thomas; The Pragmatic Bookshelf * Ultimate Go Notebook; Bill Kennedy -* Pro Puppet; James Turnbull, Jeffrey McCune; Apress -* Think Raku (aka Think Perl 6); Laurent Rosenfeld, Allen B. Downey; O'Reilly -* Chaos Engineering - System Resiliency in Practice; Casey Rosenthal and Nora Jones; eBook +* Hands-on Infrastructure Monitoring with Prometheus; Joel Bastos, Pedro Araujo; Packt +* Polished Ruby Programming; Jeremy Evans; Packt Publishing +* Perl New Features; Joshua McAdams, brian d foy; Perl School * Learn You Some Erlang for Great Good; Fred Herbert; No Starch Press -* Programming Perl aka "The Camel Book"; Tom Christiansen, brian d foy, Larry Wall & Jon Orwant; O'Reilly -* Leanring eBPF; Liz Rice; O'Reilly -* Site Reliability Engineering; How Google runs production systems; O'Reilly +* The DevOps Handbook; Gene Kim, Jez Humble, Patrick Debois, John Willis; Audible * The KCNA (Kubernetes and Cloud Native Associate) Book; Nigel Poulton -* DevOps And Site Reliability Engineering Handbook; Stephen Fleming; Audible -* 21st Century C: C Tips from the New School; Ben Klemens; O'Reilly -* Systemprogrammierung in Go; Frank Müller; dpunkt +* Distributed Systems: Principles and Paradigms; Andrew S. Tanenbaum; Pearson +* Go Brain Teasers - Exercise Your Mind; Miki Tebeka; The Pragmatic Programmers +* Concurrency in Go; Katherine Cox-Buday; O'Reilly +* Learn You a Haskell for Great Good!; Miran Lipovaca; No Starch Press +* Kubernetes Cookbook; Sameer Naik, Sébastien Goasguen, Jonathan Michaux; O'Reilly +* DNS and BIND; Cricket Liu; O'Reilly +* Programming Perl aka "The Camel Book"; Tom Christiansen, brian d foy, Larry Wall & Jon Orwant; O'Reilly +* The Pragmatic Programmer; David Thomas; Addison-Wesley +* Think Raku (aka Think Perl 6); Laurent Rosenfeld, Allen B. Downey; O'Reilly +* Raku Recipes; J.J. Merelo; Apress * Terraform Cookbook; Mikael Krief; Packt Publishing +* Developing Games in Java; David Brackeen and others...; New Riders * Java ist auch eine Insel; Christian Ullenboom; +* Higher Order Perl; Mark Dominus; Morgan Kaufmann +* Leanring eBPF; Liz Rice; O'Reilly +* Object-Oriented Programming with ANSI-C; Axel-Tobias Schreiner +* Chaos Engineering - System Resiliency in Practice; Casey Rosenthal and Nora Jones; eBook +* Pro Puppet; James Turnbull, Jeffrey McCune; Apress * Clusterbau mit Linux-HA; Michael Schwartzkopff; O'Reilly -* Amazon Web Services in Action; Michael Wittig and Andreas Wittig; Manning Publications -* The Go Programming Language; Alan A. A. Donovan; Addison-Wesley Professional * The Kubernetes Book; Nigel Poulton; Unabridged Audiobook -* The Pragmatic Programmer; David Thomas; Addison-Wesley -* Programming Ruby 3.3 (5th Edition); Noel Rappin, with Dave Thomas; The Pragmatic Bookshelf -* Modern Perl; Chromatic ; Onyx Neon Press -* Hands-on Infrastructure Monitoring with Prometheus; Joel Bastos, Pedro Araujo; Packt -* Raku Recipes; J.J. Merelo; Apress -* Go Brain Teasers - Exercise Your Mind; Miki Tebeka; The Pragmatic Programmers -* The Practise of System and Network Administration; Thomas A. Limoncelli, Christina J. Hogan, Strata R. Chalup; Addison-Wesley Professional Pro Git; Scott Chacon, Ben Straub; Apress -* Learn You a Haskell for Great Good!; Miran Lipovaca; No Starch Press +* Raku Fundamentals; Moritz Lenz; Apress +* 21st Century C: C Tips from the New School; Ben Klemens; O'Reilly +* Site Reliability Engineering; How Google runs production systems; O'Reilly ## Technical references I didn't read them from the beginning to the end, but I am using them to look up things. The books are in random order: -* Algorithms; Robert Sedgewick, Kevin Wayne; Addison Wesley -* Implementing Service Level Objectives; Alex Hidalgo; O'Reilly * The Linux Programming Interface; Michael Kerrisk; No Starch Press +* Implementing Service Level Objectives; Alex Hidalgo; O'Reilly +* Relayd and Httpd Mastery; Michael W Lucas +* Groovy Kurz & Gut; Joerg Staudemeier; O'Reilly * Go: Design Patterns for Real-World Projects; Mat Ryer; Packt * BPF Performance Tools - Linux System and Application Observability, Brendan Gregg; Addison Wesley -* Groovy Kurz & Gut; Joerg Staudemeier; O'Reilly -* Relayd and Httpd Mastery; Michael W Lucas * Understanding the Linux Kernel; Daniel P. Bovet, Marco Cesati; O'Reilly +* Algorithms; Robert Sedgewick, Kevin Wayne; Addison Wesley ## Self-development and soft-skills books In random order: -* The Courage to Be Disliked; Ichiro Kishimi and Fumitake Koga; Audiobook -* Getting Things Done; David Allen * The Off Switch; Mark Cropley; Virgin Books (RE-READ 1ST TIME) -* Atomic Habits; James Clear; Random House Business -* The Bullet Journal Method; Ryder Carroll; Fourth Estate -* The Good Enough Job; Simone Stolzoff; Ebury Edge +* Ultralearning; Scott Young; Thorsons +* Consciousness: A Very Short Introduction; Susan Blackmore; Oxford Uiversity Press +* 97 Things Every Engineering Manager Should Know; Camille Fournier; Audiobook +* Soft Skills; John Sommez; Manning Publications +* The Joy of Missing Out; Christina Crook; New Society Publishers +* Solve for Happy; Mo Gawdat (RE-READ 1ST TIME) +* So Good They Can't Ignore You; Cal Newport; Business Plus +* Buddah and Einstein walk into a Bar; Guy Joseph Ale, Claire Bloom; Blackstone Publishing * The Software Engineer's Guidebook: Navigating senior, tech lead, and staff engineer positions at tech companies and startups; Gergely Orosz; Audiobook +* Meditation for Mortals, Oliver Burkeman, Audiobook +* The 7 Habits Of Highly Effective People; Stephen R. Covey; Simon & Schuster UK +* Psycho-Cybernetics; Maxwell Maltz; Perigee Books +* Eat That Frog; Brian Tracy +* The Obstacle Is The Way; Ryan Holiday; Profile Books Ltd +* The Daily Stoic; Ryan Holiday, Stephen Hanselman; Profile Books * Never Split the Difference; Chris Voss, Tahl Raz; Random House Business +* The Bullet Journal Method; Ryder Carroll; Fourth Estate +* Atomic Habits; James Clear; Random House Business +* The Phoenix Project - A Novel About IT, DevOps, and Helping your Business Win; Gene Kim and Kevin Behr; Trade Select * Influence without Authority; A. Cohen, D. Bradford; Wiley -* Slow Productivity; Cal Newport; Penguin Random House -* Buddah and Einstein walk into a Bar; Guy Joseph Ale, Claire Bloom; Blackstone Publishing +* Staff Engineer: Leadership beyond the management track; Will Larson; Audiobook +* Digital Minimalism; Cal Newport; Portofolio Penguin * Search Inside Yourself - The Unexpected path to Achieving Success, Happiness (and World Peace); Chade-Meng Tan, Daniel Goleman, Jon Kabat-Zinn; HarperOne -* Time Management for System Administrators; Thomas A. Limoncelli; O'Reilly * The Power of Now; Eckhard Tolle; Yellow Kite +* Eat That Frog!; Brian Tracy; Hodder Paperbacks * Who Moved My Cheese?; Dr. Spencer Johnson; Vermilion -* The Daily Stoic; Ryan Holiday, Stephen Hanselman; Profile Books +* The Courage to Be Disliked; Ichiro Kishimi and Fumitake Koga; Audiobook +* Stop starting, start finishing; Arne Roock; Lean-Kanban University +* Slow Productivity; Cal Newport; Penguin Random House * The Complete Software Developer's Career Guide; John Sonmez; Unabridged Audiobook -* The 7 Habits Of Highly Effective People; Stephen R. Covey; Simon & Schuster UK +* The Good Enough Job; Simone Stolzoff; Ebury Edge +* Ultralearning; Anna Laurent; Self-published via Amazon +* Getting Things Done; David Allen * 101 Essays that change the way you think; Brianna Wiest; Audiobook -* Ultralearning; Scott Young; Thorsons -* Psycho-Cybernetics; Maxwell Maltz; Perigee Books -* Digital Minimalism; Cal Newport; Portofolio Penguin -* The Joy of Missing Out; Christina Crook; New Society Publishers * Deep Work; Cal Newport; Piatkus -* So Good They Can't Ignore You; Cal Newport; Business Plus -* Stop starting, start finishing; Arne Roock; Lean-Kanban University -* Ultralearning; Anna Laurent; Self-published via Amazon +* Time Management for System Administrators; Thomas A. Limoncelli; O'Reilly * Coders at Work - Reflections on the craft of programming, Peter Seibel and Mitchell Dorian et al., Audiobook -* Staff Engineer: Leadership beyond the management track; Will Larson; Audiobook -* The Obstacle Is The Way; Ryan Holiday; Profile Books Ltd -* Solve for Happy; Mo Gawdat (RE-READ 1ST TIME) -* 97 Things Every Engineering Manager Should Know; Camille Fournier; Audiobook -* Eat That Frog!; Brian Tracy; Hodder Paperbacks -* Soft Skills; John Sommez; Manning Publications -* Eat That Frog; Brian Tracy -* Meditation for Mortals, Oliver Burkeman, Audiobook -* The Phoenix Project - A Novel About IT, DevOps, and Helping your Business Win; Gene Kim and Kevin Behr; Trade Select -* Consciousness: A Very Short Introduction; Susan Blackmore; Oxford Uiversity Press [Here are notes of mine for some of the books](../notes/index.md) @@ -145,30 +145,30 @@ In random order: Some of these were in-person with exams; others were online learning lectures only. In random order: -* Linux Security and Isolation APIs Training; Michael Kerrisk; 3-day on-site training -* Cloud Operations on AWS - Learn how to configure, deploy, maintain, and troubleshoot your AWS environments; 3-day online live training with labs; Amazon -* Red Hat Certified System Administrator; Course + certification (Although I had the option, I decided not to take the next course as it is more effective to self learn what I need) -* MySQL Deep Dive Workshop; 2-day on-site training -* The Ultimate Kubernetes Bootcamp; School of Devops; O'Reilly Online -* AWS Immersion Day; Amazon; 1-day interactive online training * Algorithms Video Lectures; Robert Sedgewick; O'Reilly Online +* MySQL Deep Dive Workshop; 2-day on-site training * Protocol buffers; O'Reilly Online -* Ultimate Go Programming; Bill Kennedy; O'Reilly Online -* Scripting Vim; Damian Conway; O'Reilly Online * Apache Tomcat Best Practises; 3-day on-site training -* Developing IaC with Terraform (with Live Lessons); O'Reilly Online -* Structure and Interpretation of Computer Programs; Harold Abelson and more...; +* Red Hat Certified System Administrator; Course + certification (Although I had the option, I decided not to take the next course as it is more effective to self learn what I need) +* AWS Immersion Day; Amazon; 1-day interactive online training +* Cloud Operations on AWS - Learn how to configure, deploy, maintain, and troubleshoot your AWS environments; 3-day online live training with labs; Amazon +* The Ultimate Kubernetes Bootcamp; School of Devops; O'Reilly Online +* Ultimate Go Programming; Bill Kennedy; O'Reilly Online +* F5 Loadbalancers Training; 2-day on-site training; F5, Inc. * The Well-Grounded Rubyist Video Edition; David. A. Black; O'Reilly Online +* Structure and Interpretation of Computer Programs; Harold Abelson and more...; * Functional programming lecture; Remote University of Hagen -* F5 Loadbalancers Training; 2-day on-site training; F5, Inc. +* Scripting Vim; Damian Conway; O'Reilly Online +* Linux Security and Isolation APIs Training; Michael Kerrisk; 3-day on-site training +* Developing IaC with Terraform (with Live Lessons); O'Reilly Online ## Technical guides These are not whole books, but guides (smaller or larger) which I found very useful. in random order: -* Advanced Bash-Scripting Guide * How CPUs work at https://cpu.land * Raku Guide at https://raku.guide +* Advanced Bash-Scripting Guide ## Podcasts @@ -176,58 +176,58 @@ These are not whole books, but guides (smaller or larger) which I found very use In random order: -* Maintainable -* Pratical AI -* The ProdCast (Google SRE Podcast) -* Wednesday Wisdom * Cup o' Go [Golang] -* Fork Around And Find Out +* The Pragmatic Engineer Podcast +* Fallthrough [Golang] +* BSD Now [BSD] * Deep Questions with Cal Newport +* Hidden Brain +* The ProdCast (Google SRE Podcast) +* Pratical AI +* Maintainable +* The Changelog Podcast(s) +* Fork Around And Find Out * Dev Interrupted +* Wednesday Wisdom * Modern Mentor -* BSD Now [BSD] -* Fallthrough [Golang] -* The Changelog Podcast(s) -* The Pragmatic Engineer Podcast * Backend Banter -* Hidden Brain ### Podcasts I liked I liked them but am not listening to them anymore. The podcasts have either "finished" (no more episodes) or I stopped listening to them due to time constraints or a shift in my interests. +* Ship It (predecessor of Fork Around And Find Out) +* Go Time (predecessor of fallthrough) * CRE: Chaosradio Express [german] -* FLOSS weekly * Modern Mentor -* Go Time (predecessor of fallthrough) +* FLOSS weekly * Java Pub House -* Ship It (predecessor of Fork Around And Find Out) ## Newsletters I like This is a mix of tech and non-tech newsletters I am subscribed to. In random order: -* VK Newsletter -* The Valuable Dev * Monospace Mentor -* Applied Go Weekly Newsletter -* The Pragmatic Engineer -* Golang Weekly * Ruby Weekly -* Register Spill -* byteSizeGo * Changelog News +* The Valuable Dev * Andreas Brandhorst Newsletter (Sci-Fi author) +* The Pragmatic Engineer +* byteSizeGo +* Register Spill +* Golang Weekly +* VK Newsletter * The Imperfectionist +* Applied Go Weekly Newsletter ## Magazines I like(d) This is a mix of tech I like(d). I may not be a current subscriber, but now and then, I buy an issue. In random order: * freeX (not published anymore) +* LWN (online only) * Linux Magazine * Linux User -* LWN (online only) # Formal education diff --git a/about/showcase.md b/about/showcase.md index 3c0904a6..3904d278 100644 --- a/about/showcase.md +++ b/about/showcase.md @@ -91,14 +91,14 @@ This page showcases my side projects, providing an overview of what each project * 🔥 Recent Activity: 24.2 days (avg. age of last 42 commits) * ⚖️ License: No license found * 🏷️ Latest Release: v0.3.0 (2025-10-24) -* 🤖 AI-Assisted: This project was partially created with the help of generative AI +* 🤖 AI-Assisted: This project was vibe-coded. [](showcase/yoga/image-1.png) -Yoga is a terminal-based video browser designed for managing and playing local yoga video collections. It scans a directory (defaulting to `~/Yoga`) for common video formats, probes and caches their durations, and provides a keyboard-driven interface for quickly filtering videos by name, duration range, or tags. Users can sort by name, length, or age, and launch videos directly in VLC with optional crop settings—all without leaving the terminal. The tool is optimized for quick navigation and playback, making it easy to find and start a specific practice session in seconds. +Yoga is a Terminal User Interface (TUI) application written in Go that helps users browse and play local yoga video collections. It scans a designated directory for video files (MP4, MKV, MOV, AVI, WMV, M4V), extracts and caches duration metadata, and presents them in an interactive table. Users can quickly filter videos by name, duration range, or tags, sort by various criteria (name, length, age), and launch playback in VLC with a single keypress. The tool is particularly useful for managing personal yoga practice libraries where you want to quickly find videos matching specific time constraints or styles without opening a file browser. -The project is implemented in Go with a TUI interface, organized around a clean `cmd/yoga` entry point that wires together internal packages for filesystem operations (`internal/fsutil`), metadata caching (`internal/meta`), and UI flow (`internal/app`). Video metadata is persisted in `.video_duration_cache.json` files to avoid re-probing on every launch. Development uses Mage for build tasks, enforces ≥85% test coverage, and follows standard Go idioms with `gofumpt` formatting. +The implementation follows clean Go architecture with domain logic organized under `internal/` (including `app` for TUI flow, `fsutil` for filesystem operations, and `meta` for metadata caching). It uses a keyboard-driven interface with vim-like navigation and maintains a `.video_duration_cache.json` file per directory to avoid re-probing video durations on subsequent scans. The project emphasizes maintainability with ≥85% test coverage requirements, table-driven tests, and strict formatting via `gofumpt`, while keeping the entry point minimal in `cmd/yoga/main.go`. [View on Codeberg](https://codeberg.org/snonux/yoga) [View on GitHub](https://github.com/snonux/yoga) diff --git a/gemfeed/DRAFT-perl-new-features-and-foostats.md b/gemfeed/2025-11-02-perl-new-features-and-foostats.md index ea769dd3..1a4a20da 100644 --- a/gemfeed/DRAFT-perl-new-features-and-foostats.md +++ b/gemfeed/2025-11-02-perl-new-features-and-foostats.md @@ -1,6 +1,11 @@ # Perl New Features and Foostats -Perl just reached rank 10 in the TIOBE index. That headline matches my day-to-day reality because I keep developing the foostats script for simple analytics of my personal websites and Gemini capsules (e.g. `foo.zone`), and almost every Perl release adds new features. The book *Perl New Features* by brian d foy documents the changes well; this post shows how those features look in a real program that runs every morning for my stats generation. +> Published at 2025-11-01T16:10:35+02:00 + +Perl recently reached rank 10 in the TIOBE index. That headline made me write this blog post as I was developing the Foostats script for simple analytics of my personal websites and Gemini capsules (e.g. `foo.zone`) and there were a couple of new features added to the Perl language over the last releases. The book *Perl New Features* by brian d foy documents the changes well; this post shows how those features look in a real program that runs every morning for my stats generation. + +[Perl re-enters the top ten](https://developers.slashdot.org/story/25/09/14/0134239/is-perl-the-worlds-10th-most-popular-programming-language) +[Perl New Features by Joshua McAdams and brian d foy](https://perlschool.com/books/perl-new-features/) ``` $b="24P7cP3dP31P3bPaP28P24P64P31P2cP24P64P32P2cP24P73P2cP24P67P2cP24P7 @@ -46,7 +51,7 @@ P6 6P 74P3bPaP9P66P6fP72P28P24P6aP3dP30P3bP24P6aP3cP24P6cP3bP24P6aP2bP2bP29P 7bP7dPaP7dP";$b=~s/\s//g;split /P/,$b;foreach(@_){$c.=chr hex};eval $c -The above Perl scripts prints out "Just Another Perl Hacker !" in an +The above Perl script prints out "Just Another Perl Hacker !" in an animation of sorts. ``` @@ -56,26 +61,24 @@ animation of sorts. * [⇢ Perl New Features and Foostats](#perl-new-features-and-foostats) * [⇢ ⇢ Motivation](#motivation) * [⇢ ⇢ Why I used Perl](#why-i-used-perl) -* [⇢ ⇢ Inside foostats](#inside-foostats) +* [⇢ ⇢ Inside Foostats](#inside-foostats) * [⇢ ⇢ ⇢ Log pipeline](#log-pipeline) +* [⇢ ⇢ ⇢ `fooodds.txt`](#foooddstxt) +* [⇢ ⇢ ⇢ Feed kinds](#feed-kinds) * [⇢ ⇢ ⇢ Aggregation and output](#aggregation-and-output) * [⇢ ⇢ ⇢ Command-line entry points](#command-line-entry-points) * [⇢ ⇢ Packages as real blocks](#packages-as-real-blocks) * [⇢ ⇢ ⇢ Scoped packages](#scoped-packages) * [⇢ ⇢ Postfix dereferencing keeps data structures tidy](#postfix-dereferencing-keeps-data-structures-tidy) * [⇢ ⇢ ⇢ Clear dereferencing](#clear-dereferencing) +* [⇢ ⇢ `say` is the default voice now](#say-is-the-default-voice-now) * [⇢ ⇢ Lexical subs promote local reasoning](#lexical-subs-promote-local-reasoning) -* [⇢ ⇢ ⇢ Helpers that stay local](#helpers-that-stay-local) * [⇢ ⇢ Reference aliasing makes intent explicit](#reference-aliasing-makes-intent-explicit) -* [⇢ ⇢ ⇢ Shared data on purpose](#shared-data-on-purpose) * [⇢ ⇢ Persistent state without globals](#persistent-state-without-globals) * [⇢ ⇢ ⇢ Rate limiting state](#rate-limiting-state) * [⇢ ⇢ ⇢ De-duplicated logging](#de-duplicated-logging) -* [⇢ ⇢ Subroutine signatures clarify every call site](#subroutine-signatures-clarify-every-call-site) -* [⇢ ⇢ ⇢ "normal" subroutine signatures now](#normal-subroutine-signatures-now) -* [⇢ ⇢ Defined-or assignment keeps defaults obvious](#defined-or-assignment-keeps-defaults-obvious) -* [⇢ ⇢ ⇢ Defaults without boilerplate](#defaults-without-boilerplate) -* [⇢ ⇢ `say` is the default voice now](#say-is-the-default-voice-now) +* [⇢ ⇢ Subroutine signatures](#subroutine-signatures) +* [⇢ ⇢ Defined-or assignment for defaults without boilerplate](#defined-or-assignment-for-defaults-without-boilerplate) * [⇢ ⇢ Cleanup with `defer`](#cleanup-with-defer) * [⇢ ⇢ Builtins and booleans](#builtins-and-booleans) * [⇢ ⇢ Conclusion](#conclusion) @@ -88,7 +91,7 @@ I've been running `foo.zone` for a while now, but I've never looked into visitor * Exclude, if possible, any bots and scrapers from the stats * Track only anonymized IP addresses, never store raw addresses -With Foostats I've created a Perl script which does that for my highly opinionated website/blog setup: +With Foostats I've created a Perl script which does that for my highly opinionated website/blog setup, which consists of: [Gemtexter, my static site and Gemini capsule generator](https://foo.zone/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html) [How I host this site highly-available using OpenBSD](https://foo.zone/gemfeed/2024-04-01-KISS-high-availability-with-OpenBSD.html) @@ -100,18 +103,21 @@ Even though nowadays I code more in Go and Ruby, I stuck with Perl for Foostats * I wanted an excuse to explore the newer features of my first programming love. * Sometimes, I miss Perl. * Perl ships with OpenBSD (the operating system on which my sites run) by default. -* It really does live up to its Practical Extraction and Report Language (that's where the name Perl means) for this kind of log grinding I did with foostats. +* It really does live up to its Practical Extraction and Report Language (that's what the name Perl means) for this kind of log grinding I did with Foostats. -[Perl re-enters the top ten](https://developers.slashdot.org/story/25/09/14/0134239/is-perl-the-worlds-10th-most-popular-programming-language) -[Perl New Features by Joshua McAdams and brian d foy](https://perlschool.com/books/perl-new-features/) - -## Inside foostats +## Inside Foostats Foostats is simply a log file analyser, which analyses the OpenBSD httpd and relayd logs. +[https://man.openbsd.org/httpd.8](https://man.openbsd.org/httpd.8) +[https://man.openbsd.org/relayd.8](https://man.openbsd.org/relayd.8) + ### Log pipeline -A cron job starts Foostats, reads OpenBSD httpd and relayd access logs, and produces the numbers published at `https://stats.foo.zone` and `gemini://stats.foo.zone`. The dashboards are humble because traffic on my sites is still light, yet the trends are interesting for spotting patterns. The script is opinionated (I am repeating myself here, I know), and I will probably be the only one ever using it for my own sites. However, the code demonstrates how Perl's newer features help keep a small script like this exciting and fun! +A CRON job starts Foostats, reads OpenBSD httpd and relayd access logs, and produces the numbers published at `https://stats.foo.zone` and `gemini://stats.foo.zone`. The dashboards are humble because traffic on my sites is still light, yet the trends are interesting for spotting patterns. The script is opinionated (I am repeating myself here, I know), and I will probably be the only one ever using it for my own sites. However, the code demonstrates how Perl's newer features help keep a small script like this exciting and fun! + +[Foostats (HTTP)](https://stats.foo.zone) +[Foostats (Gemini)](gemini://stats.foo.zone) On OpenBSD, I've configured the job via the `daily.local` on both of my OpenBSD servers (`fishfinger.buetow.org` and `blowfish.buetow.org` - note one is the master server, the other is the standby server, but the script runs on both and the stats are merged later in the process): @@ -122,7 +128,13 @@ perl /usr/local/bin/foostats.pl --parse-logs --replicate --report Internally, `Foostats::Logreader` parses each line of the log files `/var/log/daemon*` and `/var/www/logs/access_log*`, turns timestamps into `YYYYMMDD/HHMMSS` values, hashes IP addresses with SHA3 (for anonymization), and hands a normalized event to `Foostats::Filter`. The filter compares the URI against entries in `fooodds.txt`, tracks how many times an IP address requests within the exact second, and drops anything suspicious (e.g., from web crawlers or malicious attackers). Valid events reach `Foostats::Aggregator`, which counts requests per protocol, records unique visitors for the Gemtext and Atom feeds, and remembers page-level IP sets. `Foostats::FileOutputter` writes the result as gzipped JSON files—one per day and per protocol—with IPv4/IPv6 splits, filtered counters, feed readership, and hashes for long URLs. -Whereas, there are different kinds of feeds: +### `fooodds.txt` + +`fooodds.txt` is a plain text list of substrings of URLs to be blocked, making it quick to shut down web crawlers. Foostats also detects rapid requests (an indicator of excessive crawling) and blocks the IP. Audit lines are written to `/var/log/fooodds`, which can later be reviewed for false or true positives (I do this around once a month). The `Justfile` even has a `gather-fooodds` target that collects suspicious paths from remote logs so new patterns can be added quickly. + +### Feed kinds + +There are different kinds of feeds being tracked by Foostats: * The Atom web-feed * The same feed via Gemini @@ -141,22 +153,20 @@ Those are the raw stats files: [https://blowfish.buetow.org/foostats/](https://blowfish.buetow.org/foostats/) [https://fishfinger.buetow.org/foostats/](https://fishfinger.buetow.org/foostats/) -These are the 30-day reports generated: +These are the 30-day reports generated (already linked earlier in this post, but adding here again for clarity): [stats.foo.zone Gemini capsule dashboard](gemini://stats.foo.zone) [stats.foo.zone HTTP dashboard](https://stats.foo.zone) ### Command-line entry points -`foostats_main` is the command entry point. `--parse-logs` refreshes the gzipped files, `--replicate` runs the cross-host sync, and `--report` rebuilds the HTML and Gemini report pages. `--all` performs everything in one go. Defaults point to `/var/www/htdocs/buetow.org/self/foostats` for data, `/var/gemini/stats.foo.zone` for Gemtext output, and `/var/www/htdocs/gemtexter/stats.foo.zone` for HTML output. Replication always forces the three most recent days worth of the data across HTTPS and leaves older files untouched to save bandwidth. - -`fooodds.txt` is a plain text list of substrings of URLs to be blocked, making it quick to shut down web crawlers. Foostats also detects rapid requests (an indicator of excessive crawling) and blocks the IP. Audit lines are written to `/var/log/fooodds`, which can later be reviewed for false or true positives (I do this around once a month). The `Justfile` even has a `gather-fooodds` target that collects suspicious paths from remote logs so new patterns can be added quickly. +`foostats_main` is the command entry point. `--parse-logs` refreshes the gzipped files, `--replicate` runs the cross-host sync, and `--report` rebuilds the HTML and Gemini report pages. `--all` performs everything in one go. Defaults point to `/var/www/htdocs/buetow.org/self/foostats` for data, `/var/gemini/stats.foo.zone` for Gemtext output, and `/var/www/htdocs/gemtexter/stats.foo.zone` for HTML output. Replication always forces the three most recent days' worth of data across HTTPS and leaves older files untouched to save bandwidth. The complete source lives on Codeberg here: -[foostats on Codeberg](https://codeberg.org/snonux/foostats) +[Foostats on Codeberg](https://codeberg.org/snonux/foostats) -Now let's go to some new Perl features: +Now let's go to some new Perl features: ## Packages as real blocks @@ -220,7 +230,7 @@ for my $elem ($array_ref->@*) { } ``` -You see that this feature becomes increasingly useful the with nested data structures, e.g. to print all keys of the nested hash: +You see that this feature becomes increasingly useful with nested data structures, e.g. to print all keys of the nested hash: ```perl print for keys $hash->{stats}->%*; @@ -228,17 +238,45 @@ print for keys $hash->{stats}->%*; Loops over like `$stats->{page_ips}->{urls}->%*` or `$merge{$key}->{$_}->%*` show which level of the structure is in play. The merger in Foostats updates host and URL statistics without building temporary arrays, and the reporter code mirrors the layout of the final tables. Before postfix dereferencing, the same code relied on braces within braces and was harder to read. -## Lexical subs promote local reasoning +## `say` is the default voice now -### Helpers that stay local +`say` became the default once the script switched to `use v5.38;`. It adds a newline to every message printed, comparable to Ruby's `puts`, making log messages like "Processing $path" or "Writing report to $report_path" cleaner: + +```perl +use v5.38; + +print "Hello, world!\n"; # old way + +say "Hello, world!"; # new way +``` + +## Lexical subs promote local reasoning Lexical subroutines keep helpers close to the code that needs them. In `Foostats::Logreader::parse_web_logs`, functions such as `my sub parse_date` and `my sub open_file` live only inside that scope. -## Reference aliasing makes intent explicit +This is an example of a lexical sub named `trim`, which is only visible within the outer sub named `process_lines`: + +```perl +use v5.38; + +sub process_lines { + my @lines = @_; + + my sub trim ($str) { + $str =~ s/^\s+|\s+$//gr; + } + + return [ map { trim($_) } @lines ]; +} -### Shared data on purpose +my @raw = (" foo ", " bar", "baz "); +my $cleaned = process_lines(@raw); +say for @$cleaned; # prints "foo", "bar", "baz" +``` + +## Reference aliasing makes intent explicit -Ref aliasing is enabled with `use feature qw(refaliasing)` and helps communicate intent more clearly (if you remember the Perl syntax, of course. Otherwise, it's like chinese). The filter starts with `\my $uri_path = \$event->{uri_path}` so any later modification touches the original event. +Reference aliasing can be enabled with `use feature qw(refaliasing)` and helps communicate intent more clearly (if you remember the Perl syntax, of course—otherwise, it can look rather cryptic). The filter starts with `\my $uri_path = \$event->{uri_path}` so any later modification touches the original event. This is an example with ref aliasing in action: ```perl use feature qw(refaliasing); @@ -250,7 +288,7 @@ $foo = 99; print $hash->{foo}; # prints 99 ``` -The aggregator in Foostats aliases `$self->{stats}{$date_key}` before updating counters, so the structure remains intact. Combined with subroutine signatures, this makes it obvious when a piece of data is shared instead of copied, preventing silent bugs. +The aggregator in Foostats aliases `$self->{stats}{$date_key}` before updating counters, so the structure remains intact. Combined with subroutine signatures, this makes it obvious when a piece of data is shared instead of copied, preventing silent bugs. This enables having shorter names for long nested data structures. ## Persistent state without globals @@ -270,56 +308,61 @@ say counter(); # 2 say counter(); # 3 ``` +Hash and array state variables have been supported since `state` arrived in Perl 5.10. Scalar state variables were already supported previously. + ### Rate limiting state -In Foostats, `state` variables store run-specific state without using package globals. `state %blocked` remembers IP hashes that already triggered the odd-request filter, and `state $last_time` and `state %count` track how many requests an IP makes in the exact second. Hash and array state variables have been supported since `state` arrived in Perl 5.10, so this code takes advantage of that long-standing capability. However, what's new is that hashes can now also be state variables. +In Foostats, `state` variables store run-specific state without using package globals. `state %blocked` remembers IP hashes that already triggered the odd-request filter, and `state $last_time` and `state %count` track how many requests an IP makes in the exact second. ### De-duplicated logging -`state %dedup` keeps the log output to one warning per URI. Early versions utilized global hashes for the same tasks, producing inconsistent results during tests. Switching to `state` removed those edge cases. +`state %dedup` keeps the log output of the suspicious calls to one warning per URI. Early versions utilized global hashes for the same tasks, producing inconsistent results during tests. Switching to `state` removed those edge cases. -## Subroutine signatures clarify every call site +## Subroutine signatures -Perl now supports subroutine signatures like other modern languages do. Foostats uses them everywhere. +Perl now supports subroutine signatures like other modern languages do. Foostats uses them everywhere. Examples: ```perl # Old way sub greet_old { my $name = shift; print "Hello, $name!\n" } # Another old way -sub greet_old ($) { $name = shift; print "Hello, $name!\n" } +sub greet_old2 ($) { my $name = shift; print "Hello, $name!\n" } # New way sub greet ($name) { say "Hello, $name!"; } greet("Alice"); # prints "Hello, Alice!" - -sub greet ($name) { - say "Hello, $name!"; -} - -greet("Alice"); # prints "Hello, Alice!" ``` -### "normal" subroutine signatures now +In Foostats, constructors declare `sub new ($class, $odds_file, $log_path)`, anonymous callbacks expose `sub ($event)`, and helper subs list the values they expect, e.g.: -Subroutine signatures are active throughout foostats. Constructors declare `sub new ($class, $odds_file, $log_path)`, anonymous callbacks expose `sub ($event)`, and helper subs list the values they expect. +```perl +my $anon = sub ($name) { + say "Hello, $name!"; +}; -## Defined-or assignment keeps defaults obvious +$anon->("World"); # prints "Hello, World!" +``` -### Defaults without boilerplate +## Defined-or assignment for defaults without boilerplate -The operator `//=` keeps configuration and counters simple. Environment variables may be missing when cron runs the script, so `//=`, combined with signatures, sets defaults without warnings. +The operator `//=` keeps configuration and counters simple. Environment variables may be missing when CRON runs the script, so `//=`, combined with signatures, sets defaults without warnings. Example use of that operator: -## `say` is the default voice now +```perl +my $foo; +$foo //= 42; +say $foo; # prints 42 -`say` became the default once the script switched to `use v5.38;`. Log messages such as "Processing $path" or "Writing report to $report_path". It adds a newline to every message printed, comparable to Ruby's `put`. +$foo //= 99; +say $foo; # still prints 42, because $foo was already defined +``` ## Cleanup with `defer` -Even though not used in Foostats, this (borrowed from Go?) feature is neat to have in Perl now. +Even though not used in Foostats, this feature (similar to Go's defer) is neat to have in Perl now. -The `defer` block (`use feature 'defer"`) schedules a piece of code to run when the current scope exits, regardless of how it exits (e.g. normal return, exception). This is perfect for ensuring resources, such as file handles, are closed. `Foostats::Logreader` uses it to make sure log files are always closed, even if parsing fails mid-way. +The `defer` block (`use feature 'defer"`) schedules a piece of code to run when the current scope exits, regardless of how it exits (e.g. normal return, exception). This is perfect for ensuring resources, such as file handles, are closed. ```perl use feature qw(defer); @@ -340,11 +383,11 @@ This pattern replaces manual `close` calls in every exit path of the subroutine ## Builtins and booleans -The script also utilises other modern additions that often go unnoticed. `use builtin qw(true false);` combined with `experimental::builtin` provides more real boolean values. +The script also utilizes other modern additions that often go unnoticed. `use builtin qw(true false);` combined with `experimental::builtin` provides more real boolean values. ## Conclusion -I want to code more in Perl again. The newer features make it a joy to write small scripts like Foostats. If you haven't looked at Perl in a while, give it another try! The main thing which holds me back from writing more Perl is the lack of good tooling. For example, there is no proper LSP and tree sitter support available, which would work as well as for Go and Ruby. +I want to code more in Perl again. The newer features make it a joy to write small scripts like Foostats. If you haven't looked at Perl in a while, give it another try! The main thing which holds me back from writing more Perl is the lack of good tooling. For example, there is no proper LSP and tree sitter support available, which would work as good as the ones available for Go and Ruby. E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/index.md b/gemfeed/index.md index 27e62a19..b9ef80a7 100644 --- a/gemfeed/index.md +++ b/gemfeed/index.md @@ -2,6 +2,7 @@ ## To be in the .zone! +[2025-11-02 - Perl New Features and Foostats](./2025-11-02-perl-new-features-and-foostats.md) [2025-10-11 - Key Takeaways from The Well-Grounded Rubyist](./2025-10-11-key-takeaways-from-the-well-grounded-rubyist.md) [2025-10-02 - f3s: Kubernetes with FreeBSD - Part 7: k3s and first pod deployments](./2025-10-02-f3s-kubernetes-with-freebsd-part-7.md) [2025-09-14 - Bash Golf Part 4](./2025-09-14-bash-golf-part-4.md) diff --git a/gemfeed/stats.md b/gemfeed/stats.md new file mode 100644 index 00000000..e8ae1f4c --- /dev/null +++ b/gemfeed/stats.md @@ -0,0 +1,7 @@ +# Stats + +Here, you can find some statistics! + +[My machine uptime statistics](./uptime-stats.md) +[Site statistics (HTTP)](https://stats.foo.zone) +[Site statistics (Gemini)](gemini://stats.foo.zone) @@ -1,6 +1,6 @@ # Hello! -> This site was generated at 2025-10-31T20:26:55+02:00 by `Gemtexter` +> This site was generated at 2025-11-01T16:10:35+02:00 by `Gemtexter` Welcome to the foo.zone! @@ -9,8 +9,8 @@ Everything you read on this site is my personal opinion and experience. You can ## Some links [About me](./about/index.md) -[My machine uptime statistics](./uptime-stats.md) [Welcome to the Geminispace](./gemfeed/2021-04-24-welcome-to-the-geminispace.md) +[Some stats](./stats.md) ### Webring @@ -38,6 +38,7 @@ Everything you read on this site is my personal opinion and experience. You can ### Posts +[2025-11-02 - Perl New Features and Foostats](./gemfeed/2025-11-02-perl-new-features-and-foostats.md) [2025-10-11 - Key Takeaways from The Well-Grounded Rubyist](./gemfeed/2025-10-11-key-takeaways-from-the-well-grounded-rubyist.md) [2025-10-02 - f3s: Kubernetes with FreeBSD - Part 7: k3s and first pod deployments](./gemfeed/2025-10-02-f3s-kubernetes-with-freebsd-part-7.md) [2025-09-14 - Bash Golf Part 4](./gemfeed/2025-09-14-bash-golf-part-4.md) diff --git a/uptime-stats.md b/uptime-stats.md index 9cb8d307..83c29477 100644 --- a/uptime-stats.md +++ b/uptime-stats.md @@ -1,6 +1,6 @@ # My machine uptime stats -> This site was last updated at 2025-10-31T20:26:55+02:00 +> This site was last updated at 2025-11-01T16:10:35+02:00 The following stats were collected via `uptimed` on all of my personal computers over many years and the output was generated by `guprecords`, the global uptime records stats analyser of mine. |
