Search code examples
timeansiblesyntaxruntime-errorcase

Detect slow disk speed using ansible


The threshold we felt for slow disk speed is when it takes more than 0.10 secs to read and write 3000 lines for which we used the below play and get the real time it took.

   - name: Extracting last 3000 lines from logs on "{{ inventory_hostname }}"
     shell: "time tail -3000 {{ item }} > {{ item }}_last3klines"
     register: diskspeed
     loop: "{{ log }}"

   - include_tasks: "{{ playbook_dir }}/printdiskspeed.yml"
     loop: "{{ diskspeed.results }}"
     loop_control:
       loop_var: files 

cat printdiskspeed.yml

   - debug:
       msg: "{{ files.stderr_lines[1].split()[1] }}"

Output:

TASK [debug] ******************************************************************
Wednesday 05 April 2023  23:54:18 -0500 (0:00:00.056)       0:00:17.689 *******
ok: [host3] => {
    "msg": "0m0.03s"
}

TASK [debug] ******************************************************************
Wednesday 05 April 2023  23:54:18 -0500 (0:00:00.020)       0:00:17.709 *******
ok: [host3] => {
    "msg": "0m0.02s"
}

TASK [debug] ******************************************************************
Wednesday 05 April 2023  23:54:18 -0500 (0:00:00.019)       0:00:17.729 *******
ok: [host3] => {
    "msg": "0m0.02s"
}

TASK [debug] ******************************************************************
Wednesday 05 April 2023  23:54:18 -0500 (0:00:00.025)       0:00:17.754 *******
ok: [host1] => {
    "msg": "0m0.02s"
}

TASK [debug] ******************************************************************
Wednesday 05 April 2023  23:54:18 -0500 (0:00:00.024)       0:00:17.779 *******
ok: [host1] => {
    "msg": "0m0.01s"
}

TASK [debug] ******************************************************************
Wednesday 05 April 2023  23:54:18 -0500 (0:00:00.025)       0:00:17.804 *******
ok: [host1] => {
    "msg": "0m0.02s"
}

I need help on how to compare and check if the time in the output above is greater than 0m0.10s?

I tried the below but it errors

   - debug:
       msg: "DISK SLOW"
     when: "{{ files.stderr_lines[1].split()[1] }}" > "0m0.10s"

Output:

TASK [include_tasks] ****************************************************************************************************************************************
Wednesday 05 April 2023  23:36:24 -0500 (0:00:00.064)       0:00:18.779 *******
fatal: [host3]: FAILED! => {"reason": "We were unable to read either as JSON nor YAML, these are the errors we got from each:\nJSON: Expecting value: line 1 column 4 (char 3)\n\nSyntax Error while loading YAML.\n  did not find expected comment or line break\n\nThe error appears to be in '/web/playbooks/automation/printdiskspeed.yml': line 8, column 55, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n       msg: \"DISK SLOW\"\n     when: \"{{ files.stderr_lines[1].split()[1] }}\" > \"0m0.02s\"\n                                                      ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n    with_items:\n      - {{ foo }}\n\nShould be written as:\n\n    with_items:\n      - \"{{ foo }}\"\n"}

Can you please suggest the right syntax / solution?


Solution

  • Even if in my opinion the given approach isn't the correct one to address the use case and should be avoided, there might two simple quick and lazy solutions to the described problem.


    A less preferable approach by using post-processing on the Ansible Control Node might be to treat the values just as a kind of "version". To do so, you may have a look into following minimal example playbook.

    ---
    - hosts: localhost
      become: false
      gather_facts: false
    
      vars:
    
        expectedTime: "0m0.10s"
        measuredTime: "0m0.15s"
    
      tasks:
    
      - name: Show hint
        debug:
          msg: "SLOW"
        when: measuredTime is version(expectedTime, '>=')
    

    Similar Q&A and further


    A more preferable approach by using pre-processing on the Remote Node might be to create and gather only the result and value in interest.

    ---
    - hosts: localhost
      become: true
      gather_facts: false
    
      tasks:
    
      - name: Extracting last lines from log
        shell: 'TIMEFORMAT=%R; time tail -3000 /var/log/messages > /tmp/messages'
        changed_when: false # because it is an reporting task
        register: realtime
    
      - debug:
          msg: "{{ realtime.stderr }}"
    

    resulting into an output of

    TASK [Extracting last lines from log] *****
    ok: [localhost]
    
    TASK [debug] *****
    ok: [localhost] =>
      msg: '0.012'
    

    after conversion a numerical value only.

      - debug:
          msg: "FAST"
        when: realtime.stderr | float <= 0.010
    

    Credit To

    Similar Q&A