Skip to content

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
@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
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 <[email protected]>
@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 <[email protected]>
@daipom daipom added this to the v1.19.0 milestone Mar 18, 2025
@Watson1978 Watson1978 added the backport to v1.16 We will backport this fix to the LTS branch label Mar 18, 2025
@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.)

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 <[email protected]>

Signed-off-by: Shizuo Fujita <[email protected]>
@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
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
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 <[email protected]>
Signed-off-by: Daijiro Fukuda <[email protected]>
Signed-off-by: Kentaro Hayashi <[email protected]>
Co-authored-by: Shizuo Fujita <[email protected]>
Co-authored-by: Daijiro Fukuda <[email protected]>
@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 v1.16 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