diff --git a/internal/querylog/csv.go b/internal/querylog/csv.go index 7a4016f4..dd7ceec8 100644 --- a/internal/querylog/csv.go +++ b/internal/querylog/csv.go @@ -10,7 +10,7 @@ import ( ) // csvHeaderRow is a slice of strings with row names for CSV header. This -// const should correspond with [logEntry.toCSV] func. +// slice should correspond with [logEntry.toCSV] func. var csvHeaderRow = []string{ "ans_dnssec", "ans_rcode", @@ -46,7 +46,7 @@ func (e *logEntry) toCSV() (out []string) { aData := ansData(e) return []string{ - aData.dnsSec, + strconv.FormatBool(e.AuthenticatedData), aData.rCode, aData.typ, aData.value, @@ -69,10 +69,9 @@ func (e *logEntry) toCSV() (out []string) { // csvAnswer is a helper struct for csv row answer fields. type csvAnswer struct { - dnsSec string - rCode string - typ string - value string + rCode string + typ string + value string } // ansData returns a map with message answer data. @@ -90,10 +89,6 @@ func ansData(entry *logEntry) (out csvAnswer) { out.rCode = dns.RcodeToString[msg.Rcode] - // Old query logs may still keep AD flag value in the message. Try to get - // it from there as well. - out.dnsSec = strconv.FormatBool(entry.AuthenticatedData || msg.AuthenticatedData) - if len(msg.Answer) == 0 { return out } diff --git a/internal/querylog/http.go b/internal/querylog/http.go index 97e7d4cd..e3d9a19a 100644 --- a/internal/querylog/http.go +++ b/internal/querylog/http.go @@ -99,6 +99,11 @@ func (l *queryLog) handleQueryLog(w http.ResponseWriter, r *http.Request) { _ = aghhttp.WriteJSONResponse(w, r, resp) } +// exportChunkSize is a size of one search-flush iteration for query log export. +// +// TODO(a.meshkov): Consider making configurable. +const exportChunkSize = 500 + // handleQueryLogExport is the handler for the GET /control/querylog/export // HTTP API. func (l *queryLog) handleQueryLogExport(w http.ResponseWriter, r *http.Request) { @@ -110,8 +115,7 @@ func (l *queryLog) handleQueryLogExport(w http.ResponseWriter, r *http.Request) } params := &searchParams{ - // TODO(a.meshkov): Consider making configurable. - limit: 500, + limit: exportChunkSize, searchCriteria: searchCriteria, } @@ -119,12 +123,6 @@ func (l *queryLog) handleQueryLogExport(w http.ResponseWriter, r *http.Request) w.Header().Set(httphdr.ContentDisposition, "attachment;filename=data.csv") csvWriter := csv.NewWriter(w) - defer func() { - if err = csvWriter.Error(); err != nil { - // TODO(a.garipov): Set Trailer X-Error header. - log.Error("%s %s %s: %s", r.Method, r.Host, r.URL, "writing csv") - } - }() // Write header. if err = csvWriter.Write(csvHeaderRow); err != nil { @@ -160,6 +158,11 @@ func (l *queryLog) handleQueryLogExport(w http.ResponseWriter, r *http.Request) csvWriter.Flush() } + + if err = csvWriter.Error(); err != nil { + // TODO(a.garipov): Set Trailer X-Error header. + log.Error("%s %s %s: %s", r.Method, r.Host, r.URL, "writing csv") + } } // handleQueryLogClear is the handler for the POST /control/querylog/clear HTTP diff --git a/openapi/CHANGELOG.md b/openapi/CHANGELOG.md index b85fa7d9..863c8f57 100644 --- a/openapi/CHANGELOG.md +++ b/openapi/CHANGELOG.md @@ -11,7 +11,7 @@ * The new `GET /control/querylog/export` HTTP API allows an export of query log items in the CSV file. It returns a CSV object with the following format: -```text +```csv ans_dnssec,ans_rcode,ans_type,ans_value,cached,client_ip,client_id,ecs,elapsed,filter_id,filter_rule,proto,qclass,qname,qtype,reason,time,upstream false,NOERROR,A,192.168.1.1,false,127.0.0.1,,,0.097409,,,,IN,example.com,A,Rewrite,2023-01-30T12:21:13.947563+07:00, false,NOERROR,A,45.33.2.79,false,127.0.0.1,,,482.967871,,,,IN,test.com,A,NotFilteredNotFound,2022-12-13T12:18:04.964403+07:00,https://dns10.quad9.net:443/dns-query