Community forum

Please note that VisualCron support is not actively monitoring this community forum. Please use our contact page for contacting the VisualCron support directly.


MarioStuck
2014-11-26T17:40:25Z
Hi dears,

I'm looking for an option to send mails on error with detailed error information.

For the moment we send mail notifications on error with this content:

Ergebnis der letzten Ausführung:
{JOB(Active|Result)}

Fehlerbeschreibung:
{JOB(Active|ExitCode)}

But we are looking for something like {JOB(Active|error)} or {JOB(Active|output)}

Any ideas to get more failure information?

Best regards

Mario Stuck
Sponsor
Forum information
ErikC
2014-11-27T07:42:07Z
Hi Mario,

What I'm doing here, and that might be something for you too, is having a file notification on every task writing the :
- task name
- task output
- task error output
You can set this up in the Flow of every task. Use the PrevTask in the notification to get the current task output, or else you get the results of the task notofication as output in the file.
As a file name, you could use the job name and the current date, so you have a log for every day.

When a job fails, you can send the log file of that day in an e-mail. Use the job flow for this.

Regards,
Erik

Uses Visualcron since 2006.
MKKM0603
2014-11-27T15:39:25Z
Hi Erik,
Have you used XENDAPP to push notification to Smart phone? WHat is the Connection Server in the XENDAPP TAsk setup page?
Support
2014-11-27T15:43:59Z
Originally Posted by: MKKM0603 

Hi Erik,
Have you used XENDAPP to push notification to Smart phone? WHat is the Connection Server in the XENDAPP TAsk setup page?



You do not have to fill in Server in XendApp Connection as it will always connect to the XendApp service.
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
Nautius
2014-12-10T20:17:59Z
Hi Mario,

I have this set up for our organization. It's worked really well for me this far:

Subject: Process {JOB(Active|Name)} Completion Status: {JOB(Active|Result)}

Text Body:

