# Using kv to produce fields with every word capitalized

**URL:** https://discuss.elastic.co/t/using-kv-to-produce-fields-with-every-word-capitalized/242058
**Category:** Logstash
**Created:** [July 21, 2020, 3:35pm UTC](https://discuss.elastic.co/t/using-kv-to-produce-fields-with-every-word-capitalized/242058 "2020-07-21T15:35:43Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![username11](https://avatars.discourse-cdn.com/v4/letter/u/e5b9ba/32.png) [@username11](https://discuss.elastic.co/u/username11)
#### Post date: [July 21, 2020, 3:35pm UTC](https://discuss.elastic.co/t/using-kv-to-produce-fields-with-every-word-capitalized/242058/1 "2020-07-21T15:35:43Z")

</div>

I am using kv to parse a certain log that contains comma-separated key-value pairs. However, the keys may contain multiple space-separated words with inconsistent capitalization, and I'm trying to bring the resulting field names to a defined naming convention - no spaces, every word capitalized, i.e.:

Input:  
`Field One: value 1, Field two: value 2, Field three: "value 3"`  
Output:

```auto
"FieldOne": "value 1",
"FieldTwo": "value 2",
"FieldThree": "value 3"

```

Right now, I remove the spaces in the field names using kv, and then I'm left with inconsistently-capitalized field names, and whatever does not fit the convention, I rename using mutate:

```auto
    kv {
        source => "message"
        target => "processed_message"

        field_split => ","
        value_split_pattern => ": "
        # Most keys already capitalize every word, which is the chosen naming convention;
        # "capitalize" only works for the first word and breaks the rest.
        #transform_key => "capitalize"
        remove_char_key => "- "
        trim_value => "\""
    }

    mutate {
        rename => { ... }
    }

```

I've been trying to find a universal solution for this case, since new fields may appear, and I don't want to amend the config every time. Is there a right way to do this with available plugins, or can it only be done with Ruby code?

---

<div class="post-metadata">

### Author: ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)
#### Post date: [July 21, 2020, 3:49pm UTC](https://discuss.elastic.co/t/using-kv-to-produce-fields-with-every-word-capitalized/242058/2 "2020-07-21T15:49:49Z")

</div>

> [@username11](#):
>
> can it only be done with Ruby code?

Yes, I think that will require a ruby filter.

---

<div class="post-metadata">

### Author: ![username11](https://avatars.discourse-cdn.com/v4/letter/u/e5b9ba/32.png) [@username11](https://discuss.elastic.co/u/username11)
#### Post date: [July 23, 2020, 10:07am UTC](https://discuss.elastic.co/t/using-kv-to-produce-fields-with-every-word-capitalized/242058/3 "2020-07-23T10:07:58Z")

</div>

Dear future people,

This is the code that I came up with. Works well so far. Feel free to use, but do mind that I do not know Ruby at all.

```auto
filter {
    # Parse out comma-separated key-value pairs.
    # Commas are escaped by quoting the string; kv seems to handle this if trim_value is set, but this is not documented.
    # Space removal and capitalization is handled by ruby code below.
    kv {
        source => "message"
        target => "processed_message"

        field_split => ", "
        value_split_pattern => ": "
        trim_value => "\""

        remove_field => ["message"]
    }

    # Enforce field naming convention for the target container:
    # Alphanumeric characters only, every word capitalized.
    ruby {
        code => "
            # Only work on target container fields
            target_container = '[processed_message]'

            keys = event.get(target_container).to_hash.keys
            keys.each { |key|
                # Split on all non-alphanumeric characters - spaces, dashes, brackets, etc.
                # Should skip the loop if the array is empty.
                words = key.split(/[^[:alnum:]]+/)
                words.each_index { |i|
                    words[i].capitalize!
                }

                # You should use words.flatten.join('') to account for nested fields,
                # but this should never happen, so I'd rather avoid the overhead.
                new_key = words.join('')

                # Rename the resulting field
                event.set(
                    target_container + '[' + new_key + ']',
                    event.remove(target_container + '[' + key + ']')
                )
            }

            # Exception handling
            rescue Exception => e
                event.set('logstash_ruby_exception', 'capitalize: ' + e.message)
        "
    }
}

```

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)
#### Post date: [August 20, 2020, 10:08am UTC](https://discuss.elastic.co/t/using-kv-to-produce-fields-with-every-word-capitalized/242058/4 "2020-08-20T10:08:01Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
