/***************************************************************************************
This script returns a (graphical) timeline for all SQL jobs using google graph
****************************************************************************************
Version:      1.1
Author:      Theo Ekelmans
Email:      theo@ekelmans.com
Date:      2015-06-24

Version:     1.2
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2015-07-28
Change:     Updated using feedback from the SqlServerCentral Community

Version:     2.0
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2015-07-28
Change:     Added an option to split multiple days into seperate graphs as requested by 
         the SqlServerCentral Community

Version:     2.1
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2016-01-19
Change:     Day of week added
            
Version:     2.2
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2016-02-22
Change:     Option for DateRange bar added
            
Version:     2.3
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2016-05-20
Change:     DateRange fixed to begin and end of day
                        
Version:     3.0
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2017-05-03
Change:     Added an option to show either show Category/Job or Job/Step
         Solved a few bugs that limited the number of days this report can span
         Note: 14 days will take about 40 seconds to render !!

Version:	  3.1
Author:	  Theo Ekelmans
Email:	  theo@ekelmans.com
Date:	  2019-02-01
Change:	  Fixed a minor NULL bug for a French Admin (Thanks for the help Salam :)
		  
              "height": '+cast(isnull(@HeightInPixels, 250) as varchar(10))+',
              "width": '+cast(isnull(@WidthInPixels, 1800) as varchar(10))+'

Version:     4.0
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2017-05-12
Change:     Added an option to show either one timeline, or one timeline per day


Version:     4.1
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2019-05-01
Change:     split a few strings into smaller ones

Version:     4.2
Author:     Theo Ekelmans
Email:     theo@ekelmans.com
Date:     2020-06-19
Change:     Small changes in the sequences of text due to the new release of google charts

Version:     4.3
Author:     Theo Ekelmans / Hendrik Burmann 
Email:     theo@ekelmans.com
Date:     2020-06-19
Change:     2 bugfixes by Hendrik Burmann 


****************************************************************************************/
set nocount on

declare @dt datetime 
declare @StartDT datetime 
declare @EndDT datetime 
declare @SDT datetime 
declare @EDT datetime 
declare @MaxEDT datetime 
declare @MinRuntimeInSec int
declare @SendMail int
declare @ReturnRecocordset int
declare @Emailprofilename varchar(50)
declare @EmailRecipients varchar(50)
declare @CategoryCount int
declare @CategoryJobCount float
declare @Teller int
declare @HeightInPixels int
declare @WidthInPixels int
declare @RowHeightInPixels int
declare @AddDateRangeBar int
declare @Show varchar(50)
declare @ShowDays varchar(50)
declare @sql nvarchar(4000)

--***************************************************************************************
-- Set variables
--***************************************************************************************
set @Teller = 1 

-- Last week
set @StartDT = getdate() - 8
set @EndDT = getdate() 
set @MinRuntimeInSec = 5 --Ignore jobs with runtime smaller then this
set @WidthInPixels = 1900 -- The width of the graph per day (increase this value to show more detail)
set @RowHeightInPixels = 35 -- Base for graph height calculation
set @AddDateRangeBar = 1 -- Add the daterange bar for reference (ignored for single timeline)

-- Only last night from 18:00 until today 10:00
--set @StartDT = convert(varchar(10), cast(getdate() -1 as date), 120) + ' 18:00:00' -- getdate() - 5
--set @EndDT = convert(varchar(10), cast(getdate() as date), 120) + ' 10:00:00' -- getdate() 
--set @MinRuntimeInSec = 5 --Ignore jobs with runtime smaller then this
--set @WidthInPixels = 1900 -- The width of the graph per day (increase this value to show more detail)
--set @RowHeightInPixels = 20 -- Base for graph height calculation
--set @AddDateRangeBar = 1 -- Add the daterange bar for reference (ignored for single timeline)

--Choose one of the 2 show days options below
set @ShowDays = 'MultiDayTimeline' -- For the entire week
--set @ShowDays = 'OneTimeline' -- For one day, or more days as one timemline (make sure @WidthInPixels is large enough)

--Choose one of the 2 show options below
set @Show = 'Category/Job' 
--set @Show = 'Job/Step'

set @ReturnRecocordset = 0 
set @SendMail = 1
set @Emailprofilename = 'Ordina'--'<MailProfileName>'
set @EmailRecipients = 'theo.ekelmans@ordina.nl'--'<email>'


