How to change field types in xml filter

i have this xml as an example

<testsuites tests="4409" failures="0" errors="0" time="23302.14700000004">
<testsuite errors="0" failures="0" hostname="localhost" name="pytest" skipped="1" tests="1" time="0.002" timestamp="2022-04-14T10:57:05.110800">
<testcase classname="test.api.test_profiler_database.profiler_database" name="test_profile_database" time="0.002">
<skipped message="Skip for HW device." type="pytest.skip">/tmp//test/api/test_profiler_database.py:40: Skip for HW device.</skipped>
</testcase>
</testsuite>
<testsuite errors="0" failures="0" hostname="localhost" name="pytest" skipped="0" tests="2" time="15.762" timestamp="2022-04-14T12:37:53.221709">
<testcase classname="test.api.mpls_headend.test_headend_ipv4_svi_enable_mpls_sr_acct.ipv4_svi_enable_mpls_sr_acct" name="test_prefix_global_ecmp_update_destination" time="11.961"/>
<testcase classname="test.api.mpls_headend.test_headend_ipv4_svi_enable_mpls_sr_acct.ipv4_svi_enable_mpls_sr_acct" name="test_prefix_global_error_handling" time="3.801"/>
</testsuite>
</testsuites>

i enter this in my parser file

input {
    file {
        mode => "read"
        path => "/data/elastic/JUNITS/*.xml"
        file_completed_action => "delete"
        start_position => "beginning"
        sincedb_path => "/dev/null"
        exit_after_read => true
        file_chunk_size => "1000000"
        codec => multiline {
           pattern => "<testsuites*>"
           negate => true
           what => "previous"
           max_lines => 100000
        }
    }
}
filter {
    xml {

        source => "message"
        target => "parsed"
        store_xml => "false"
        force_array => "false"
        xpath => ["/testsuites/@tests", "testsuites-tests"]
        xpath => ["/testsuites/@failures", "testsuites-failures"]
        xpath => ["/testsuites/@errors", "testsuites-errors"]
        xpath => ["/testsuites/@time", "testsuites-time"]
        xpath => ["/testsuites/testsuite/@errors" , "testsuite-errors"]
        xpath => ["/testsuites/testsuite/@failures" , "testsuite-failures"]
        xpath => ["/testsuites/testsuite/@hostname" , "testsuite-hostname"]
        xpath => ["/testsuites/testsuite/@name" , "testsuite-name"]
        xpath => ["/testsuites/testsuite/@skipped" , "testsuite-skipped"]
        xpath => ["/testsuites/testsuite/@tests" , "testsuite-tests"]
        xpath => ["/testsuites/testsuite/@time" , "testsuite-time"]
        xpath => ["/testsuites/testsuite/@timestamp" , "testsuite-timestamp"]
        xpath => ["/testsuites/testsuite/testcase/@classname" , "testcase-classname"]
        xpath => ["/testsuites/testsuite/testcase/@name" , "testcase-name"]
        xpath => ["/testsuites/testsuite/testcase/@time" , "testcase-time"]
        xpath => ["/testsuites/testsuite/testcase/skipped/@message" , "testcase-message"]
        xpath => ["/testsuites/testsuite/testcase/skipped/@type" , "testcase-type"]
    }
    date {
        match => ["testsuites-time" , "ISO8601", "yyyy-MM-dd HH:mm:ss.SSS"]
        target => "@timestamp"
        }
    ruby {
        code => '
            event.to_hash.each { |k, v|
                if k.start_with?("testsuites-tests")
                    event.set(k, v.to_i)
                elsif k.start_with?("testsuites-failures")
                    event.set(k, v.to_i)
                elsif k.start_with?("testsuites-errors")
                    event.set(k, v.to_i)
                elsif k.start_with?("testsuite-errors")
                    event.set(k, v.to_i)
                elsif k.start_with?("testsuite-failures")
                    event.set(k, v.to_i)
                elsif k.start_with?("testsuite-skipped")
                    event.set(k, v.to_i)
                elsif k.start_with?("testsuite-tests")
                    event.set(k, v.to_i)
                end
            }
        '
    }
}
output {
    elasticsearch {
        hosts => ["192.168.1.152:9200"]
        index => "junits-04-10-2022"
    }
}

data is entered correctly to the ELK but the fields are all strings.
i need to mode the ruby block to mutate the fields to either integer date or float

dose anyone here master ruby?

You should use a mapping/ template in Elasticsearch (think schema) to set the field types and when written to elasticseach from logstash the types will / should be correct.

No need to modify the ruby code.

A mapping is the schema and a template will apply that schema to all indices that match the index template pattern..

And or you can use the convert filter

Dates have their on special filter

No need to rewrite the ruby code...

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