Sorry. You're right. I wasn't clear about my goal. I want to be able to easily access the individual flags, so I can do things like graph UDP vs. TCP transport.
I did manage to make it work with translate, but your suggestion is probably cleaner. Thank you for the suggestion.
grok {
keep_empty_captures => true
match => {
"message" => "queries: info: client %{IP:clientip}#%{INT:port}: query: %{DATA:query} %{WORD:class} %{WORD:querytype} (?<recursive>[-+])((?<signed>S)?)((?<edns>E)?)((?<transport>T)?)((?<dnssec>D)?)((?<cd>C)?) \(%{IP:serverip}\)"
}
}
translate {
field => "recursive"
destination => "[dns_flags][recursive]"
remove_field => [ "recursive" ]
dictionary => [ "+", "Yes", "-", "No" ]
}
translate {
field => "signed"
destination => "[dns_flags][signed]"
remove_field => [ "signed" ]
fallback => "No"
dictionary => [ "S", "Yes" ]
}
translate {
field => "edns"
destination => "[dns_flags][edns]"
remove_field => [ "edns" ]
fallback => "No"
dictionary => [ "E", "Yes" ]
}
translate {
field => "transport"
destination => "[dns_flags][transport]"
remove_field => [ "transport" ]
fallback => "UDP"
dictionary => [ "T", "TCP" ]
}
translate {
field => "dnssec"
destination => "[dns_flags][dnssec]"
remove_field => [ "dnssec" ]
fallback => "No"
dictionary => [ "D", "Yes" ]
}
translate {
field => "cd"
destination => "[dns_flags][cd]"
remove_field => [ "cd" ]
fallback => "No"
dictionary => [ "C", "Yes" ]
}