--***************************************************************************************
-- Pre-run cleanup (just in case)
--***************************************************************************************
IF OBJECT_ID('tempdb..##JobRuntime') IS NOT NULL DROP TABLE ##JobRuntime;
IF OBJECT_ID('tempdb..##GoogleGraph') IS NOT NULL DROP TABLE ##GoogleGraph;
IF OBJECT_ID('tempdb..##GoogleDiv') IS NOT NULL DROP TABLE ##GoogleDiv;
IF OBJECT_ID('tempdb..##GoogleDraw') IS NOT NULL DROP TABLE ##GoogleDraw;
IF OBJECT_ID('tempdb..#Dates') IS NOT NULL DROP TABLE #Dates;

--***************************************************************************************
-- Create the tables for HTML assembly
--***************************************************************************************
create table ##GoogleGraph ([ID] [int] IDENTITY(1,1) NOT NULL,
                     [HTML] [varchar](max) NULL)

create table ##GoogleDiv ([ID] [int] IDENTITY(1,1) NOT NULL,
                     [HTML] [varchar](max) NULL)

create table ##GoogleDraw ([ID] [int] IDENTITY(1,1) NOT NULL,
                     [HTML] [varchar](max) NULL)

create table #Dates   ([StartDT] datetime NOT NULL,
                     [EndDT] datetime NOT NULL)

--***************************************************************************************
-- Break the range into days
--***************************************************************************************
;WITH w(DT) AS
(        SELECT    cast(cast(@StartDT as int) as datetime)
        UNION ALL
        SELECT    dateadd(day, 1 ,w.DT) 
        FROM    w 
        WHERE    w.DT < @EndDT - 1 
)
INSERT INTO #Dates
SELECT    DT
        ,dateadd(day, 1 ,DT) 
FROM    w 
OPTION (MAXRECURSION 1000);

--***************************************************************************************
-- Create the Job Runtime information table
--***************************************************************************************
if @Show = 'Category/Job'

    set @sql = '
    select    job.name as JobName
            ,cat.name as CatName
            ,CONVERT(DATETIME, CONVERT(CHAR(8), run_date, 112) + '' '' + STUFF(STUFF(RIGHT(''000000'' + CONVERT(VARCHAR(8), run_time), 6), 5, 0, '':''), 3, 0, '':''), 120) as SDT
            ,dateadd(    s,
                        ((run_duration/10000)%100 * 3600) + ((run_duration/100)%100 * 60) + run_duration%100 ,
                        CONVERT(DATETIME, CONVERT(CHAR(8), run_date, 112) + '' '' + STUFF(STUFF(RIGHT(''000000'' + CONVERT(VARCHAR(8), run_time), 6), 5, 0, '':''), 3, 0, '':''), 120) 
                    ) as EDT
    into    ##JobRuntime
    FROM    msdb.dbo.sysjobs job 
                left JOIN msdb.dbo.sysjobhistory his
                    ON his.job_id = job.job_id
                INNER JOIN msdb.dbo.syscategories cat
                    ON job.category_id = cat.category_id
    where    CONVERT(DATETIME, CONVERT(CHAR(8), run_date, 112) + '' '' + STUFF(STUFF(RIGHT(''000000'' + CONVERT(VARCHAR(8), run_time), 6), 5, 0, '':''), 3, 0, '':''), 120) between '''+convert(nvarchar(20), @StartDT, 120)+''' and '''+convert(nvarchar(20), @EndDT, 120)+'''
    and        step_id = 0 -- step_id = 0 is the entire job, step_id > 0 is actual step number
    and        ((run_duration/10000)%100 * 3600) + ((run_duration/100)%100 * 60) + run_duration%100 > '+cast(@MinRuntimeInSec as nvarchar(50))+' -- Ignore trivial runtimes
    --and job.name in(''Ordina_Backup_Full'',''Ordina_Backup_Diff'',''Ordina_Backup_Log'')
    ORDER BY SDT
    '

