Skip to content

Conversation

@americodls
Copy link
Contributor

Adds OpenTelemetry instrumentation for the FactoryBot gem to provide visibility into test data creation patterns during testing.

Subscribes to the factory_bot.run_factory ActiveSupport::Notifications event to capture all factory operations without monkey-patching. Supports FactoryBot 4.0+ and captures all factory strategies (create, build, build_stubbed, attributes_for) including batch operations (create_list, build_list, etc.).

Span naming: FactoryBot.{strategy}({factory_name})
Example: FactoryBot.build(user), FactoryBot.create_list(post)

Span attributes:

  • factory_bot.strategy: Internal strategy name (build, create, stub, attributes_for)
  • factory_bot.factory_name: Name of the factory being used
  • factory_bot.traits: Comma-separated list of traits applied (if any)

@kaylareopelle
Copy link
Contributor

Hi @americodls, thanks for opening this PR. Would you be interested in being a codeowner for this gem? That would involve reviewing PRs and issues related to the factory bot instrumentation. We don't have the codeowner behavior automated in GitHub, but we're currently documenting this in the CODEOWNERS file in the repo.

Adds OpenTelemetry instrumentation for the FactoryBot gem to provide
visibility into test data creation patterns during testing.

Subscribes to the factory_bot.run_factory ActiveSupport::Notifications event
to capture all factory operations without monkey-patching. Supports FactoryBot
4.0+ and captures all factory strategies (create, build, build_stubbed,
attributes_for) including batch operations (create_list, build_list, etc.).

Span naming: FactoryBot.{strategy}({factory_name})
Example: FactoryBot.build(user), FactoryBot.create_list(post)

Span attributes:
- factory_bot.strategy: Internal strategy name (build, create, stub, attributes_for)
- factory_bot.factory_name: Name of the factory being used
- factory_bot.traits: Comma-separated list of traits applied (if any)
@americodls americodls force-pushed the ad/add-factory-bot-instrumentation branch from b21de9a to 48f77b0 Compare October 8, 2025 09:10
@americodls
Copy link
Contributor Author

Hi @kaylareopelle! Happy to take it on 🙂
I've just updated the CODEOWNERS file — let me know if anything is needed!

@simi
Copy link
Contributor

simi commented Oct 8, 2025

@americodls would you mind to share more how do you instrument testing also?

span_name = "FactoryBot.#{strategy_symbol}(#{factory_name})"

attrs = {
'factory_bot.strategy' => internal_strategy,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion name this test.data.strategy given it could be used elsewhere and we already have the test namespace?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback!

I checked the OpenTelemetry test semantic conventions and found that the test.* namespace currently only defines attributes for test execution metadata (test cases, suites, and their statuses).

Since test.data isn’t part of the spec yet, using it now could risk conflicts if it’s added later. The current factory_bot.* approach keeps things scoped to this library’s specific domain.

I’d suggest keeping the dedicated namespace for now — we can always generalize to something like test.data.* if similar fixture/factory patterns start appearing across other testing libraries. That way, we’re being intentional rather than speculative about the abstraction.

Of course, I’m open to other perspectives — input from the maintainers would be especially valuable given their broader experience in this space.

Copy link
Contributor

Choose a reason for hiding this comment

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

So perhaps the following helps defining attributes

When defining an attribute for a narrow use case, think about potential broader use cases. For example, if creating a system-specific attribute, evaluate whether other systems in the same domain might need a similar attribute in the future.

I see the attributes identified as falling into that category as anything generating data needs a strategy etc.

I would even suggest raising a pr to get the attributes/spans added.

Copy link
Contributor

Choose a reason for hiding this comment

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

Although I agree with @thompson-tomo that we need to do our best to adhere to the spec for attribute naming; I am amenable to releasing custom attributes for our instrumentations since they are all pre-1.0 at this point and we are still working through figuring out how the version semantic conventions used in instrumentation libraries.

The factory bot use case seems very narrow since the spans are implementation specific. Other testing object mother or factory libraries will likely use different domain language based on DSLs and helper methods. We may find that higher level span names may have some overlap but library specific attributes like traits are likely not going to be a good fit for a "broader" use case.

@americodls Are there any other testing libraries that are currently instrumented in other languages?

Is there enough traction there to start up a conversation between SIGs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@americodls Are there any other testing libraries that are currently instrumented in other languages?

Is there enough traction there to start up a conversation between SIGs?

I haven't found anything that's why I suggested to "go as is".

'factory_bot.factory_name' => factory_name.to_s
}

