def _renderView(self, pdfRenderer, view, lastView=False): """ render an individual panel """ types = view.getRenderTypes() pdfRenderer.conditionalPageBreak(types) # always render header first self._renderViewHeader(pdfRenderer, view) if view.hasError(): pdfRenderer.renderText(view.getError()) return if view.requiresSearchJobObj(): if view.hasSearchError(): pdfRenderer.renderText(view.getSearchError()) return while not view.isSearchComplete() and not view.isRealtime(): time.sleep(self.POLLING_WAIT_TIME) self._keepAllSearchesAlive() self._checkForTimeout() if 'trellis.enabled' in view.getOptions() and normalizeBoolean( view.getOptions()['trellis.enabled']): pdfRenderer.renderText( "PDF export is not available for visualizations using trellis layout." ) else: try: for type in types: if type == 'chart': self._renderChart(pdfRenderer, view) elif type == 'map': self._renderMap(pdfRenderer, view) elif type == 'table': self._renderTable(pdfRenderer, view) elif type == 'event': self._renderEvents(pdfRenderer, view) elif type == 'single': self._renderSingle(pdfRenderer, view) elif type == 'list': self._renderList(pdfRenderer, view) elif type == 'html': self._renderHtml(pdfRenderer, view) elif type == 'viz': pdfRenderer.renderText( "PDF export does not support custom visualizations." ) else: pdfRenderer.renderText( "No render option for type '%s'" % type) logger.warning( "PDFGenHandler::_renderView> No render option for type = '%s'" % type) except Exception as e: content = str(e) pu.logErrorAndTrace(e) pdfRenderer.renderText(content) if not lastView: pdfRenderer.spaceBetween()
def _render(self): try: self._inactiveViews = self._views[:] for _ in range(3): self._startNextSearch() except Exception, e: errorMsg = \ 'Exception raised while trying to prepare "%s" for rendering to PDF. %s' \ % (self._title, e) pu.logErrorAndTrace(errorMsg) self._outputError([errorMsg]) return False
def _handleRequest(self): logger.debug("pdfgen/render request: " + str(self.request)) if not self._initialize(): return if self.method == 'GET' and not self._enableInsecurePdfgen: errorMsg = "pdfgen GET is deprecated. Please use POST instead." pu.logErrorAndTrace(errorMsg) self._outputError([errorMsg]) return if not self._render(): return self._respond()
def _initialize(self): try: self._initParameters() if self._viewType == self.VIEW_TYPE_DASHBOARD: # handle Xml vs. entity name logger.debug("dashboardName=%s dashboardXml=%s" % (self._dashboardName, self._dashboardXml)) if self._dashboardXml != None: (self._title, self._description, self._views) = pv.getDashboardTitleAndPanelsFromXml( dashboardXml=self._dashboardXml, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) elif self._dashboardName != None: (self._title, self._description, self._views) = pv.getDashboardTitleAndPanels( dashboard_name=self._dashboardName, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) elif self._viewType == self.VIEW_TYPE_REPORT: self._views.append(pv.Report(savedSearchName=self._reportName, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey)) self._title = self._reportName elif self._viewType == self.VIEW_TYPE_SEARCH: self._title = self._reportName self._views.append(pv.SearchReport(search=self._searchStr, et=self._et, lt=self._lt, title=self._title, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey)) self._handlePresetSearchIDs() # instantiate the pdfRenderer object with a file-like object self._pdfBuffer = cStringIO.StringIO() self._pdfRenderer = pdfrenderer.PDFRenderer(namespace=self._namespace, title=self._title, description=self._description, outputFile=self._pdfBuffer, paperSize=self._paperSize, timestamp=self._timestampStr, includeSplunkLogo=self._includeSplunkLogo, cidFontList=self._cidFontList, pdfSettings=self._pdfSettings, requestSettings=self._requestSettings) return True except ArgError as e: self.response.setStatus(400) self.response.write(e.message) except Exception as e: errorMsg = "Bailing out of Integrated PDF Generation. Exception raised while preparing to render \"%s\" to PDF. %s" % (self._title, e) pu.logErrorAndTrace(errorMsg) self._outputError([errorMsg]) return False
def _respond(self): # save and write out the file try: self.response.write(self._pdfBuffer.getvalue().decode('ISO 8859-1')) self.response.setHeader('content-type', 'application/pdf') # override normal cache-control header to fix problem on ie6-ie8 (see SPL-50739) self.response.setHeader('cache-control', 'max-age=0, must-revalidate') name = self._generateFileName() logger.info('Generated pdf, filename = %s' % name) disposition = 'inline' if self.ARG_DISPLAY_INLINE in self.args else 'attachment' self.response.setHeader('content-disposition', disposition + '; filename="' + name + '"') self.response.setStatus(200) self._pdfBuffer.close() except Exception as e: errorMsg = "Exception raised while trying to respond. Bailing out of Integrated PDF Generation. Rendering \"%s\" to PDF. %s" % (self._title, e) pu.logErrorAndTrace(errorMsg) self._outputError([errorMsg]) return False return True
def _render(self): try: self._inactiveViews = self._views[:] for _ in range(3): self._startNextSearch() except Exception as e: errorMsg = "Exception raised while trying to prepare \"%s\" for rendering to PDF. %s" % (self._title, e) pu.logErrorAndTrace(errorMsg) self._outputError([errorMsg]) return False # iterate over views and render each to the pdf viewPrepErrors = [] for i, view in enumerate(self._views): try: self._keepAllSearchesAlive() self._checkForTimeout() isLastView = (i == len(self._views) - 1) self._renderView(self._pdfRenderer, view, lastView = isLastView) self._startNextSearch() except TimeoutError: errorMsg = "Timeout while trying to prepare \"%s\" for rendering to PDF." % self._title self._outputTimeoutError(errorMsg) return except Exception as e: errorMsg = "Exception raised while trying to prepare \"%s\" for rendering to PDF. %s" % (self._title, e) pu.logErrorAndTrace(errorMsg) viewPrepErrors.append(errorMsg) if len(self._views) == 0: # fix SPL-67268, render a empty dashboard if there's 0 views self._pdfRenderer.renderText("") # if we weren't able to render any views successfully, output an error as response to endpoint if len(viewPrepErrors) == len(self._views) and len(self._views) > 0: self._outputError(viewPrepErrors) logger.error("No views prepared without exceptions. Bailing out of Integrated PDF Generation.") return False try: self._pdfRenderer.save() except Exception as e: errorMsg = [] errorMsg.append("Exception raised while trying to render \"%s\" to PDF." % (self._title)) # SPL-80872 - [PDF] Cannot render PDF report of A5 size if the table is too big if "too large on page" in e.message: errorMsg.append("Please try using a larger paper size than %s." % (self._paperSize)) errorMsg.append("%s" % (e)) pu.logErrorAndTrace(errorMsg) self._outputError(errorMsg) return False return True
class PDFGenHandler(splunk.rest.BaseRestHandler): _args = {} _deletePdfFileAfterSettingResponse = True _timeoutTime = None _views = [] _inputSids = {} _title = 'Untitled' _description = '' _dashboardName = None _dashboardXml = None _reportName = None _viewType = None _paperSize = DEFAULT_PAPER_SIZE _namespace = None _owner = None _timeoutDuration = DEFAULT_TIMEOUT _maxRowsPerTable = DEFAULT_MAX_ROWS_PER_TABLE _includeSplunkLogo = DEFAULT_INCLUDE_SPLUNK_LOGO _cidFontList = None _now = None _timestampStr = '' _searchStr = None _et = '' _lt = '' _inactiveViews = None _fileNamePattern = None _touchSearchJobsLastTime = None _pdfBuffer = None _pdfRenderer = None VIEW_TYPE_DASHBOARD = 'dashboard' VIEW_TYPE_REPORT = 'report' VIEW_TYPE_SEARCH = 'search' ARG_INPUT_DASHBOARD = 'input-dashboard' ARG_INPUT_DASHBOARD_XML = 'input-dashboard-xml' ARG_INPUT_REPORT = 'input-report' ARG_INPUT_SEARCH = 'input-search' ARG_INPUT_LOCALE = 'locale' ARG_INPUT_ET = 'et' ARG_INPUT_LT = 'lt' ARG_INPUT_PAPERSIZE = 'paper-size' ARG_INPUT_SID = 'sid' ARG_INPUT_NAMESPACE = 'namespace' ARG_INPUT_OWNER = 'owner' ARG_INPUT_TIMEOUT = 'timeout' ARG_INPUT_MAX_ROWS_PER_TABLE = 'max-rows-per-table' ARG_INPUT_INCLUDE_SPLUNK_LOGO = 'include-splunk-logo' ARG_INPUT_REPORT_FILE_NAME = 'report-file-name' ARG_INPUT_NOW = 'now' ARG_CACHE_BUSTER = '_' ARG_CSRF_FORM_KEY = 'splunk_form_key' _validArgs = [ ARG_INPUT_DASHBOARD, ARG_INPUT_DASHBOARD_XML, ARG_INPUT_REPORT, ARG_INPUT_SEARCH, ARG_INPUT_ET, ARG_INPUT_LT, ARG_INPUT_PAPERSIZE, ARG_INPUT_SID, ARG_INPUT_NAMESPACE, ARG_INPUT_OWNER, ARG_INPUT_TIMEOUT, ARG_INPUT_MAX_ROWS_PER_TABLE, ARG_INPUT_INCLUDE_SPLUNK_LOGO, ARG_INPUT_NOW, ARG_CACHE_BUSTER, ARG_CSRF_FORM_KEY, ARG_INPUT_LOCALE, ] SID_VALIDATOR_STR = 'sid_([0-9]+)' sidRE = re.compile(SID_VALIDATOR_STR) POLLING_WAIT_TIME = 0.5 TOUCH_SEARCH_INTERVAL = 10 ALERT_ACTIONS_ENTITY = '/configs/conf-alert_actions' LIMITS_ENTITY = '/configs/conf-limits' WEB_ENTITY = '/configs/conf-web' def handle_GET(self): self._handleRequest() def handle_POST(self): self._handleRequest() def _handleRequest(self): logger.debug('pdfgen/render request: ' + str(self.request)) if not self._initialize(): return if not self._render(): return self._respond() def _initialize(self): try: self._initParameters() if self._viewType == self.VIEW_TYPE_DASHBOARD: # handle Xml vs. entity name logger.debug('dashboardName=%s dashboardXml=%s' % (self._dashboardName, self._dashboardXml)) if self._dashboardXml != None: (self._title, self._description, self._views) = \ pv.getDashboardTitleAndPanelsFromXml(dashboardXml=self._dashboardXml, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) elif self._dashboardName != None: (self._title, self._description, self._views) = \ pv.getDashboardTitleAndPanels(dashboard_name=self._dashboardName, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) elif self._viewType == self.VIEW_TYPE_REPORT: self._views.append( pv.Report(savedSearchName=self._reportName, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey)) self._title = self._reportName elif self._viewType == self.VIEW_TYPE_SEARCH: self._title = self._reportName self._views.append( pv.SearchReport( search=self._searchStr, et=self._et, lt=self._lt, title=self._title, namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey, )) self._handlePresetSearchIDs() # instantiate the pdfRenderer object with a file-like object self._pdfBuffer = cStringIO.StringIO() self._pdfRenderer = pdfrenderer.PDFRenderer( namespace=self._namespace, title=self._title, description=self._description, outputFile=self._pdfBuffer, paperSize=self._paperSize, timestamp=self._timestampStr, includeSplunkLogo=self._includeSplunkLogo, cidFontList=self._cidFontList, pdfSettings=self._pdfSettings, ) return True except ArgError, e: self.response.setStatus(400) self.response.write(e.message) except Exception, e: errorMsg = \ 'Bailing out of Integrated PDF Generation. Exception raised while preparing to render "%s" to PDF. %s' \ % (self._title, e) pu.logErrorAndTrace(errorMsg) self._outputError([errorMsg])
isLastView = i == len(self._views) - 1 self._renderView(self._pdfRenderer, view, lastView=isLastView) self._startNextSearch() except TimeoutError: errorMsg = \ 'Timeout while trying to prepare "%s" for rendering to PDF.' \ % self._title self._outputTimeoutError(errorMsg) return except Exception, e: errorMsg = \ 'Exception raised while trying to prepare "%s" for rendering to PDF. %s' \ % (self._title, e) pu.logErrorAndTrace(errorMsg) viewPrepErrors.append(errorMsg) if len(self._views) == 0: # fix SPL-67268, render a empty dashboard if there's 0 views self._pdfRenderer.renderText('') # if we weren't able to render any views successfully, output an error as response to endpoint if len(viewPrepErrors) == len(self._views) and len(self._views) \ > 0: self._outputError(viewPrepErrors) logger.error( 'No views prepared without exceptions. Bailing out of Integrated PDF Generation.' )