* Re: A program that can get exactly the log of a supervised process? [not found] <YXQyNQbpPZBKYLXC@caspervector> @ 2021-10-24 6:20 ` Laurent Bercot 2021-10-24 7:20 ` Casper Ti. Vector [not found] ` <YXUJKWltk+OwYhtf@caspervector> 0 siblings, 2 replies; 10+ messages in thread From: Laurent Bercot @ 2021-10-24 6:20 UTC (permalink / raw) To: supervision >Any idea on how the log "teeing" may be done cleanly (and portably >if possible; something akin to `tail -f' seems unsuitable because of >potential log rotation), and perhaps any flaw or redundancy in the >design above? The obstacle I have always bumped against when trying to do similar things is that the teeing program always has to remain there, even after it has done its job (it has read the readiness line and informed the supervisor). And so, instead of "service | logger", your data flow permanently becomes "service | loggrep | logger" before readiness, and "service | cat | logger" after readiness (the best loggrep can do is exec into cat, or reimplement its functionality, once it has read its readiness line). That wouldn't be a huge performance problem, especially if "cat" can do zero-copy data, but it is definitely a reliability problem: - loggrep must die when the service dies, so a new loggrep can be run when the service runs again. So loggrep cannot be run as a separate supervised service in the same service pipeline. (If loggrep were to restart independently from service, it would need to check whether service is ready, and run as 'cat' if it is. This is doable, but more complex.) - That means that either the pipe between service and loggrep cannot be held, or loggrep must have an additional notification that service died. This is, again, doable, but more complex. - If loggrep isn't supervised, and the pipe isn't being held, then killing loggrep will incur a broken pipe, which means a service restart with a lost line of logs, which supervision aims to avoid. So basically, either loggrep is a simple tee-like program but you weaken the supervision properties of the service, or the functionality needs to be embedded in the supervision architecture, with loggrep being a consumer for service and a producer for logger (which is easy with s6-rc but not so much with pure s6) and loggrep always watching the state of service (which is not so easy with s6-rc, where you don't know the full path to another service directory). In short: practical issues. It's impossible to do that in a clean, satisfying way. And it entirely makes sense that it's so difficult, because the very idea is to use the *data flow* to inform the *control flow*, and that is inherently dangerous and not planned for in supervision architectures. Making your control flow depend on your data flow is not a good pattern at all, and I really wish daemons would stop doing that. I'm sorry I don't have a better answer. -- Laurent ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2021-10-24 6:20 ` A program that can get exactly the log of a supervised process? Laurent Bercot @ 2021-10-24 7:20 ` Casper Ti. Vector [not found] ` <YXUJKWltk+OwYhtf@caspervector> 1 sibling, 0 replies; 10+ messages in thread From: Casper Ti. Vector @ 2021-10-24 7:20 UTC (permalink / raw) To: supervision On Sun, Oct 24, 2021 at 06:20:53AM +0000, Laurent Bercot wrote: > So basically, either loggrep is a simple tee-like program but you > weaken the supervision properties of the service, or the functionality > needs to be embedded in the supervision architecture, with loggrep > being a consumer for service and a producer for logger (which is > easy with s6-rc but not so much with pure s6) and loggrep always > watching the state of service (which is not so easy with s6-rc, where > you don't know the full path to another service directory). Well, I do realise the lifespan issue of the loggrep program, which is why I asked the question in the first place. But I really never thought of directly inserting loggrep into the logging chain as a new node; instead, what I have thought is making loggrep a program "attachable" to the logger. That is, the logger is extended with a listener which at least one client can connect to, and which upon connection tees the log to the client. I do not know whether you have similar ideas. Additionally, I have just noticed a race condition in the origin design in my question. If loggrep is double-forked by an external program (execline or so), the daemon may become ready before loggrep is ready to receive logs; a better way is to let loggrep do the double fork itself, after the teeing pipe is ready. The downside is that errors deemed tolerable by the daemon but fatal by the user would then need to be explicitly handled by loggrep; but this is probably already over-design, so perhaps it just does not matter... -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2022.09.20) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <YXUJKWltk+OwYhtf@caspervector>]
* Re: A program that can get exactly the log of a supervised process? [not found] ` <YXUJKWltk+OwYhtf@caspervector> @ 2021-10-25 12:37 ` Laurent Bercot 2021-10-25 12:57 ` Rio Liu 2021-10-25 16:00 ` Casper Ti. Vector 0 siblings, 2 replies; 10+ messages in thread From: Laurent Bercot @ 2021-10-25 12:37 UTC (permalink / raw) To: Casper Ti. Vector, supervision >Well, I do realise the lifespan issue of the loggrep program, which is >why I asked the question in the first place. But I really never thought >of directly inserting loggrep into the logging chain as a new node; >instead, what I have thought is making loggrep a program "attachable" to >the logger. That is, the logger is extended with a listener which at >least one client can connect to, and which upon connection tees the log >to the client. I do not know whether you have similar ideas. Well in theory you could have something like skabus-dyntee ( https://skarnet.org/software/skabus/skabus-dyntee.html ) as your logger, and have your "real" logger run as a skabus-dyntee client. Then you could add a loggrep as a second skabus-dyntee client, and it would just disappear when it has finished its work. It would be a little unreliable as is, because skabus-dyntee doesn't care if it has no client at all, so if the real logger dies, it won't block the log stream until the real logger has restarted, so you may lose logs. But apart from that, it would work. A really reliable solution would be having a skabus-dyntee equivalent that has one permanent output and blocks as long as that output isn't there. As you say, it would be a logger extended with a listener. Another question is how to piggyback loggrep into the notification mechanism: if loggrep is tied to the logger and not to the service, it doesn't have native access to the notification pipe. That means a specific mechanism is needed to give it cross-service access. That's definitely a lot of code and a lot of architectural convolutions to accommodate what is ultimately a daemon misdesign. But it's probably the least bad way to do it, so I might think about it more and add something like that to s6 in the distant future. -- Laurent ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2021-10-25 12:37 ` Laurent Bercot @ 2021-10-25 12:57 ` Rio Liu 2021-10-25 13:26 ` Laurent Bercot 2021-10-25 16:00 ` Casper Ti. Vector 1 sibling, 1 reply; 10+ messages in thread From: Rio Liu @ 2021-10-25 12:57 UTC (permalink / raw) To: supervision [-- Attachment #1: Type: text/plain, Size: 2147 bytes --] Why not have the grepper listen on the log file directly? You'll need to have a timestamp in the log and know where the log is, but those can be known at the time of writing the service script. --------原始郵件-------- 在 2021年10月25日 08:37, Laurent Bercot 寫道: >>Well, I do realise the lifespan issue of the loggrep program, which is >>why I asked the question in the first place. But I really never thought >>of directly inserting loggrep into the logging chain as a new node; >>instead, what I have thought is making loggrep a program "attachable" to >>the logger. That is, the logger is extended with a listener which at >>least one client can connect to, and which upon connection tees the log >>to the client. I do not know whether you have similar ideas. > > Well in theory you could have something like skabus-dyntee > ( https://skarnet.org/software/skabus/skabus-dyntee.html ) as your > logger, and have your "real" logger run as a skabus-dyntee client. > Then you could add a loggrep as a second skabus-dyntee client, and it > would just disappear when it has finished its work. > > It would be a little unreliable as is, because skabus-dyntee doesn't > care if it has no client at all, so if the real logger dies, it won't > block the log stream until the real logger has restarted, so you may > lose logs. But apart from that, it would work. > > A really reliable solution would be having a skabus-dyntee equivalent > that has one permanent output and blocks as long as that output isn't > there. As you say, it would be a logger extended with a listener. > > Another question is how to piggyback loggrep into the notification > mechanism: if loggrep is tied to the logger and not to the service, > it doesn't have native access to the notification pipe. That means a > specific mechanism is needed to give it cross-service access. > > That's definitely a lot of code and a lot of architectural > convolutions to accommodate what is ultimately a daemon misdesign. > But it's probably the least bad way to do it, so I might think about it > more and add something like that to s6 in the distant future. > > -- > Laurent ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2021-10-25 12:57 ` Rio Liu @ 2021-10-25 13:26 ` Laurent Bercot 0 siblings, 0 replies; 10+ messages in thread From: Laurent Bercot @ 2021-10-25 13:26 UTC (permalink / raw) To: Rio Liu, supervision >Why not have the grepper listen on the log file directly? You'll need to have a timestamp in the log and know where the log is, but those can be known at the time of writing the service script. There's no such thing as "the log file". There's the log backendS, which can be one or more automatically rotated log files in a directory, status files, network backends, etc. The only way to access the log stream in a reliable and generic way is to read it on the way to the backends. You have no control over what happens later on. -- Laurent ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2021-10-25 12:37 ` Laurent Bercot 2021-10-25 12:57 ` Rio Liu @ 2021-10-25 16:00 ` Casper Ti. Vector 1 sibling, 0 replies; 10+ messages in thread From: Casper Ti. Vector @ 2021-10-25 16:00 UTC (permalink / raw) To: supervision On Mon, Oct 25, 2021 at 12:37:41PM +0000, Laurent Bercot wrote: > Another question is how to piggyback loggrep into the notification > mechanism: if loggrep is tied to the logger and not to the service, > it doesn't have native access to the notification pipe. That means a > specific mechanism is needed to give it cross-service access. As has been sketched in previous mails, make loggrep a double-forking chainloader, where the grandparent blocks (before closing the notification fd and then chaining) until the grandchild is ready to accept logs (after connecting to the logger and spawning the "grep"; the latter perhaps being an awk script in most cases)? > But it's probably the least bad way to do it, [...] I fullly agree. This is the crux of the problem. -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2022.09.20) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C ^ permalink raw reply [flat|nested] 10+ messages in thread
* A program that can get exactly the log of a supervised process? @ 2021-10-23 16:03 Casper Ti. Vector 2023-06-22 17:44 ` Casper Ti. Vector 0 siblings, 1 reply; 10+ messages in thread From: Casper Ti. Vector @ 2021-10-23 16:03 UTC (permalink / raw) To: supervision Many daemons output some lines in their logs (here assumed to have been redirected to logging pipes in some supervision framework) that can be used as a kind of markers for readiness. So if we can implement the following program, we will able to trivially add readiness support to these daemons without patching their source code, while reducing the daemon-specific code (the pattern recogniser) to a minimum: * The program is double-forked from the ./run script of a service, and also watches for the death of the daemon: in case the daemon dies before logging the readiness marker (and optionally, if a specified timeout is reached), this program dies as well, killing its subprocess (the pattern recogniser, discussed below). To maximise portability across supervision frameworks, the death notification can be implemented with a pipe that can be written to by an ancillary program ran from the ./finish script. * The program somehow (directly or indirectly) gets a copy of the log from the reading side of the logging pipe, and feeds it into a specified pattern recogniser, which should exit 0 upon finding the readiness marker. A special exit value of the subprocess can be considered a notification for fatal error erroneously ignored by the daemon, leading to the program exiting some special value which can be handled by a `s6-svc -t' invocation. In order to avoid potential feedback loops, the subprocess should be killed (and waited for) before the program outputs any warning; the subprocess should be responsible for keeping itself quiet when running normally. Any idea on how the log "teeing" may be done cleanly (and portably if possible; something akin to `tail -f' seems unsuitable because of potential log rotation), and perhaps any flaw or redundancy in the design above? -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2022.09.20) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2021-10-23 16:03 Casper Ti. Vector @ 2023-06-22 17:44 ` Casper Ti. Vector 2023-06-22 19:39 ` Casper Ti. Vector 0 siblings, 1 reply; 10+ messages in thread From: Casper Ti. Vector @ 2023-06-22 17:44 UTC (permalink / raw) To: supervision On Sun, Oct 24, 2021 at 12:03:01AM +0800, Casper Ti. Vector wrote: > Any idea on how the log "teeing" may be done cleanly (and portably > if possible; something akin to `tail -f' seems unsuitable because of > potential log rotation), and perhaps any flaw or redundancy in the > design above? The recordio program is extremely enlightening here: * Instead of trying to communicate with the logger, our program can directly sit between the service and the logging pipe. (This also solves the lifespan issue cleanly, saving lots of code; the latter is apart from the lots of code to talk with the logger.) * When forking, we may let the parent (instead of the child) exec()s into the service, so our program does not need to forward signals. (But the loggrep subprocess from our program may die after the supervisor receives SIGCHLD from the service; therefore in order not to interfere with the next run of the service, we should ensure the loggrep program would exit on EOF and does not produce spurious outputs on its stdout.) The source code of the program, logtee (licence: CC0), is available at: <https://cpaste.org/?fa30831511a456b7=#ECwUd1YaVQBLUokynQbRYZq5wvBvXXeXo3bQoeL2rL4L> It may be tested with (logtee is itself init-agnostic; writing an adapter to, for instance, s6, should be an easy exercise in the manipulation of argv): ------------------------------------------------------------------------ #!/bin/execlineb -P fdmove -c 3 1 logtee { fdmove 1 3 if { timeout 3 grep -q "bytes from" } echo } fdclose 3 fdmove -c 2 1 ping -i 10 example.com ------------------------------------------------------------------------ -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2024.09.30) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2023-06-22 17:44 ` Casper Ti. Vector @ 2023-06-22 19:39 ` Casper Ti. Vector 2023-06-22 19:43 ` Casper Ti. Vector 0 siblings, 1 reply; 10+ messages in thread From: Casper Ti. Vector @ 2023-06-22 19:39 UTC (permalink / raw) To: supervision On Fri, Jun 23, 2023 at 01:44:19AM +0800, Casper Ti. Vector wrote: > The source code of the program, logtee (licence: CC0), is available at: > <https://cpaste.org/?fa30831511a456b7=#ECwUd1YaVQBLUokynQbRYZq5wvBvXXeXo3bQoeL2rL4L> Sorry, patch (the first hunk is cosmetic): --- logtee.c 2023-06-23 03:33:57.233531347 +0800 +++ logtee.c 2023-06-23 03:33:05.693672295 +0800 @@ -29,7 +29,7 @@ *len = 0; return 1; } if (iopause_g (x, 2 - !x[1].fd, 0) < 0) strerr_diefu1sys (111, "iopause_g"); - for (i = 0; i < 2; ++i) if (x[i].fd && x[i].revents) { + for (i = 0; i < 2; ++i) if (x[i].fd > 0 && x[i].revents) { r = fd_write (x[i].fd, buf + pos[i], *len - pos[i]); if (r < 0) { if (!i) return 0; @@ -57,8 +57,9 @@ int main (int argc, char const **argv, char const *const *envp) { int pir[2], fdc, fdw, argc1; PROG = "logtee"; ++argv; --argc; - if ((argc1 = el_semicolon (argv)) >= argc) - { strerr_dief1x (100, "unterminated block"); } + argc1 = el_semicolon (argv); + if (argc1 >= argc) strerr_dief1x (100, "unterminated block"); + if (!argv[0] || !argv[argc1 + 1]) strerr_dief1x (100, "empty program"); argv[argc1] = 0; if (pipe (pir) < 0) strerr_diefu1sys (111, "pipe"); if ((fdc = selfpipe_init ()) < 0) strerr_diefu1sys (111, "selfpipe_init"); -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2024.09.30) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: A program that can get exactly the log of a supervised process? 2023-06-22 19:39 ` Casper Ti. Vector @ 2023-06-22 19:43 ` Casper Ti. Vector 0 siblings, 0 replies; 10+ messages in thread From: Casper Ti. Vector @ 2023-06-22 19:43 UTC (permalink / raw) To: supervision On Fri, Jun 23, 2023 at 03:39:39AM +0800, Casper Ti. Vector wrote: > + if (!argv[0] || !argv[argc1 + 1]) strerr_dief1x (100, "empty program"); > argv[argc1] = 0; Well, these two lines should be swapped. Sorry for the spam :( -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2024.09.30) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-06-22 19:43 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <YXQyNQbpPZBKYLXC@caspervector> 2021-10-24 6:20 ` A program that can get exactly the log of a supervised process? Laurent Bercot 2021-10-24 7:20 ` Casper Ti. Vector [not found] ` <YXUJKWltk+OwYhtf@caspervector> 2021-10-25 12:37 ` Laurent Bercot 2021-10-25 12:57 ` Rio Liu 2021-10-25 13:26 ` Laurent Bercot 2021-10-25 16:00 ` Casper Ti. Vector 2021-10-23 16:03 Casper Ti. Vector 2023-06-22 17:44 ` Casper Ti. Vector 2023-06-22 19:39 ` Casper Ti. Vector 2023-06-22 19:43 ` Casper Ti. Vector
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).