Debug

QFQ Log

Setup in Configuration

  • qfqLog
    • Filename where to log QFQ debug and error messages.
    • File is relative to the <site path> or absolute (starting with ‘/’).
    • Content: error situations of QFQ and debug, if enabled.

All non SQL related information will be logged to QFQ log file.

SQL Log

Setup in Configuration

  • sqlLog
    • Filename where to log SQL queries and statistical data.
    • File is relative to the <site path> or absolute (starting with ‘/’).
    • Content: SQL queries and timestamp, formName/formId, fe_user, success, affected rows, newly created record id’s and accessed from IP.
    • The global setting can be overwritten by defining sqlLog inside of a QFQ tt-content record.
  • sqlLogMode: all|modify|error|none

    • all: logs every SQL statement.
    • modify: logs only statements who might potentially change data.
    • error: logs only queries which generate SQL errors.
    • none: no query logging at all.
    • The global setting can be overwritten by defining sqlLogMode inside of a QFQ tt-content record.
  • showDebugInfo = [yes|no|auto],[download]

    If active, displays additional information in the Frontend (FE). This is typically helpful during development.

    • yes:

      • Form:

        • For every internal link/button, show tooltips with decoded SIP on mouseover.
        • Shows an ‘Edit form’-button (wrench symbol) on a form. The link points to the T3 page with the FormEditor.
      • Report: Will be configured per tt-content record.

        debugShowBodyText = 1

    • no: No debug info.

    • auto: Depending if there is a Typo3 BE session, set internally:

      • showDebugInfo = yes (BE session exist)
      • showDebugInfo = no (no BE session)
    • download:

      • During a download (especially by using wkhtml), temporary files are not deleted automatically. Also the wkhtmltopdf, pdfunite, pdf2img command lines will be logged to QFQ Log. Use this only to debug problems on download.

MAIL Log

Setup in Configuration

  • mailLog
    • File which sendEmail logs sending mail.
    • File is relative to the <site path> or absolute (starting with ‘/’).

Mail Log page (Table MailLog)

For debugging purposes you may like to add a Mail Log page in the frontend. The following QFQ code could be used for that purpose (put it in a QFQ PageContent element)

Note: If you do not use/have the Ggroup table, then remove the “# Filters” block.

# Page parameters
1.sql = SELECT @grId := '{{grId:C0:digit}}' AS _grId
2.sql = SELECT @summary := IF('{{summary:CE:alnumx}}' = 'true', 'true', 'false') AS _s

# Filters
10 {
  sql = SELECT "'", gr.id, IF(gr.id = @grId, "' selected>", "'>"), gr.value, ' (Id: ', gr.id, ')'
           FROM Ggroup AS gr
           INNER JOIN MailLog AS ml ON ml.grId = gr.id
           GROUP BY gr.id
  head = <form onchange='this.submit();' class='form-inline'><input type='hidden' name='id' value='{{pageAlias:T0}}'>
           Filter By Group: <select name='grId' class='form-control'><option value=''></option>
  rbeg = <option value=
  rend = </option>
  tail = </select>
}

20 {
  sql = SELECT IF(@summary = 'true', ' checked', '')
  head = <div class='checkbox'><label><input type='checkbox' name='summary' value='true'
  tail = >Summary</label></div></form>
}

# Mail Log
50 {
  sql = SELECT id, '</td><td>', grId, '</td><td>', xId, '</td><td>'
               , REPLACE(receiver, ',', '<br>'), '</td><td>', REPLACE(sender, ',', '<br>'), '</td><td>'
               , DATE_FORMAT(modified, '%d.%m.%Y<br>%H:%i:%s'), '</td><td style="word-break:break-word;">'
               , CONCAT('<b>', subject, '</b><br>', IF(@summary = 'true', CONCAT(SUBSTR(body, 1
                        , LEAST(IF(INSTR(body, '\n') = 0, 50, INSTR(body, '\n')), IF(INSTR(body, '<br>') = 0, 50
                        , INSTR(body, '<br>')))-1), ' ...'), CONCAT('<br>', REPLACE(body, '\n', '<br>'))) )
          FROM MailLog
          WHERE (grId = @grId OR @grId = 0)
          ORDER BY modified DESC
          LIMIT 100
  head = <table class="table table-condensed table-hover"><tr>
             <th>Id</th><th>grId</th><th>xId</th><th>To</th><th>From</th><th>Date</th><th>E-Mail</th></tr>
  tail = </table>
  rbeg = <tr><td>
  rend = </td></tr>
}

