I stumbled upon this 6 year old post https://discuss.elastic.co/t/keeping-global-variables-in-ls/39908 which describes the exact same scenario as mine.
After following this post, I was able to get partial success using ruby filter.
My progress. so far:
- 
Using ruby filter, store the value of task_name field in a variable called @@taskname that will persist for later user.
 - 
Using GROK, search for events where you want to insert the above field.
 - 
Field inserted in all the lines that match in step 2.
 
What I am stuck at:
- 
"_grokparsefailure" tag gets inserted in all events, even though the patterns have matched and the task_name field was inserted.
 - 
When I run Logstash again, then all 4 events get the same task_name inserted. Actual behavior should be, 2 events get task_name as "Formatting xfs filesystem" and the other 2 should get the. 2nd task name. If I run it again, I get one of the events getting a null value. Any ideas for the reason behind this random behaviour?
 
I have made sure to set the Logstash workers to '1' for thread safety.
Below is my conf
## Parse Logs
input {
  file {
    path => "/var/log/dummy.log"
    start_position => "beginning"
    sincedb_path  => "/dev/null"
  }
}
filter {
  grok {
    patterns_dir => ["./patterns"]
    match => { "message" => "%{GROK_PATTERN}TASK%{SPACE}\[%{WORD:role}%{SPACE}\:%{SPACE}%{GREEDYDATA:task_name}\]" }
  }
## Store the value in @@taskname
  ruby {
       init => '@@taskname = ""'
       code => '
         if event.get("task_name")
            @@taskname = event.get("task_name")
         end'
  }
## Match events where the @@taskname should be added
  grok {
    patterns_dir => ["./patterns"]
    match => { "message" => "%{GROK_PATTERN}%{WORD:task_status}\:%{SPACE}\[%{HOSTNAME:hostname}.*" }
  }
## Insert the field
  if [task_status] =~ "changed" {
    ruby { code => 'event.set("task_name", @@taskname)' }
  }
}
output {
  elasticsearch {
    hosts => ["TESTVM-1:9200"]
    index => "dummy_logs"
  }
  stdout {}
}