Nested field in a grok filter

    grok { match => { "message" => "^inactive: %{WORD:inactive}, sources : \[(?<[@metadata][sources]>[^\]]+)\], assigned: %{WORD:assigned}" } }
    ruby {
        code => '
            matches = event.get("[@metadata][sources]").scan(/{id:\s*([0-9]+), type:\s*([a-zA-Z0-9]+), name:\s*([a-zA-Z0-9]+)}/)
            event.set("matches", matches)
        '
    }

will get you to

   "matches" => [
    [0] [
        [0] "1",
        [1] "fr",
        [2] "custom"
    ],
    [1] [
        [0] "2",
        [1] "fr",
        [2] "random"
    ]
]

It is unclear what structure you want that data in, so you might be able to move stuff around using mutate, or you may need ruby.