Skip to content

Commit

Permalink
feat(journal): add truncate-all-fields flag
Browse files Browse the repository at this point in the history
This feature implements the new flag 'truncate-all-fields'
which allows users to truncate worker data content
for all fields to the character count provided.

This is useful when a lot of fields are present
that need to be truncated in a simple flag.

Signed-off-by: Jason Jerome <jajerome@redhat.com>
  • Loading branch information
DuckBoss committed Oct 6, 2023
1 parent bf71712 commit 2e23130
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 59 deletions.
1 change: 1 addition & 0 deletions cmd/yggctl/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func messageJournalAction(ctx *cli.Context) error {
ctx.String("until"),
ctx.Bool("persistent"),
ctx.StringSlice("truncate-field"),
ctx.Uint("truncate-all-fields"),
}
obj := conn.Object("com.redhat.Yggdrasil1", "/com/redhat/Yggdrasil1")
if err := obj.Call("com.redhat.Yggdrasil1.MessageJournal", dbus.Flags(0), args...).Store(&journalEntries); err != nil {
Expand Down
6 changes: 6 additions & 0 deletions cmd/yggctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ from stdin.`,
Usage: "Truncates worker event data `FIELD` content if it exceeds the specified character `COUNT` (Format: fieldName=maxContentLength)",
Required: false,
},
&cli.UintFlag{
Name: "truncate-all-fields",
Aliases: []string{"taf"},
Value: 0,
Usage: "Truncates all worker event data content if it exceeds the specified character `COUNT`",
},
},
Action: messageJournalAction,
},
Expand Down
14 changes: 8 additions & 6 deletions cmd/yggd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ func (c *Client) MessageJournal(
until string,
persistent bool,
truncateFields []string,
truncateAllFields uint,
) ([]map[string]string, *dbus.Error) {

if c.dispatcher.MessageJournal == nil {
Expand Down Expand Up @@ -244,12 +245,13 @@ func (c *Client) MessageJournal(
}

filter := messagejournal.Filter{
Persistent: persistent,
MessageID: messageID,
Worker: worker,
Since: since,
Until: until,
TruncateFields: truncateFieldsMap,
Persistent: persistent,
MessageID: messageID,
Worker: worker,
Since: since,
Until: until,
TruncateFields: truncateFieldsMap,
TruncateAllFields: truncateAllFields,
}

journal, err := c.dispatcher.MessageJournal.GetEntries(filter)
Expand Down
4 changes: 3 additions & 1 deletion dbus/com.redhat.Yggdrasil1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@
@persistent: Filter journal entries to only contain entries from the persistent collection of
journal entries spanning multiple sessions. By default, journal entries are collected from
the active session.
@truncate_fields: Truncates the worker events optional data fields by the provided character count.
@truncate_fields: Truncates the worker events optional data fields to the provided character count.
This field is a dictionary with key/value pairs where the key is the name of the data field and
the value is the maximum length of the fields content.
@truncate_all_fields: Truncates all the worker events optional data fields to the provided character count.
@messages: Array of dictionary objects matching the input filter parameters.
Each element in the array is a dictionary with key/value pairs as follows:
Expand All @@ -69,6 +70,7 @@
<arg type="s" name="until" direction="in" />
<arg type="s" name="persistent" direction="in" />
<arg type="as" name="truncate_fields" direction="in" />
<arg type="u" name="truncate_all_fields" direction="in" />
<arg type="aa{ss}" name="messages" direction="out" />
</method>

Expand Down
44 changes: 29 additions & 15 deletions internal/messagejournal/messagejournal.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ type MessageJournal struct {
// Filter is a data structure representing the filtering options
// that are used when message journal entries are retrieved by yggctl.
type Filter struct {
Persistent bool
MessageID string
Worker string
Since string
Until string
TruncateFields map[string]int
Persistent bool
MessageID string
Worker string
Since string
Until string
TruncateFields map[string]int
TruncateAllFields uint
}

type errorJournal struct {
Expand Down Expand Up @@ -208,21 +209,34 @@ func (j *MessageJournal) GetEntries(filter Filter) ([]map[string]string, error)
// This process requires unmarshalling the worker event data,
// extracting the specified field (if any), and truncating the
// content of the field to the maximum length.
if len(filter.TruncateFields) > 0 {
if len(filter.TruncateFields) > 0 || filter.TruncateAllFields > 0 {
var eventData map[string]string
err = json.Unmarshal([]byte(workerEventData), &eventData)
if err != nil {
return nil, fmt.Errorf("cannot unmarshal worker event data: %w", err)
}

for field, length := range filter.TruncateFields {
fieldContent, ok := eventData[field]
if !ok {
log.Debugf("cannot find specified field to truncate: %v", field)
continue
// Only truncate all the fields if the filter was provided
// a value greater than 0. The default value is 0.
if filter.TruncateAllFields > 0 {
for field, content := range eventData {
if len(content) >= int(filter.TruncateAllFields) {
eventData[field] = fmt.Sprintf(
"%+v...",
eventData[field][:filter.TruncateAllFields],
)
}
}
if len(fieldContent) >= length && length > 0 {
eventData[field] = fmt.Sprintf("%+v...", eventData[field][:length])
} else {
for field, length := range filter.TruncateFields {
fieldContent, ok := eventData[field]
if !ok {
log.Debugf("cannot find specified field to truncate: %v", field)
continue
}
if len(fieldContent) >= length && length > 0 {
eventData[field] = fmt.Sprintf("%+v...", eventData[field][:length])
}
}
}

Expand All @@ -244,7 +258,7 @@ func (j *MessageJournal) GetEntries(filter Filter) ([]map[string]string, error)
"worker_name": workerName,
"response_to": responseTo,
"worker_event": ipc.WorkerEventName(workerEvent).String(),
"worker_data": string(truncatedEventData),
"worker_data": workerEventData,
}
entries = append(entries, newMessage)
}
Expand Down
117 changes: 80 additions & 37 deletions internal/messagejournal/messagejournal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ func TestGetEntries(t *testing.T) {
description: "get journal entries - unfiltered empty",
entries: []yggdrasil.WorkerMessage{},
input: Filter{
Persistent: true,
MessageID: "",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
Persistent: true,
MessageID: "",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
TruncateAllFields: 0,
},
wantError: &errorJournal{"no journal entries found"},
},
Expand All @@ -75,12 +76,13 @@ func TestGetEntries(t *testing.T) {
placeholderWorkerMessageEntry,
},
input: Filter{
Persistent: true,
MessageID: "",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
Persistent: true,
MessageID: "",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
TruncateAllFields: 0,
},
want: []map[string]string{
0: {
Expand All @@ -99,12 +101,13 @@ func TestGetEntries(t *testing.T) {
placeholderWorkerMessageEntry,
},
input: Filter{
Persistent: true,
MessageID: "test-invalid-filtered-message-id",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
Persistent: true,
MessageID: "test-invalid-filtered-message-id",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
TruncateAllFields: 0,
},
wantError: &errorJournal{"no journal entries found"},
},
Expand All @@ -127,12 +130,13 @@ func TestGetEntries(t *testing.T) {
},
},
input: Filter{
Persistent: true,
MessageID: "test-filtered-message-id",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
Persistent: true,
MessageID: "test-filtered-message-id",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
TruncateAllFields: 0,
},
want: []map[string]string{
0: {
Expand Down Expand Up @@ -163,12 +167,13 @@ func TestGetEntries(t *testing.T) {
},
},
input: Filter{
Persistent: true,
MessageID: "test-truncated-field-length",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{"test": 2},
Persistent: true,
MessageID: "test-truncated-field-length",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{"test": 2},
TruncateAllFields: 0,
},
want: []map[string]string{
0: {
Expand Down Expand Up @@ -199,20 +204,58 @@ func TestGetEntries(t *testing.T) {
},
},
input: Filter{
Persistent: true,
MessageID: "test-invalid-truncate-field",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{"test": 2},
Persistent: true,
MessageID: "test-invalid-truncate-field",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{"invalid-test": 2},
TruncateAllFields: 0,
},
want: []map[string]string{
0: {
"message_id": "test-invalid-truncate-field",
"response_to": "test-response",
"sent": "2000-01-01 00:00:00 +0000 UTC",
"worker_event": "",
"worker_data": "{\"test\":\"te...\"}",
"worker_data": "{\"test\":\"test-event-data\"}",
"worker_name": "test-worker",
},
},
},
{
description: "get journal entries - truncate all fields",
entries: []yggdrasil.WorkerMessage{
{
MessageID: "test-truncate-all-fields",
Sent: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
WorkerName: "test-worker",
ResponseTo: "test-response",
WorkerEvent: struct {
EventName uint "json:\"event_name\""
EventData map[string]string "json:\"event_data\""
}{
0,
map[string]string{"test1": "test1-event-data", "test2": "test2-event-data"},
},
},
},
input: Filter{
Persistent: true,
MessageID: "test-truncate-all-fields",
Worker: "",
Since: "",
Until: "",
TruncateFields: map[string]int{},
TruncateAllFields: 5,
},
want: []map[string]string{
0: {
"message_id": "test-truncate-all-fields",
"response_to": "test-response",
"sent": "2000-01-01 00:00:00 +0000 UTC",
"worker_event": "",
"worker_data": "{\"test1\":\"test1...\",\"test2\":\"test2...\"}",
"worker_name": "test-worker",
},
},
Expand Down

0 comments on commit 2e23130

Please sign in to comment.