Benjamin Marwell
Benjamin Marwell

Reputation: 1246

Xidel: Parse attributes into new object

Given is a verbose GC log from any Java virtual machine (could be any xml, so not tagging with java):

<?xml version="1.0" ?>

<verbosegc version="versioninformation">

<af type="nursery" id="49383" timestamp="Jan 01 01:34:54 2015" intervalms="33.821">
  <tenured freebytes="769243504" totalbytes="1610416128" percent="47" >
    <soa freebytes="198858272" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
  <gc></gc>
  <tenured freebytes="768800232" totalbytes="1610416128" percent="47" >
    <soa freebytes="198415" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
</af>

<af type="nursery" id="49384" timestamp="Jan 01 01:35:54 2015" intervalms="40.877">
  <tenured freebytes="768800232" totalbytes="1610416128" percent="47" >
    <soa freebytes="198415" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
  <gc></gc>
  <tenured freebytes="768320928" totalbytes="1610416128" percent="47" >
    <soa freebytes="197935696" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
</af>

So, I'd like to create a new object, which gets repeated for each garbage collection cycle with the timestamp and the used bytes (total minus free). The calculation works just fine, but the output does not. This is what I excpect to get:

[
  {
    "timestamp": "Jan 01 01:34:54 2015",
    "used": 8.41172624E8
  },
  {
    "timestamp": "Jan 01 01:35:54 2015",
    "used": 8.41615896E8
  },
]

I tried this command line, which sadly creates a null timestamp and a long list of heap information:

xidel --input-format=xml   -e "//af/tenured[1]/(heap:={used:=(@totalbytes - @freebytes):timestamp:=@timestamp})" gc.log --output-format=json-wrapped

The output looks like this:

[
  {
    "timestamp": [null],
    "used": [8.41172624E8, 8.41615896E8]
  }
]

Obviously not what I excpected.

Upvotes: 2

Views: 566

Answers (2)

BeniBela
BeniBela

Reputation: 16917

You can actually write the entire JSON structure in the extract expression and do not need output-format:

xidel --input-format=xml   -e "[ //af/tenured[1]/{'used':(@totalbytes - @freebytes),'timestamp':../@timestamp} ]" gc.log 

Upvotes: 1

Benjamin Marwell
Benjamin Marwell

Reputation: 1246

The correct idea was not to assign the object to a variable (heap:={}) and to use json notation directly in xpath. And third, timestamp is a level above tenured, so I placed ../ in front.

So this one works:

xidel --input-format=xml   -e "//af/tenured[1]/('used':(@totalbytes - @freebytes),'timestamp':../@timestamp)" gc.log --output-format=json-wrapped

Output:

[
    [
        {
            "timestamp": "Jan 01 01:34:54 2015",
            "used": 841172624.0
        },
        {
            "timestamp": "Jan 01 01:35:54 2015",
            "used": 841615896.0
        },
    ]
]

It gives an extra array, but I can live with that. At least it's a stable output and parsable.

Upvotes: 0

Related Questions