attrs['factory_bot.traits'] = traits.join(',') if traits.any?
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion name this test.data.traits given it could be used elsewhere and we already have the test namespace?

Comment on lines 29 to 34
attrs = {
'factory_bot.strategy' => internal_strategy,
'factory_bot.factory_name' => factory_name.to_s
}

attrs['factory_bot.traits'] = traits.join(',') if traits.any?
Copy link
Contributor

Choose a reason for hiding this comment

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

If test.data.* is adopted, I would add a test.data.provider.name attribute.

@americodls
Copy link
Contributor Author

@americodls would you mind to share more how do you instrument testing also?

Something like this:

# spec/spec_helper.rb

#...

if ENV["ENABLE_TRACING"]
  require 'opentelemetry/sdk'
  require 'opentelemetry/instrumentation/rspec'

  OpenTelemetry::SDK.configure do |c|
    # ...
    c.use 'OpenTelemetry::Instrumentation::RSpec'
    c.use 'OpenTelemetry::Instrumentation::FactoryBot'
    # ...
  end
end

RSpec.configure do |config|
  #...
  config.after(:suite) do
    OpenTelemetry.tracer_provider.shutdown if ENV["ENABLE_TRACING"]
  end
  #...
end

Copy link
Contributor

@arielvalentin arielvalentin left a comment

Choose a reason for hiding this comment

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

Thank you for your submission!

There are a few required changes you will have to make to avoid issues/conflicts with our release tooling.

I will have to reach out for help to other users who are FactoryBot users to help with a review before we merge.

@americodls americodls force-pushed the ad/add-factory-bot-instrumentation branch from da05c9e to 4d0543b Compare October 12, 2025 13:55
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Oct 12, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@americodls americodls force-pushed the ad/add-factory-bot-instrumentation branch 2 times, most recently from 3e4df45 to 30a3ea8 Compare October 12, 2025 14:02
americodls and others added 4 commits October 12, 2025 15:26
Per OpenTelemetry semantic conventions, plural attribute names should
use array values. Changed factory_bot.traits from comma-separated
string to string array.
- Move instrumentation.install to top-level before block
- Remove redundant install calls from nested describe blocks
- Add comprehensive attribute tests for all strategies
- Test empty traits array in all relevant sections
- Ensure all 3 attributes tested: strategy, factory_name, traits
@americodls americodls force-pushed the ad/add-factory-bot-instrumentation branch from 30a3ea8 to 9e42630 Compare October 12, 2025 14:27
@arielvalentin
Copy link
Contributor

arielvalentin commented Nov 3, 2025

@americodls there seems to be conflicts with upstream. Please merge main and we will proceed.

@arielvalentin arielvalentin enabled auto-merge (squash) November 9, 2025 19:30
Copy link
Contributor

@arielvalentin arielvalentin left a comment

Choose a reason for hiding this comment

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

@americodls thank you again for your submission.

Although I approved this PR, I am going to have request some additional changes.

Our CI workflows have changed and this gems test suite is not longer running by default.

You will need to add entries in the following actions workflow:

In addition to that please add factorybot as a gem dependency in our canary install test:

Thank you for your patience.

@americodls
Copy link
Contributor Author

@arielvalentin

Thanks for your feedback!
I've gone ahead and fixed the issues you pointed out 🙂

Let me know if there’s anything else you’d like me to tweak!

@arielvalentin arielvalentin merged commit c097042 into open-telemetry:main Nov 10, 2025
39 checks passed
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.

5 participants