How do I add info to the Certify Logfile?

I can see that the logfile name is:
$env:ProgramData + “\certify\logs\log_” + $result.ManagedItem.Id + “.txt”
but this may not be true in all cases?

Is there any way to get the logfile name or call a function to log stuff?
I am using “Add-Content $logpath” right now – but is that the “proper” way to do this?
Also, being able to use the standard line-prefix builder would be nice.
Failing that - where might that code chunk be? I could port it to PS.

At least the run start/end and task name is logged. :slight_smile:

2023-08-06 18:59:29.439 -06:00 [INF] ---- Performing Task [On-Demand or Manual Execution] :: Run Powershell Script ----
2023-08-06 18:59:29.507 -06:00 [INF] Task [Run Powershell Script] :: Task is being has been forced to run. Normal status would be [Task is enabled but will not run because primary request unsuccessful.]
2023-08-06 18:59:29.532 -06:00 [INF] Executing command via PowerShell
***** my output *****
2023-08-06 18:59:38.251 -06:00 [INF] Waiting for powershell to complete..5s
Powershell Task Completed.

Maybe there’s some standard powershell way - but as most of what I see does not appear to be powershell-generated, I have my doubts.

Am I missing something obvious?
Something buried somewhere is the docs?
There doesn’t look to be anything useful in the $result variable related to this.

Hi, no you definitely don’t need to do that usually, and instead standard output is normally directed to the log file automatically. What is your script actually doing? Are you using the default in-process PowerShell execution or are you running as new process?

All text that goes to the Powershell “standard output” stream ends up as INF messages in the log file, errors should show up as ERR and the task should fail as a result.

If you attempt your own logging to the same log file your results may get clobbered when our Serilog buffer gets flushed to disk (maybe it won’t?) or you might cause a sharing contention on the file.

Our stream capture setup is defined here:

So if you just wanted a message output to the log file you would use Write-Output or Write-Error

Yes - this is the missing datum: “Certify traps the standard output”.
Maybe it’s in the doc somewhere, but I didn’t see it.
Default exec modes across the board (rule of thumb: change nothing until you have to).

And yes – conflicts with buffering, async tasks, and who knows what else was a big worry.

The scripts are going to do a bunch of things using the cPanel API via Invoke-WebRequest:

  • Install the new cert into/via cPanel
  • Figure out if there’s wildcard subdomains that need to be updated
  • Cleanout old garbage
    Details subject to change of course.
    I already know I can “hit” the cPanel API and get results, while running from Certify,
    so all the rest is just grunt work now.

Just tested and maybe spotted a bug.
First, just:
Write-Output “$logpath1” # logpath1 is just a leftover handy text string
Write-Output “xxx”

This yields:

2023-08-06 20:45:06.193 -06:00 [INF] ---- Performing Task [On-Demand or Manual Execution] :: Run cPanel Powershell ----
2023-08-06 20:45:06.195 -06:00 [INF] Task [Run cPanel Powershell] :: Task is being has been forced to run. Normal status would be [Task is enabled but will not run because primary request unsuccessful.]
2023-08-06 20:45:06.195 -06:00 [INF] Executing command via PowerShell
2023-08-06 20:45:06.372 -06:00 [INF] C:\ProgramData\certify\logs\log_487e154f-1868-47e2-b19b-a4d1377339fd.txt
Powershell Task Completed.

So – How do I get the second Write-Output to have it’s prefix?

But here’s a bigger issue (which may be related to the missing prefix on line 2):
Write-Output “$logpath1”
Write-Output “xxx”
Write-Error “Something broke!!!”

It properly yields a popup in the UI showing the error.
BUT - the “INF” lines are changed to “ERR” and the actual Write-Error is just some text at the end of “Completed”.

2023-08-06 20:57:22.376 -06:00 [INF] ---- Performing Task [On-Demand or Manual Execution] :: Run cPanel Powershell ----
2023-08-06 20:57:22.381 -06:00 [INF] Task [Run cPanel Powershell] :: Task is being has been forced to run. Normal status would be [Task is enabled but will not run because primary request unsuccessful.]
2023-08-06 20:57:22.381 -06:00 [INF] Executing command via PowerShell
2023-08-06 20:57:22.554 -06:00 [ERR] C:\ProgramData\certify\logs\log_487e154f-1868-47e2-b19b-a4d1377339fd.txt
Powershell Task Completed.Error: cPanel.ps1: Something broke!!!

Maybe this is “per design” – or a “dang didn’t know it did that, but it’s ‘per design’ now.” LOL
Note the text “Error:” on that last line probably should have a leading space.

I could dig into the C# but would have to dust off old brain cells that haven’t been used in a decade or two, and my brain is kinda busy learning PowerShell (never did more than “Hello World” until yesterday).

P.S. I’m guessing that if I “catch” an error and a retry works, I better not “Write-Error” to log that -
thinking that you kill the task on any error – or maybe there’s a parm to say “it’s OK-fixed now”.

Thanks, yes the handing of the log stream from powershell isn’t particularly sophisticated, if you output anything to the error stream the task fails.

Currently everything from the powershell script is written as one log entry which is why you only get one INF or ERR:


I’ll look into whether we can make that a little better without breaking what we have! We also have some ongoing work for better log parsing elsewhere in the app, mainly for our upcoming web version.

Sounds good!
For my scripts, it’s not going to be an issue – now that I know the rules.
I’ll just have a “sub-level” of INF if I ever need it.

A quick google shows things like “$ErrorAction” and other stuff that needs a deeper dive –
But for my current case, a retry can be done with a manual invoke, so I’ll just ERR on failure - with a good explanation. My design will be checking and cross-checking current status of “all the things” before doing anything, so no issues with a retry after partial execution.

Great, note that if a task does fail the renewal will be automatically re-attempted as a whole later (but it includes re-order the cert which counts against your CA rate limits).

You should definitely try to do the least amount of work in your task as you can and if it’s going to be something that has good chance of failing I’d recommend writing out the cert to a pickup location then pickup and process that with a different scheduled task. You can also use a Deployment Task to push the cert to a secrets vault like Azure Keyvault then pull that down in your own scheduled task etc. This has the advantage of fully de-coupling cert renewal from cert deployment.

“This has the advantage of fully de-coupling cert renewal from cert deployment.”
But you have deployment stuff all over the UI.
I am just adding a new one – as discussed in the thread you told me to not use any more.
It is really no more and no less than a deploy to a server’s file-system.

In any event, I just had an initial success running with hard-coded parameters under the IDE,
so proof of concept is there. Now, I just need to deal with wildcards and sub-domains (which will actually be more difficult), and ensure I’ve got my error handling/logging all dealt with - turns out a cPanel API fail doesn’t return a “bad” HTTP response, as I was expecting - but that actually makes life easier because of the powershell die-on-error you told me about in this thread.

P.S. Because the cPanel API wants PEMs, I precede my task with exports of cert and chain (although I really only need the cert - cPanel already has and maintains the proper Let’s Encrypt chain).

The most common failure is going to be connecting to the target server - which will be rare of course.

The key is already in the user directory I’m running in, and for management reasons, I use “static” CSRs & keys in Certify as AutoSSL does when it’s available (I’ve had too many customers over my years of Hosting Support that want it that way so they don’t have to constantly clean old stuff off the server).