if @Show = 'Job/Step' 
    set @sql = '
    SELECT h.step_name as JobName
            ,j.name as CatName
            ,CONVERT(DATETIME, CONVERT(CHAR(8), run_date, 112) + '' '' + STUFF(STUFF(RIGHT(''000000'' + CONVERT(VARCHAR(8), run_time), 6), 5, 0, '':''), 3, 0, '':''), 120) as SDT
            ,dateadd(    s,
                        ((run_duration/10000)%100 * 3600) + ((run_duration/100)%100 * 60) + run_duration%100 ,
                        CONVERT(DATETIME, CONVERT(CHAR(8), run_date, 112) + '' '' + STUFF(STUFF(RIGHT(''000000'' + CONVERT(VARCHAR(8), run_time), 6), 5, 0, '':''), 3, 0, '':''), 120) 
                    ) as EDT
    into    ##JobRuntime
    FROM msdb.dbo.sysjobhistory h inner join msdb.dbo.sysjobs j
    ON j.job_id = h.job_id
    where    CONVERT(DATETIME, CONVERT(CHAR(8), run_date, 112) + '' '' + STUFF(STUFF(RIGHT(''000000'' + CONVERT(VARCHAR(8), run_time), 6), 5, 0, '':''), 3, 0, '':''), 120) between '''+convert(nvarchar(52), @StartDT, 120)+''' and '''+convert(nvarchar(20), @EndDT, 120)+'''
    and        ((run_duration/10000)%100 * 3600) + ((run_duration/100)%100 * 60) + run_duration%100 > '+cast(@MinRuntimeInSec as nvarchar(50))+' -- Ignore trivial runtimes
    and        h.step_id > 0 
    ORDER BY j.name, h.run_date, h.run_time, step_id
    '

exec (@sql)