Redirect all mail to (catch all)

Setup in Configuration

  • redirectAllMailTo=john@doe.com
    • During the development, it might be helpful to configure a ‘catch all’ email address, which QFQ uses as the final receiver instead of the original intended one.
    • The setting will:
      • Replace the ‘To’ with the configured one.
      • Clear ‘CC’ and ‘Bcc’
      • Write a note and the original configured receiver at the top of the email body.

Show log files realtime

Display QFQ log files in realtime.

The following QFQ code could be used for that purpose (put it in a QFQ PageContent element):

#
# {{logfile:SU}}
#

# Show buttons to select log file.
10 {
  sql = SELECT '{{logfile:SU:::sql.log}}' AS '_=logfile'
  head = <p>
  tail = </p>

  20.sql = SELECT CONCAT('p:{{pageAlias:T}}&logfile=sql.log|t:sql.log|b:', IF('{{logfile:R}}'='sql.log','primary','')) AS _page, ' '
                  , CONCAT('p:{{pageAlias:T}}&logfile=qfq.log|t:qfq.log|b:', IF('{{logfile:R}}'='qfq.log','primary','')) AS _page, ' '
                  , CONCAT('p:{{pageAlias:T}}&logfile=mail.log|t:mail.log|b:', IF('{{logfile:R}}'='mail.log','primary','')) AS _page
}

# Show selected log file.
100 {
  sql = SELECT 'file:fileadmin/protected/log/{{logfile:R}}' AS _monitor
  head = <pre id="monitor-1">Please wait</pre>
}

Form Submit Log page

For debugging purposes you may like to add a Form Submit Log page in the frontend. The following QFQ code could be used for that purpose (put it in a QFQ PageContent element):

# Filters
20.shead = <form onchange='this.submit()' class='form-inline'><input type='hidden' name='id' value='{{pageAlias:T0}}'>
20 {
  sql = SELECT "'", id, IF(id = '{{formId:SC0}}', "' selected>", "'>"), name
          FROM Form
          ORDER BY name
  head = <label for='formId'>Form:</label> <select name='formId' id='formId' class='form-control'><option value=0></option>
  tail = </select>
  rbeg = <option value=
  rend = </option>
}
30 {
  sql = SELECT feUser, IF(feUser = '{{feUser:SCE:alnumx}}', "' selected>", "'>"), feUser
          FROM FormSubmitLog
          GROUP BY feUser ORDER BY feUser
  head = <label for='feUser'>FE User:</label> <select name='feUser' id='feUser' class='form-control'><option value=''></option>
  tail = </select>
  rbeg = <option value='
  rend = </option>
}
30.stail = </form>

# Show Log
50 {
  sql = SELECT l.id
                 , CONCAT('<b>Form</b>: ', f.name
                 , '<br><b>Record Id</b>: ', l.recordId
                 , '<br><b>Fe User</b>: ', l.feUser
                 , '<br><b>Date</b>: ', l.created
                 , '<br><b>Page Id</b>: ', l.pageId
                 , '<br><b>Session Id</b>: ', l.sessionId
                 , '<br><b>IP Address</b>: ', l.clientIp
                 , '<br><b>User Agent</b>: ', l.userAgent
                 , '<br><b>SIP Data</b>: <div style="margin-left:20px;">'
                 , "<script>var data = JSON.parse('", l.sipData, "'); for (var key in data) {
                            document.write('<b>' + key + '</b>: ' + data[key] + '<br>'); }</script>", '</div>')
                 , CONCAT("<script>var data = JSON.parse('", l.formData, "'); for (var key in data) {
                            document.write('<b>' + key + '</b>: ' + data[key] + '<br>'); }</script>")
            FROM FormSubmitLog AS l
            LEFT JOIN Form AS f
              ON f.id = l.formId
            WHERE (l.formId = '{{formId:SC0}}' OR '{{formId:SC0}}' = 0)
              AND (l.feUser = '{{feUser:SCE:alnumx}}' OR '{{feUser:SCE:alnumx}}' = '')
            ORDER BY l.created DESC
            LIMIT 100
  head = <table class="table table-hover">
         <tr><th>Id</th><th style="min-width:250px;">Environment</th><th>Submitted Data</th>
  tail = </table>
  rbeg = <tr>
  renr = </tr>
  fbeg = <td>
  fend = </td>
}