code: func EventString(ev *auditinternal.Event) string {
  	username := "<none>"
  	groups := "<none>"
  	if len(ev.User.Username) > 0 {
  		username = ev.User.Username
  		if len(ev.User.Groups) > 0 {
  			groups = auditStringSlice(ev.User.Groups)
  		}
  	}
  	asuser := "<self>"
  	asgroups := "<lookup>"
  	if ev.ImpersonatedUser != nil {
  		asuser = ev.ImpersonatedUser.Username
  		if ev.ImpersonatedUser.Groups != nil {
  			asgroups = auditStringSlice(ev.ImpersonatedUser.Groups)
  		}
  	}
  
  	namespace := "<none>"
  	if ev.ObjectRef != nil && len(ev.ObjectRef.Namespace) != 0 {
  		namespace = ev.ObjectRef.Namespace
  	}
  
  	response := "<deferred>"
  	if ev.ResponseStatus != nil {
  		response = strconv.Itoa(int(ev.ResponseStatus.Code))
  	}
  
  	ip := "<unknown>"
  	if len(ev.SourceIPs) > 0 {
  		ip = ev.SourceIPs[0]
  	}
  
  	return fmt.Sprintf("%s AUDIT: id=%q stage=%q ip=%q method=%q user=%q groups=%q as=%q asgroups=%q namespace=%q uri=%q response=\"%s\"",
  		ev.RequestReceivedTimestamp.Format(time.RFC3339Nano), ev.AuditID, ev.Stage, ip, ev.Verb, username, groups, asuser, asgroups, namespace, ev.RequestURI, response)
  }
docs: // EventString creates a 1-line text representation of an audit event, using a subset of the
  // information in the event struct.