Skip to content
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

fix: lock accesses to encoder in json stdout exporter to prevent crash #2265

Merged
merged 5 commits into from
Sep 30, 2021

Conversation

lizthegrey
Copy link
Member

@lizthegrey lizthegrey commented Sep 28, 2021

Which problem is this PR solving?

verified that

func (e *metricExporter) marshal(v interface{}) ([]byte, error) {
does not suffer from this problem and thus doesn't also need to be fixed.

Short description of the changes

@lizthegrey lizthegrey changed the title lock accesses to encoder fix: lock accesses to encoder in json stdout exporter to prevent crash Sep 28, 2021
@codecov
Copy link

codecov bot commented Sep 28, 2021

Codecov Report

Merging #2265 (1082e33) into main (00d8ca5) will decrease coverage by 0.0%.
The diff coverage is 100.0%.

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #2265     +/-   ##
=======================================
- Coverage   72.5%   72.4%   -0.1%     
=======================================
  Files        168     168             
  Lines      11872   11874      +2     
=======================================
- Hits        8609    8608      -1     
- Misses      3029    3031      +2     
- Partials     234     235      +1     
Impacted Files Coverage Δ
exporters/stdout/stdouttrace/trace.go 76.4% <100.0%> (+0.9%) ⬆️
...s/otlp/otlptrace/internal/connection/connection.go 14.8% <0.0%> (-1.6%) ⬇️

@MadVikingGod
Copy link
Contributor

MadVikingGod commented Sep 28, 2021 via email

@Aneurysm9
Copy link
Member

That's a good point @MadVikingGod. It looks like the SimpleSpanProcessor is only taking a read lock on the exporter mutex, which wouldn't serialize access. See this discussion on its addition for more context.

I think that it should be safe to change that to an exclusive lock given that the SimpleSpanProcessor is expected to be synchronous. I don't think it hurts to also add the mutex around the stdouttrace exporter's use of the JSON encoder.

@lizthegrey
Copy link
Member Author

That's a good point @MadVikingGod. It looks like the SimpleSpanProcessor is only taking a read lock on the exporter mutex, which wouldn't serialize access. See this discussion on its addition for more context.

I think that it should be safe to change that to an exclusive lock given that the SimpleSpanProcessor is expected to be synchronous. I don't think it hurts to also add the mutex around the stdouttrace exporter's use of the JSON encoder.

I fingered the change to the json encoder as the proximal change, because this is a regression from 0.20.0, and the simplespanprocessor hadn't changed since then. But I'm flexible as to how we fix this.

@evantorrie
Copy link
Contributor

evantorrie commented Sep 29, 2021

Root cause of the problem does appear to be that Go standard library's json.Encoder is not thread safe when using non-empty indentPrefix and/or indentValue.

It reuses the same indentBuf inside the Encoder struct rather than creating a new buffer each invocation to handle the pretty-printed JSON output.

@lizthegrey Does it work if you remove the pretty-printing option from the the stdouttrace exporter?

@lizthegrey
Copy link
Member Author

lizthegrey commented Sep 29, 2021

Root cause of the problem does appear to be that Go standard library's json.Encoder is not thread safe when using non-empty indentPrefix and/or indentValue.

It reuses the same indentBuf inside the Encoder struct rather than creating a new buffer each invocation to handle the pretty-printed JSON output.

Yeah, this is documented here: golang/go#32957

@lizthegrey Does it work if you remove the pretty-printing option from the the stdouttrace exporter?

I'm sure it would, but Go gives guidance that you should not assume stdlib objects are thread-safe unless documented otherwise.

@Aneurysm9
Copy link
Member

@lizthegrey can you merge in main and I'll get this merged? We can evaluate separately whether the simple span processor should be blocking as well.

@lizthegrey
Copy link
Member Author

branch updated

@Aneurysm9 Aneurysm9 merged commit 66fccc0 into open-telemetry:main Sep 30, 2021
@lizthegrey lizthegrey deleted the lizf.fix-json-crash branch September 30, 2021 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[crash] stdout json exporter crashes when many spans generated at once
5 participants