if not exists (select 1 from ##JobRuntime) 
    goto NothingToDo

update    ##JobRuntime
set        JobName = replace(JobName, '''', '`')
        ,CatName = replace(CatName, '''', '`')

--***************************************************************************************
-- Format for google graph - Header 
-- (Split into multiple inserts because the default text result setting is 256 chars)
--***************************************************************************************
insert into ##GoogleGraph (HTML) 
select '<html>
<head>
    <!--<META HTTP-EQUIV="refresh" CONTENT="1">--> '
insert into ##GoogleGraph (HTML) 
select '
  <script type="text/javascript"></script>
  <script src="https://www.gstatic.com/charts/loader.js"></script>
  <script>google.charts.load(''current'', {packages: [''timeline'']})</script>
	</head>	
	'
	
-- start of the body
insert into ##GoogleGraph (HTML) 
select '
	<body>
		<font face="Helvetica" size="3" >'
    +'Job timeline on: '+@@servername + ' (Node: ' +cast(SERVERPROPERTY('ComputerNamePhysicalNetBIOS') as varchar(128)) +')' 
    +' from '+convert(varchar(20), @StartDT, 120)
    +' until '+convert(varchar(20), @EndDT, 120)
    +case when @MinRuntimeInSec = 0 then '' else ' (hiding jobs with runtime < '+cast(@MinRuntimeInSec as varchar(10))+' seconds)' end 
	+'</font>'
	
	
insert into ##GoogleGraph (HTML) 
select '
  <script language = "JavaScript">'
insert into ##GoogleGraph (HTML) 
select '	function drawChart() {'

--***************************************************************************************
-- One timeline over all
--***************************************************************************************
if @ShowDays = 'OneTimeline' 
begin

  -- Calculate new width
  set @WidthInPixels = @WidthInPixels * datediff(day, @StartDT, @EndDT)

  insert into ##GoogleGraph (HTML) 
  select '
     var container = document.getElementById(''JobTimeline'');
     var chart = new google.visualization.Timeline(container);
     var dataTable = new google.visualization.DataTable();'

  insert into ##GoogleGraph (HTML) 
  select '        dataTable.addColumn({ type: ''string'', id: ''Position'' });
     dataTable.addColumn({ type: ''string'', id: ''Name'' });'
  insert into ##GoogleGraph (HTML) 
  select '        dataTable.addColumn({ type: ''date'', id: ''Start'' });
     dataTable.addColumn({ type: ''date'', id: ''End'' });
     dataTable.addRows([
	 '
  --***************************************************************************************
  -- Format for google graph - Data
  --***************************************************************************************
  insert into ##GoogleGraph (HTML) 
  SELECT '        [ ' 
         +'''' + CatName + ''', '
         +'''' + replace(JobName,'''','') + ''', '
         +'new Date('
         +  cast(DATEPART(year , SDT) as varchar(4))
         +', '+cast(DATEPART(month, SDT) -1 as varchar(4)) --Java months count from 0
         +', '+cast(DATEPART(day,  SDT) as varchar(4))
         +', '+cast(DATEPART(hour, SDT) as varchar(4))
         +', '+cast(DATEPART(minute, SDT) as varchar(4))
         +', '+cast(DATEPART(second, SDT) as varchar(4)) 
         +'), '

         +'new Date('
         +  cast(DATEPART(year, EDT) as varchar(4))
         +', '+cast(DATEPART(month, EDT) -1 as varchar(4)) --Java months count from 0
         +', '+cast(DATEPART(day,  EDT) as varchar(4))
         +', '+cast(DATEPART(hour, EDT) as varchar(4))
         +', '+cast(DATEPART(minute, EDT) as varchar(4))
         +', '+cast(DATEPART(second, EDT) as varchar(4)) 
         + ') ],' --+ char(10)
  from    ##JobRuntime 
  where    SDT between @StartDT and @EndDT
  order by    CatName, SDT, JobName

  select    @CategoryCount = count(distinct CatName)
  from    ##JobRuntime 
  where    SDT between @StartDT and @EndDT

  select    @CategoryJobCount = avg(cJobname * 1.0) 
  from    (
         -- Count JobNames per CatName 
         select CatName, count(JobName) as cJobname
         from    (
                  -- Get Cat CatName and JobName
                  select    distinct CatName, JobName
                  from    ##JobRuntime 
                  where    SDT between @StartDT and @EndDT
                  ) as i
         group by CatName
         ) as o

    
  set @HeightInPixels = @RowHeightInPixels * (((@CategoryCount * 1.0) * @CategoryJobCount) + 2)

  insert into ##GoogleGraph (HTML) 
  select '        ]);

  var options = 
  {
     timeline:     { '

  if @Show = 'Category/Job' 
  insert into ##GoogleGraph (HTML) 
  select '                    groupByRowLabel: true,'

  if @Show = 'Job/Step' 
  insert into ##GoogleGraph (HTML) 
  select '                    groupByRowLabel: false,'

  insert into ##GoogleGraph (HTML) 
  select '                    colorByRowLabel: false,
                  singleColor: false,
                  rowLabelStyle: {fontName: ''Helvetica'', fontSize: 14 },
                  barLabelStyle: {fontName: ''Helvetica'', fontSize: 14 },'                                        

  insert into ##GoogleGraph (HTML) 
  select '
                  },
		"height": '+cast(isnull(@HeightInPixels, 250) as varchar(10))+',
		"width": '+cast(isnull(@WidthInPixels, 1800) as varchar(10))+'
  };
'

  insert into ##GoogleDiv (HTML) 
  SELECT '  <div id="JobTimeline"></div>'

  insert into ##GoogleDraw (HTML) 
  SELECT '  chart.draw(dataTable, options);'

end

--***************************************************************************************
-- One timeline per day
--***************************************************************************************
if @ShowDays = 'MultiDayTimeline' 
begin

  -- Loop all dates
  DECLARE cDates CURSOR READ_ONLY FOR

  select StartDT, EndDT
  from     #Dates
  where [StartDT] >= (select min(SDT) from [##JobRuntime]) --Just in case there is no job run in the date range
  and     [EndDT] <= (select max(EDT) from [##JobRuntime]) --Just in case there is no job run in the date range
  order by StartDT

  OPEN cDates

  FETCH NEXT FROM cDates INTO @SDT, @EDT
  WHILE (@@fetch_status = 0)
  BEGIN

      insert into ##GoogleGraph (HTML) 
      select '
          //************************'+convert(varchar(10), @SDT, 120)+'******************************
          var container'+cast(@Teller as varchar(10))+' = document.getElementById(''JobTimeline'+cast(@Teller as varchar(10))+''');'
      insert into ##GoogleGraph (HTML) 
      select '          var chart'+cast(@Teller as varchar(10))+' = new google.visualization.Timeline(container'+cast(@Teller as varchar(10))+');
          var dataTable'+cast(@Teller as varchar(10))+' = new google.visualization.DataTable();'
      insert into ##GoogleGraph (HTML) 
      select '          dataTable'+cast(@Teller as varchar(10))+'.addColumn({ type: ''string'', id: ''Position'' });
          dataTable'+cast(@Teller as varchar(10))+'.addColumn({ type: ''string'', id: ''Name'' });
          dataTable'+cast(@Teller as varchar(10))+'.addColumn({ type: ''date'', id: ''Start'' });'
      insert into ##GoogleGraph (HTML) 
      select '          dataTable'+cast(@Teller as varchar(10))+'.addColumn({ type: ''date'', id: ''End'' });
          dataTable'+cast(@Teller as varchar(10))+'.addRows([
      '
     if @AddDateRangeBar = 1 -- Add the daterange bar for reference
     begin
        --***************************************************************************************
         -- Insert placeholders for begin and end of day
         --***************************************************************************************

         ---- De max value of a day is either the MaxDT of the longest job if it sticks out over the day boundry
         --set @MaxEDT = (    SELECT max(EDT)
                  --  from     ##JobRuntime 
                  --  where SDT between @SDT and @EDT
                  --  )

         ---- Or if the the longest job is within the day boundry than it the end of the day
         --if @MaxEDT < @EDT 
             set @MaxEDT = @EDT

         insert into ##GoogleGraph (HTML) 
         SELECT '        [ ' 
                 +'''' + 'DateRange' + ''', '
                 +'''' + ' ' + ''', '
                 +'new Date('
                 +  cast(DATEPART(year , @SDT) as varchar(4))
                 +', '+cast(DATEPART(month, @SDT) -1 as varchar(4)) --Java months count from 0
                 +', '+cast(DATEPART(day,  @SDT) as varchar(4))
                 +', '+cast(DATEPART(hour, @SDT) as varchar(4))
                 +', '+cast(DATEPART(minute, @SDT) as varchar(4))
                 +', '+cast(DATEPART(second, @SDT) as varchar(4)) 
                 +'), '

                 +'new Date('
                 +  cast(DATEPART(year, @MaxEDT) as varchar(4))
                 +', '+cast(DATEPART(month, @MaxEDT) -1 as varchar(4)) --Java months count from 0
                 +', '+cast(DATEPART(day,  @MaxEDT) as varchar(4))
                 +', '+cast(DATEPART(hour, @MaxEDT) as varchar(4))
                 +', '+cast(DATEPART(minute, @MaxEDT) as varchar(4))
                 +', '+cast(DATEPART(second, @MaxEDT) as varchar(4)) 
                 + ') ],' --+ char(10)
     end

      --***************************************************************************************
      -- Format for google graph - Data
      --***************************************************************************************
      insert into ##GoogleGraph (HTML) 
      SELECT '        [ ' 
              +'''' + CatName + ''', '
              +'''' + replace(JobName,'''','') + ''', '
              +'new Date('
              +  cast(DATEPART(year , SDT) as varchar(4))
              +', '+cast(DATEPART(month, SDT) -1 as varchar(4)) --Java months count from 0
              +', '+cast(DATEPART(day,  SDT) as varchar(4))
              +', '+cast(DATEPART(hour, SDT) as varchar(4))
              +', '+cast(DATEPART(minute, SDT) as varchar(4))
              +', '+cast(DATEPART(second, SDT) as varchar(4)) 
              +'), '

              +'new Date('
              +  cast(DATEPART(year, EDT) as varchar(4))
              +', '+cast(DATEPART(month, EDT) -1 as varchar(4)) --Java months count from 0
              +', '+cast(DATEPART(day,  EDT) as varchar(4))
              +', '+cast(DATEPART(hour, EDT) as varchar(4))
              +', '+cast(DATEPART(minute, EDT) as varchar(4))
              +', '+cast(DATEPART(second, EDT) as varchar(4)) 
              + ') ],' --+ char(10)
      from    ##JobRuntime 
      where    SDT between @SDT and @EDT
      order by    CatName, SDT, JobName

      select    @CategoryCount = count(distinct CatName)
      from    ##JobRuntime 
      where    SDT between @SDT and @EDT

      select    @CategoryJobCount = avg(cJobname * 1.0) 
      from    (
              -- Count JobNames per CatName 
              select CatName, count(JobName) as cJobname
              from    (
                      -- Get Cat CatName and JobName
                      select    distinct CatName, JobName
                      from    ##JobRuntime 
                      where    SDT between @SDT and @EDT
                      ) as i
              group by CatName
              ) as o

    
      set @HeightInPixels = @RowHeightInPixels * (((@CategoryCount * 1.0) * @CategoryJobCount) + 2)

      insert into ##GoogleGraph (HTML) 
      select '        ]);

      var options'+cast(@Teller as varchar(10))+' = 
      {
          timeline:     { '

      if @Show = 'Category/Job' 
      insert into ##GoogleGraph (HTML) 
      select '                    groupByRowLabel: true,'

      if @Show = 'Job/Step' 
      insert into ##GoogleGraph (HTML) 
      select '                    groupByRowLabel: false,'

      insert into ##GoogleGraph (HTML) 
      select '                    colorByRowLabel: false,
                      singleColor: false,
                      rowLabelStyle: {fontName: ''Helvetica'', fontSize: 14 },
                      barLabelStyle: {fontName: ''Helvetica'', fontSize: 14 },'                                        

      insert into ##GoogleGraph (HTML) 
      select '
                      },
		"height": '+cast(isnull(@HeightInPixels, 250) as varchar(10))+',
		"width": '+cast(isnull(@WidthInPixels, 1800) as varchar(10))+'
      };
  '

      insert into ##GoogleDiv (HTML) 
      SELECT '	  <hr>from '+datename(dw, @SDT)+' '+convert(varchar(20), @SDT, 120) +' until '+datename(dw, @EDT)+' '+convert(varchar(20), @EDT, 120)+'<hr> <div id="JobTimeline'+cast(@Teller as varchar(10))+'"></div>'

      insert into ##GoogleDraw (HTML) 
      SELECT '	  chart'+cast(@Teller as varchar(10))+'.draw(dataTable'+cast(@Teller as varchar(10))+', options'+cast(@Teller as varchar(10))+');'

      set @Teller = @Teller + 1

      FETCH NEXT FROM cDates INTO @SDT, @EDT
  END

  CLOSE cDates
  DEALLOCATE cDates
end

--***************************************************************************************
-- Format for google graph - Footer
--***************************************************************************************
-- The DRAWs
insert into ##GoogleGraph (HTML) 
SELECT HTML FROM ##GoogleDraw

-- And last but not least the ending tags
insert into ##GoogleGraph (HTML) 
select '	}
	google.charts.setOnLoadCallback(drawChart);
    </script>'

-- The DIVs
insert into ##GoogleGraph (HTML) 
SELECT HTML FROM ##GoogleDiv

-- And last but not least the ending tags
insert into ##GoogleGraph (HTML) 
select '    </body>
</html>'

--***************************************************************************************
-- Output HTML page - copy output & paste to a .HTML file and open with google chrome
--***************************************************************************************
if @ReturnRecocordset = 1 
    select HTML from ##GoogleGraph order by ID

--***************************************************************************************
-- Send Email - 
--***************************************************************************************
if @SendMail = 1

    execute msdb.dbo.sp_send_dbmail    
         @profile_name = @Emailprofilename
        ,@recipients = @EmailRecipients
        ,@subject = 'JobTimeline'
        ,@body = 'See attachment for JobTimeline, open with Google Chrome!' 
        ,@body_format = 'HTML' -- or TEXT
        ,@importance = 'Normal' --Low Normal High
        ,@sensitivity = 'Normal' --Normal Personal Private Confidential
        ,@execute_query_database = 'master'
        ,@query_result_header = 0
        ,@query = 'set nocount on; SELECT HTML FROM ##GoogleGraph order by ID'
        ,@query_result_no_padding = 1 -- prevent SQL adding padding spaces in the result
        --,@query_no_truncate= 1   -- mutually exclusive with @query_result_no_padding 
        ,@attach_query_result_as_file = 1
        ,@query_attachment_filename= 'JobTimeline.HTML'

goto Cleanup

--***************************************************************************************
-- Just in case....
--***************************************************************************************
NothingToDo:

print 'No job runtime info found....'

--***************************************************************************************
-- Cleanup
--***************************************************************************************
Cleanup:
IF OBJECT_ID('tempdb..##JobRuntime') IS NOT NULL DROP TABLE ##JobRuntime;
IF OBJECT_ID('tempdb..##GoogleGraph') IS NOT NULL DROP TABLE ##GoogleGraph;
IF OBJECT_ID('tempdb..##GoogleDiv') IS NOT NULL DROP TABLE ##GoogleDiv;
IF OBJECT_ID('tempdb..##GoogleDraw') IS NOT NULL DROP TABLE ##GoogleDraw;
IF OBJECT_ID('tempdb..#Dates') IS NOT NULL DROP TABLE #Dates;