Skip to content

formatter_csv: fix memory leak #4864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 19, 2025
Merged

Conversation

Watson1978
Copy link
Contributor

@Watson1978 Watson1978 commented Mar 14, 2025

Which issue(s) this PR fixes:
Fixes #3627

What this PR does / why we need it:
Seems in_exec plugin creats Thread object each interval and it invoke formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv, that thread will be permanently referenceable and will not be collected by the GC.

Here is memory usage of Ruby's process.
chart

Reproduce

See #3627

<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken https://github.com/fluent/fluentd/issues/3609
    retry_max_times 0  # need to go to secondary as soon as possible https://github.com/fluent/fluentd/issues/3610
  </buffer>
</match>

Docs Changes:

Release Note:
formatter_csv: fix memory leak

@Watson1978 Watson1978 changed the title formatter_csv: release Thread object formatter_csv: release Thread object when terminated Mar 14, 2025
@Watson1978 Watson1978 changed the title formatter_csv: release Thread object when terminated formatter_csv: use Thread local variable for cache Mar 14, 2025
@Watson1978 Watson1978 changed the title formatter_csv: use Thread local variable for cache formatter_csv: fix memory leak by using Thread local variable for cache Mar 14, 2025
Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
@Watson1978 Watson1978 marked this pull request as ready for review March 14, 2025 07:22
@Watson1978 Watson1978 requested a review from daipom March 14, 2025 07:22
Copy link
Contributor

@daipom daipom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Good catch!

It seems that in #2529, input plugins were assumed to spawn only a fixed number of threads for emitting.
However, in_exec for example, makes threads for emitting without limit.
The cache would then become infinitely large.
We need to fix this cache.

Copy link
Contributor

@daipom daipom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thread key would need to be unique for each plugin instance.

The following out_http code has a similar feature.
I want to align the code with this one unless there is a special reason not to.

def connection_cache_id_thread_key
"#{plugin_id}_connection_cache_id"
end

For example, I want the following getter.

def csv_thread_key
  "#{plugin_id}_csv"
end

@Watson1978
Copy link
Contributor Author

@daipom Thanks. I fixed the key name at last commit.

@Watson1978 Watson1978 requested a review from daipom March 14, 2025 09:19
Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Copy link
Contributor

@daipom daipom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot that this is a owned plugin.
It would not be expected to have an owned plugin with PluginId.

So, could you please fix the following points?

(Owned plugins are unique to the owner's id and usage.)

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
@Watson1978
Copy link
Contributor Author

When it invoke CsvFormatter via Fluent::Compat::TextFormatter, looks like it does not set owner...

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
@daipom daipom added this to the v1.19.0 milestone Mar 18, 2025
@Watson1978 Watson1978 added the backport to LTS We will backport this fix to the LTS branch label Mar 18, 2025
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
@daipom
Copy link
Contributor

daipom commented Mar 18, 2025

When it invoke CsvFormatter via Fluent::Compat::TextFormatter, looks like it does not set owner...

Sorry, I missed this point.
I have pushed another idea to fix this issue.

@Watson1978 Could you please review this commit?
If there seem to be some problems, we can revert it.

The aim of this commit is to ensure that the compat layer does not affect this cache feature.
(Because I'm not sure how to make the key unique on the compat layer context.)

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Copy link
Contributor

@daipom daipom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing the CI failures my commit caused!

It seems possible that there is no owner. (FluentBinlogReader)
It would be a good solution to disable the cache feature in such a case.

I commented on some minor points.
Please check them.

@daipom daipom self-requested a review March 18, 2025 09:13
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
@Watson1978 Watson1978 changed the title formatter_csv: fix memory leak by using Thread local variable for cache formatter_csv: fix memory leak Mar 18, 2025
Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Copy link
Contributor

@daipom daipom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for your contribution!

@daipom daipom merged commit 8a4506b into fluent:master Mar 19, 2025
9 of 10 checks passed
@Watson1978 Watson1978 deleted the formatter_csv branch March 19, 2025 04:50
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
kenhys pushed a commit to kenhys/fluentd that referenced this pull request Apr 23, 2025
**Which issue(s) this PR fixes**:
Fixes fluent#3627

**What this PR does / why we need it**:
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See fluent#3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken fluent#3609
    retry_max_times 0  # need to go to secondary as soon as possible fluent#3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**:
formatter_csv: fix memory leak

---------

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
daipom added a commit that referenced this pull request Apr 24, 2025
**Which issue(s) this PR fixes**: 
Backport #4864
Fixes #3627

**What this PR does / why we need it**: 
Seems `in_exec` plugin creats Thread object each interval and it invoke
formatter_csv on the thread.

If it use a Thread object as hash key when caching with formatter_csv,
that thread will be permanently referenceable and will not be collected
by the GC.

Here is memory usage of Ruby's process.

![chart](https://github.com/user-attachments/assets/4e74adda-154b-4c00-9cb4-3b1a0e8745fd)

### Reproduce
See #3627
```
<system>
  process_name fluentd_monitor
</system>

<source>
  @type exec
  tag hardware.memory
  run_interval 0.1
  command /home/watson/prj/sandbox/fluentd/get_memory_metrics.sh
  <parse>
    @type json
    types mem_available:float,swap_total:float,swap_free:float
  </parse>
</source>

<match **>
  @type exec
  command /home/watson/prj/sandbox/fluentd/psql_memory.sh
  <format>
    @type csv
    force_quotes false
    delimiter |
    fields time_local,mem_available,swap_total,swap_free
  </format>
  <buffer time>
    @type file
    path /home/watson/prj/sandbox/fluentd/log
    timekey 50s
    timekey_wait 0s
    flush_mode lazy
    total_limit_size 200MB
    retry_type periodic  # exponential backoff is broken #3609
    retry_max_times 0  # need to go to secondary as soon as possible #3610
  </buffer>
</match>
```

**Docs Changes**:

**Release Note**: 
formatter_csv: fix memory leak

Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Daijiro Fukuda <fukuda@clear-code.com>
Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
Co-authored-by: Shizuo Fujita <fujita@clear-code.com>
Co-authored-by: Daijiro Fukuda <fukuda@clear-code.com>
@kenhys kenhys added the backported "backport to LTS" is done label Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport to LTS We will backport this fix to the LTS branch backported "backport to LTS" is done
Projects
None yet
Development

Successfully merging this pull request may close these issues.

in_exec with out_exec in one config create file descriptors leak
3 participants