-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Adding more customization to NetworkLoggerPlugin. #1894
Adding more customization to NetworkLoggerPlugin. #1894
Conversation
fileprivate let cURLTerminator = "\\\n" | ||
fileprivate let output: (_ separator: String, _ terminator: String, _ target: TargetType, _ items: Any...) -> Void | ||
fileprivate let requestDataFormatter: ((Data) -> (String))? | ||
fileprivate let responseDataFormatter: ((Data) -> (Data))? |
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.
Not sure here why both dataFormatters did not have the same return type. As for now, i've made both of them return a String - which I believe is the logical choice for a logger -, but if it causes some trouble let me now.
@@ -250,8 +251,7 @@ final class MoyaProviderIntegrationTests: QuickSpec { | |||
provider.request(.zen) { _ in done() } | |||
} | |||
|
|||
expect(log).to(contain("Request:")) | |||
expect(log).to(contain("{ URL: https://api.github.com/zen }")) | |||
expect(log).to(contain("Request: https://api.github.com/zen")) |
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 request's description wasn't correct here. I don't think it's due to my work but rather an update of AF 5 that wasn't fixed.
Tests/NetworkLoggerPluginSpec.swift
Outdated
|
||
expect(log).to(contain("Response:")) | ||
expect(log).to(contain("{ URL: https://api.github.com/zen }")) | ||
expect(log).to(contain("formatted request body")) |
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.
There seemed to be a mismatch between the test's name and its content: it was supposed to check the requestDataFormatter, but acted like it was testing the response. So I fixed it by trully checking the request.
I didn't have any feedback on the draft so I continued along the path. |
Proselint report on docs/Plugins.md
Mdspell report on docs/Plugins.md:
Mdspell report on docs/MigrationGuides/migration_13_to_14.md:
Generated by 🚫 Danger Swift against 12d7515 |
Codecov Report
@@ Coverage Diff @@
## development #1894 +/- ##
===============================================
+ Coverage 92.27% 92.48% +0.21%
===============================================
Files 26 26
Lines 919 932 +13
===============================================
+ Hits 848 862 +14
+ Misses 71 70 -1
Continue to review full report at Codecov.
|
public extension NetworkLoggerPlugin { | ||
struct Configuration { | ||
|
||
public typealias OutputType = (_ target: TargetType, _ items: [Any]) -> Void |
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.
⚠️ Types should be nested at most 1 level deep (nesting
)
struct Configuration { | ||
|
||
public typealias OutputType = (_ target: TargetType, _ items: [Any]) -> Void | ||
public typealias DataFormatterType = (Data) -> (String) |
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.
⚠️ Types should be nested at most 1 level deep (nesting
)
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.
Should we set the swiftlint flag to ignore this? @amaurydavid @sunshinejr
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.
Definitively, though I'm not sure whether to disable it for the whole project or just those two typealiases.
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 we could just let for those two. Maybe this warning is good to have and decide if we fix or disable the warning on a case by case basis. cc @sunshinejr thoughts?
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.
Hey @amaurydavid, thanks for doing this! And sorry for the late review. This is a really big change to the plugin and I wanted to take my time and think in what direction I would like to go with that.
And this is a very good start! I really like that we extracted all the options to a separate entity and that we are able to customize a lot more things. Additionally, as our Vision.md states:
provide an API where common things are easy, and uncommon things are possible.
I think we are doing a very good job on the flexibility of the API, but we need to improve on the common use cases. E.g. when I would like to print everything, now instead of just using verbose: true
I would need to do:
let provider = MoyaProvider<MultiTarget>(plugins: [NetworkLoggerPlugin(configuration: .init(requestLoggingOptions: .verbose,
successResponseLoggingOptions: .verbose,
errorResponseLoggingOptions: .verbose))])
which, I think we can agree, is not ideal. I know that this allows us for a lot better and more flexible logging options, but the popular use case suffers. Maybe we could try to use enum for the logging option and include what we had before + a custom one? E.g.
enum LoggingOption {
default
verbose
custom(request: RequestLogginOptions, response: ResponseLoggingOptions...etc.)
}
But I think in that case we would need to move cURL
option somewhere else as it won't really fit in there (all of them are available printing parts but cURL
is a response-output formatter rather.
Let me know what do you think about it!
I agree, the necessity of having to use .verbose on all 3 parameters struck me when updating the tests. |
@amaurydavid thanks, I think it looks better! gonna checkout the branch and play with the logger :) cc @LucianoPAlmeida @pedrovereza are u guys up for a CR maybe? |
@@ -231,16 +231,11 @@ final class MoyaProviderIntegrationTests: QuickSpec { | |||
|
|||
describe("a provider with network logger plugin") { | |||
var log = "" | |||
var plugin: NetworkLoggerPlugin! | |||
let plugin = NetworkLoggerPlugin(configuration: .init(output: { log += $1.joined() }, |
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.
oh nice this looks really clean now!
fileprivate let dateFormatter = DateFormatter() | ||
fileprivate let separator = ", " | ||
fileprivate let terminator = "\n" | ||
fileprivate let cURLTerminator = "\\\n" |
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.
Did we remove those constants and are using that hard coded now or they are not needed anymore?
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.
Previously the dateFormatter
was set using a dateFormat
provided in the NetworkLoogerPlugin's
init. Now we have to directly provide the DateFormatter
, which allow use to set it up using an hard coded dateFormat
, or Apple's dateStyle
and timeStyle
. The default value uses a short date and time style.
separator
and terminator
are now hardCoded in the default output method.
cURLTerminator
is no longer used.
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.
Nice @amaurydavid :))
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 looks nice 👍
Aside for a minor question, LGTM @sunshinejr @amaurydavid
@@ -0,0 +1,9 @@ | |||
# Migration Guide from 13.x to 14.x |
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.
💯
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.
@amaurydavid this looks awesome. Thank you for your time and patience on this one. I love the outcome and I can't wait to use it in the next Moya version 🚀
Following the discussion with @sunshinejr in #1880, here is a draft of a potential rework of the NetworkLoggerPlugin.
The issue we had was that response's body was only logged if we were in verbose mode. This means that if a request returns with an error, the error's body wasn't logged if not in verbose. It's ok if you don't want it, but it can be necessary according to your workflow. So we had to provide an option so that responses' bodies are logged in errors.
I could have used a simple enum
LogLevel { case error(showBodies: Bool), info, verbose }
but I wanted the user to fully customize the logs.So I came with the following idea: list all the components that can be logged in requests & responses, and allow the user to opt-in for each one.
That's the purpose of the new
RequestLoggingOptions
andResponseLoggingOptions
.And to handle the issue we were facing with bodies in errors, there are 2 sets of options for responses: the
successResponseLoggingOptions
will be used when the response returns as a success, anderrorResponseLoggingOptions
when it's an error. This way, we can configure the logger to log the error's body, but not success's.Additionnaly, I've moved all of the plugin's config into a....
Configuration
struct, making the Plugin more readable imo.So it's just a draft of the direction I want to go, It's not even tested and things may be broken atm.
But I want to have some feedback before spending some time on it: do you feel it may be a suitable rework for NetworkLoggerPlugin?