-
-
Notifications
You must be signed in to change notification settings - Fork 53
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 dialyzer issues and use :ok tuples when :error tuples are possible #63
Conversation
I also put in a commit to set the formatter |
Should pull in the newest Dialyxir RC while you're here to get the new Elixir formatting =) |
@callback now() :: term | ||
@callback default_sender() :: module | ||
@callback trace_id() :: Spandex.id() | ||
@callback span_id() :: Spandex.id() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the adapter is in charge of the type, meaning we shouldn't set it to be non_neg_integer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually wanted to propose that we change it to String.t()
so that the adapter can choose, but it was currently an integer so I wanted to do that as a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it's explicitly not a string for datadog and others. We really can't set a type in this library otherwise the adapters will fail dialyzer and/or they will have to be bound by whatever type we set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that Spandex says it's a String.t()
and the adapters can serialize/deserialize however they want to. I imagine most back-ends will use a UUID - I was surprised that DataDog just uses a random integer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really see a benefit to forcing serialization/deserialization on the adapters end. Nothing in core cares if they are a string, so why bother forcing it? We should just let it be whatever type their adapter uses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I guess that's fair. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I defined Spandex.id()
to be term()
so that we can still document the fact that a function expects a Spandex.id()
, and still leave it up to the Adapter
s, without having to sprinkle term()
all over the place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's a good plan :)
lib/span.ex
Outdated
update(%__MODULE__{}, opts, @span_opts) | ||
case Optimal.validate(opts, @span_opts) do | ||
{:ok, opts} -> | ||
span = Map.merge(%Span{}, Enum.into(opts, %{})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a pretty radical change from calling update
I'm pretty positive that update
contains transformations that we shouldn't drop here. Additionally, we'd want to just do struct(Span, opts)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this ought to be left calling into update
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I changed it is that dialyzer was unhappy about passing the struct into the update function with all nil values (because the type def says that’s not allowed). I’ll think about whether there’s a different way to solve that without just allowing all the fields to be nil (which seems like a cop-out to me).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it is a copout, but it's definitely losing functionality by not calling into update, so we'll have to figure something out. Perhaps just extracting the main parts ofthe update function into their own functions and calling those from create?
mix.exs
Outdated
@@ -4,7 +4,7 @@ defmodule Spandex.Mixfile do | |||
def project do | |||
[ | |||
app: :spandex, | |||
version: "2.0.0", | |||
version: "2.1.0-dev", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll bump the versions separately afterwards, as opposed to in this PR.
def distributed_context(_, :disabled), do: {:error, :disabled} | ||
|
||
def distributed_context(conn, opts) do | ||
adapter = opts[:adapter] | ||
adapter.distributed_context(conn, opts) | ||
end | ||
|
||
# Private Helpers | ||
|
||
defp do_continue_trace(name, trace_id, opts) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard to cross reference visually. None of the bodies in do_*
are altered from their originals, right? Same as they were when they were inline above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ll double check and make sure we have decent test coverage on them before we merge. One reason to do this (besides making the functions simpler to understand) was that dialyzer was having trouble following along when there is a with
inside an if
/else
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, definitely a positive change, just wanted to make sure I didn't miss any changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a bunch of tests, so I think this refactor should be relatively safe.
Note that there are some tests with @tag :skip
because they don't currently validate additional opts, but I wasn't sure whether that was intentional.
@asummers lets do a separate PR with that. Feel free to, or to lodge an issue for me to do it :) |
This looks great! Left some feedback/discussion. |
Hadn't heard about that @asummers, but now I want to look into that! 😁 |
The testing looks awesome. I'm very surprised to hear the opts with invalid types are ignored. If that's true, it's 100% a bug that we should fix. I still have a slight issue with Span.new I think. When I'm at my laptop I'll post an alternative. Aside from that, and the issue w/ validation, I think this should be good to go. |
We should diagnose the validation issue at least, and then maybe fix it in a separate PR. |
Ah, I see the issue. The validator is doing the right thing, but we always return the span, even if we didn't update it. I think that, as part of this return type refactor, we would expect to return the errors. |
Thinking about it now, there are certain functions where that would be hard (like |
Alright, @GregMefford since we know whats up with the validation issue the only thing left is |
5c52377
to
e7e6713
Compare
Ok, I think this is all set. ✅ |
When running
mix dialyzer
, I was getting the following errors:Those are now resolved, but when I started to tug on that thread, the changes ended up leading me all over the place and I'm sorry for the huge PR.
As mentioned in #62, this also standardizes on
{:ok, result}
tuples wherever an{:error, reason}
tuple is possible. For that reason, I'm proposing a version bump from2.0.0
to2.1.0
since it's a small breaking change to the API, but my guess is that people probably aren't often using the return values from these functions in practice, as long as the right things are getting passed around inside Spandex.