Tasks:
{LOGIC(If|String|{TASK(Active,Order)}|==|1|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|1. {TASK(1,Name)} - {TASK(1,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|1|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(1|ExitCode)}|==|0|{TASK(1|StdOut)}|{TASK(1|ExitCode)} - {TASK(1,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|2|{TASK(2,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|2|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|2. {TASK(2,Name)} - {TASK(2,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|2|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(2|ExitCode)}|==|0|{TASK(2|StdOut)}|{TASK(2|ExitCode)} - {TASK(2,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|3|{TASK(3,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|3|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|3. {TASK(3,Name)} - {TASK(3,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|3|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(3|ExitCode)}|==|0|{TASK(3|StdOut)}|{TASK(3|ExitCode)} - {TASK(3,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|4|{TASK(4,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|4|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|4. {TASK(4,Name)} - {TASK(4,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|4|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(4|ExitCode)}|==|0|{TASK(4|StdOut)}|{TASK(4|ExitCode)} - {TASK(4,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|5|{TASK(5,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|5|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|5. {TASK(5,Name)} - {TASK(5,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|5|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(5|ExitCode)}|==|0|{TASK(5|StdOut)}|{TASK(5|ExitCode)} - {TASK(5,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|6|{TASK(6,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|6|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|6. {TASK(6,Name)} - {TASK(6,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|6|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(6|ExitCode)}|==|0|{TASK(6|StdOut)}|{TASK(6|ExitCode)} - {TASK(6,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|7|{TASK(7,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|7|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|7. {TASK(7,Name)} - {TASK(7,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|7|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(7|ExitCode)}|==|0|{TASK(7|StdOut)}|{TASK(7|ExitCode)} - {TASK(7,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|8|{TASK(8,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|8|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|8. {TASK(8,Name)} - {TASK(8,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|8|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(8|ExitCode)}|==|0|{TASK(8|StdOut)}|{TASK(8|ExitCode)} - {TASK(8,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|9|{TASK(9,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|9|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|9. {TASK(9,Name)} - {TASK(9,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|9|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(9|ExitCode)}|==|0|{TASK(1|StdOut)}|{TASK(9|ExitCode)} - {TASK(9,StdErr)})}|)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|10|{TASK(10,Name)}|)}
{LOGIC(If|String|{TASK(Active,Order)}|==|10|{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|10. {TASK(10,Name)} - {TASK(10,Result)}|)}|)}

{LOGIC(If|String|{TASK(Active,Order)}|==|10|{LOGIC(If|String|{TASK(Active,IsActive)}|==|True|{LOGIC(If|String|{TASK(10|ExitCode)}|==|0|{TASK(10|StdOut)}|{TASK(10|ExitCode)} - {TASK(10,StdErr)})}|)}|)}
mb2019
2019-03-26T14:48:39Z
I face a problem when the notification becomes to long. I've extended Nautius' post (very helpful).
Adding the 25th row results in: TranslateVariables->Infinite loop error on string

I think it is related to the number of variables that need to be processed to create the notification email. When I added an extra column, I needed to lower the number of rows to 24 to work around the error (TranslateVariables->Infinite loop error on string)

<!DOCTYPE html>
<html>
<body>
<table>
<tr><td valign="top">batch</td> <td>{JOB(Active|Name)}</td><td></td><td></td></tr>
<tr><td valign="top"></td> <td>{JOB(Active|Desc)}</td><td></td><td></td></tr>
<tr><td valign="top">status</td> <td><b>{JOB(Active|Result)}</b></td><td></td><td></td></tr>
<tr><td valign="top">duration</td><td>{JOB(Active|ExecutionTime|hh\:mm\:ss)}</td><td></td><td></td></tr>
<tr><td valign="top">start</td> <td>{JOB(Active|LastRun|d/MM/yyyy H:mm)}</td><td></td><td></td></tr>
<tr><td valign="top">end</td> <td>{JOB(Active|LastExited|d/MM/yyyy H:mm)}</td><td></td><td></td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|1|{TASK(1,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|1|<td valign="top">1.</td> <td>{TASK(1|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(1,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(1,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|2|{TASK(2,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|2|<td valign="top">2.</td> <td>{TASK(2|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(2,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(2,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|3|{TASK(3,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|3|<td valign="top">3.</td> <td>{TASK(3|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(3,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(3,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|4|{TASK(4,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|4|<td valign="top">4.</td> <td>{TASK(4|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(4,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(4,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|5|{TASK(5,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|5|<td valign="top">5.</td> <td>{TASK(5|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(5,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(5,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|6|{TASK(6,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|6|<td valign="top">6.</td> <td>{TASK(6|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(6,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(6,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|7|{TASK(7,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|7|<td valign="top">7.</td> <td>{TASK(7|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(7,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(7,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|8|{TASK(8,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|8|<td valign="top">8.</td> <td>{TASK(8|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(8,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(8,Result)}|Disabled|)}|)}</td></tr>
<tr> {LOGIC(If|String|{TASK(Active,Order)}|==|9|{TASK(9,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|9|<td valign="top">9.</td> <td>{TASK(9|LastRun|d/MM/yyyy H:mm)}</td> <td>{TASK(9,Name)}</td> <td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(9,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|10|{TASK(10,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|10|<td valign="top">10.</td><td>{TASK(10|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(10,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(10,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|11|{TASK(11,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|11|<td valign="top">11.</td><td>{TASK(11|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(11,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(11,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|12|{TASK(12,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|12|<td valign="top">12.</td><td>{TASK(12|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(12,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(12,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|13|{TASK(13,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|13|<td valign="top">13.</td><td>{TASK(13|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(13,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(13,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|14|{TASK(14,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|14|<td valign="top">14.</td><td>{TASK(14|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(14,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(14,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|15|{TASK(15,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|15|<td valign="top">15.</td><td>{TASK(15|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(15,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(15,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|16|{TASK(16,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|16|<td valign="top">16.</td><td>{TASK(16|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(16,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(16,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|17|{TASK(17,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|17|<td valign="top">17.</td><td>{TASK(17|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(17,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(17,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|18|{TASK(18,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|18|<td valign="top">18.</td><td>{TASK(18|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(18,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(18,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|19|{TASK(19,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|19|<td valign="top">19.</td><td>{TASK(19|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(19,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(19,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|20|{TASK(20,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|20|<td valign="top">20.</td><td>{TASK(20|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(20,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(20,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|21|{TASK(21,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|21|<td valign="top">21.</td><td>{TASK(21|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(21,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(21,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|22|{TASK(22,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|22|<td valign="top">22.</td><td>{TASK(22|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(22,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(22,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|23|{TASK(23,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|23|<td valign="top">23.</td><td>{TASK(23|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(23,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(23,Result)}|Disabled|)}|)}</td></tr>
<tr>{LOGIC(If|String|{TASK(Active,Order)}|==|24|{TASK(24,Name)}|)}{LOGIC(If|String|{TASK(Active,Order)}|==|24|<td valign="top">24.</td><td>{TASK(24|LastRun|d/MM/yyyy H:mm)}</td><td>{TASK(24,Name)}</td><td>{LOGIC(If|String|{TASK(Active|IsActive)}|==|True|{TASK(24,Result)}|Disabled|)}|)}</td></tr>
</table>
</body>
</html>


jrtwynam
2019-03-28T13:58:36Z
You can get much of the way there by using VC's API to pull info on the job and its tasks. I say "much of the way there" because I haven't yet figured out how to pull a task's result and last run time using the API, and those are obviously crucial pieces of information for this particular use.

Anyway, what I've done is created a separate job called "Generate Task Error Report", and in the flow of each task, I can change the "On Error" to run this job. The job does this:


  1. Uses an HTTP task to hit the API and create an Authorization Token.
  2. Stores that authorization token in a VC variable for use later on.
  3. Uses an HTTP task to hit the API and get info on the job in question, passing it {JOB(Active|Variable|Job ID)}.
  4. Uses an HTTP task to hit the API and get info on the tasks within the job in question, again passing it {JOB(Active|Variable|Job ID)}.
  5. Loops through the list of tasks and constructs an HTML table with the data.
  6. Emails the results to myself.


The resulting email looks like this:
Capture.PNG

Although this concept seems to work perfectly, for this use it's really not very useful since the API for the tasks on a job doesn't return the required information. Maybe that's an idea for an upgrade - it would be nice if the API for the tasks would return ALL of the data that's visible within the client UI, most notably the task's result and last run time.



Scroll to Top