[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17354118#comment-17354118 ] Marco Lotz edited comment on KAFKA-5676 at 5/30/21, 10:47 PM: -- [~mjsax] [~cadonna] I have spent a reasonable amount of time analysing this ticket. It seems to me that this is tightly coupled in many points (which also explains the fair amount of unmerged PRs related to it). Based on the previous comments, I found out the following in the code: * As [~chia7712] mentioned, if we keep the MockStreamsMetrics class and make it implement the interface, we would need to extend the interface (thus a KIP). Specially because the MockStreamsMetrics is used interchangeably with StreamsMetricsImpl class. The implementation has tons of extra public methods. Including static ones. There is a huge amount of test classes (20+) counting on StreamsMetricsImpl behaviours provided by MockStreamsMetrics. * If we go for removing MockStreamsMetrics and trying to mock StreamsMetricsImpl whenever it’s not truly needed: # One will find out that many methods in the class are final (which is not a limitation since PowerMock is available in Kafka project). But is a sign that it may require further design attention. Among them is {code:java} public final Sensor taskLevelSensor(...){code} # One will uncover that many static final methods are also called for StreamsMetricsImpl (that can also be solved by PowerMock). Among them is: {code:java} public static void StreamsMetricsImpl.addValueMetricToSensor(...){code} # One will find out that many test classes (e.g. StreamTaskTest or RecordCollectorTest) would require a considerable amount of behaviour mocking. Seems easily 20+ test classes would need considerable amount of mock configuration in this scenario. A possible solution is indeed making a mocking utils to init mocks of StreamsMetricsImpl - but again, it seems to me that there are enough code smells to indicate that something may need to be re-evaluated a bit further. With those points I believe that this ticket needs to be evaluated a bit more deeply - since it is likely connected to some considerable tech-debt (e.g. final methods mocking, inconsistencies on how the mocking of the metrics is performed, high coupling with implementation instead of interface, etc). Unfortunately I won’t be able to provide the amount fo rework/redesign that this ticket requires right now, maybe a core committer could eventually look into it if important? was (Author: marcolotz): [~mjsax] [~cadonna] I have spent a reasonable amount of time analysing this ticket. It seems to me that this is tightly coupled in many points (which also explains the fair amount of unmerged PRs related to it). Based on the previous comments, I found out the following in the code: * As [~chia7712] mentioned, if we keep the MockStreamsMetrics class and make it implement the interface, we would need to extend the interface (thus a KIP). Specially because the MockStreamsMetrics is used interchangeably with StreamsMetricsImpl class. The implementation has tons of extra public methods. Including static ones. There is a huge amount of test classes (20+) counting on StreamsMetricsImpl behaviours provided by MockStreamsMetrics. * If we go for removing MockStreamsMetrics and trying to mock StreamsMetricsImpl whenever it’s not truly needed: * One will find out that many methods in the class are final (which is not a limitation since PowerMock is available in Kafka project). But is a sign that it may require further design attention. Among them is {code:java} public final Sensor taskLevelSensor(...){code} * One will uncover that many static final methods are also called for StreamsMetricsImpl (that can also be solved by PowerMock). Among them is: {code:java} public static void StreamsMetricsImpl.addValueMetricToSensor(...){code} * One will find out that many test classes (e.g. StreamTaskTest or RecordCollectorTest) would require a considerable amount of behaviour mocking. Seems easily 20+ test classes would need considerable amount of mock configuration in this scenario. A possible solution is indeed making a mocking utils to init mocks of StreamsMetricsImpl - but again, it seems to me that there are enough code smells to indicate that something may need to be re-evaluated a bit further. With those points I believe that this ticket needs to be evaluated a bit more deeply - since it is likely connected to some considerable tech-debt (e.g. final methods mocking, inconsistencies on how the mocking of the metrics is performed, high coupling with implementation instead of interface, etc). Unfortunately I won’t be able to provide the amount fo rework/redesign that this ticket requires right now, maybe a core committer could eventually look into it if important? > MockStreamsMetrics shoul
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17350960#comment-17350960 ] Bruno Cadonna edited comment on KAFKA-5676 at 5/25/21, 10:42 AM: - [~marcolotz] Thank you for looking into this! The classes that use {{StreamsMetricsImpl}} should be only internal classes, like {{ClientMetrics}} that contains {{addStateMetrics()}}. They are allowed to use the implementation instead of the interface. The interface {{StreamsMetrics}} should be the one that is exposed in the public API. Currently, I do not recall why we need to move {{MockStreamsMetrics}} in the public API. IMO, we should get rid of {{MockStreamsMetrics}} and replace its usages with an EasyMock mock. However, I do not know whether this is straight forward. See also KAFKA-8977. was (Author: cadonna): [~marcolotz] Thank you for looking into this! The classes that use {{StreamsMetricsImpl}} should be only internal classes, like {{ClientMetrics}} that contains {{addStateMetrics()}}. They are allowed to use the implementation instead of the interface. The interface {{StreamsMetrics}} should be the one that is exposed in the public API. Currently, I do not recall why we need to move {{MockStreamsMetrics}} in the public API. IMO, we should get rid of {{MockStreamsMetrics}} and replace its usages with an EasyMock mock. However, I do not know whether this is straight forward. > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Marco Lotz >Priority: Major > Labels: newbie > Time Spent: 96h > Remaining Estimate: 0h > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17349475#comment-17349475 ] Marco Lotz edited comment on KAFKA-5676 at 5/21/21, 9:39 PM: - [~mjsax] [~guozhang] I can take over this ticket if nobody minds. I had a look at the code and indeed there's quite a problem of dependency inversion here. Tons of classes using behaviours only available in StreamsMetricsImpl instead of StreamsMetrics. Among the public behaviours not declared in the interface are: {code:java} Version version(); addClientLevelMutableMetric(); and many more{code} An example of calls that directly use the implementation is in ProcessorNodeMetrics#addStateMetric {code:java} public static void addStateMetric(final StreamsMetricsImpl streamsMetrics, final Gauge stateProvider) { streamsMetrics.addClientLevelMutableMetric( <--- This one is only available in the implementation STATE, STATE_DESCRIPTION, RecordingLevel.INFO, stateProvider ); } {code} It seems to me that the interface StreamMetrics is missing many behaviours. I can work on a PR to move those behaviours up to the interface and then we work together from there. Edit: Extra example, even interfaces are returning the implementation: {code:java} public interface InternalProcessorContext { ... @Override StreamsMetricsImpl metrics(); }{code} Edit 2: It seems to be many inconsistencies around, there are far more calls to {code:java} createMock(StreamsMetricsImpl.class);{code} and similar calls than uses of MockStreamsMetrics class. This will be likely a huge PR if this is really the goal. But then, seeing that there's only one implementation of the interface and the implementation has so many "extra" behaviours, the following question comes: is having interface segregation here the way to go? If it is, then we need to revisit the interface behaviours. If it's not, then maybe the interface should be dropped in favour to the single implementation. was (Author: marcolotz): [~mjsax] [~guozhang] I can take over this ticket if nobody minds. I had a look at the code and indeed there's quite a problem of dependency inversion here. Tons of classes using behaviours only available in StreamsMetricsImpl instead of StreamsMetrics. Among the public behaviours not declared in the interface are: {code:java} Version version(); addClientLevelMutableMetric(); and many more{code} An example of calls that directly use the implementation is in ProcessorNodeMetrics#addStateMetric {code:java} public static void addStateMetric(final StreamsMetricsImpl streamsMetrics, final Gauge stateProvider) { streamsMetrics.addClientLevelMutableMetric( <--- This one is only available in the implementation STATE, STATE_DESCRIPTION, RecordingLevel.INFO, stateProvider ); } {code} It seems to me that the interface StreamMetrics is missing many behaviours. I can work on a PR to move those behaviours up to the interface and then we work together from there. Edit: Extra example, even interfaces are returning the implementation: {code:java} public interface InternalProcessorContext { ... @Override StreamsMetricsImpl metrics(); }{code} > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Marco Lotz >Priority: Major > Labels: newbie > Time Spent: 96h > Remaining Estimate: 0h > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17349475#comment-17349475 ] Marco Lotz edited comment on KAFKA-5676 at 5/21/21, 9:04 PM: - [~mjsax] [~guozhang] I can take over this ticket if nobody minds. I had a look at the code and indeed there's quite a problem of dependency inversion here. Tons of classes using behaviours only available in StreamsMetricsImpl instead of StreamsMetrics. Among the public behaviours not declared in the interface are: {code:java} Version version(); addClientLevelMutableMetric(); and many more{code} An example of calls that directly use the implementation is in ProcessorNodeMetrics#addStateMetric {code:java} public static void addStateMetric(final StreamsMetricsImpl streamsMetrics, final Gauge stateProvider) { streamsMetrics.addClientLevelMutableMetric( <--- This one is only available in the implementation STATE, STATE_DESCRIPTION, RecordingLevel.INFO, stateProvider ); } {code} It seems to me that the interface StreamMetrics is missing many behaviours. I can work on a PR to move those behaviours up to the interface and then we work together from there. Edit: Extra example, even interfaces are returning the implementation: {code:java} public interface InternalProcessorContext { ... @Override StreamsMetricsImpl metrics(); }{code} was (Author: marcolotz): [~mjsax] [~guozhang] I can take over this ticket if nobody minds. I had a look at the code and indeed there's quite a problem of dependency inversion here. Tons of classes using behaviours only available in StreamsMetricsImpl instead of StreamsMetrics. Among the public behaviours not declared in the interface are: {code:java} Version version(); addClientLevelMutableMetric(); and many more{code} An example of calls that directly use the implementation is in ProcessorNodeMetrics#addStateMetric {code:java} public static void addStateMetric(final StreamsMetricsImpl streamsMetrics, final Gauge stateProvider) { streamsMetrics.addClientLevelMutableMetric( <--- This one is only available in the implementation STATE, STATE_DESCRIPTION, RecordingLevel.INFO, stateProvider ); } {code} It seems to me that the interface StreamMetrics is missing many behaviours. I can work on a PR to move those behaviours up to the interface and then we work together from there. > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Marco Lotz >Priority: Major > Labels: newbie > Time Spent: 96h > Remaining Estimate: 0h > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16120968#comment-16120968 ] Chanchal Singh edited comment on KAFKA-5676 at 8/11/17 12:22 PM: - also request you to let me know if there is any faster channel for communication other then jira. Created merge request but showing conflict of code changes with trunk . please look into it was (Author: chanchal.kafka): also request you to let me know if there is any faster channel for communication other then jira. > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Chanchal Singh > Labels: newbie > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16117994#comment-16117994 ] Chanchal Singh edited comment on KAFKA-5676 at 8/8/17 12:31 PM: Hi Wang , testMetrics() in StreamTaskTest class , ProcessorNodeTest class and NamedCacheTest class. ProcessorNodeTest uses MockStreamsMetrics object from MockProcessorContext. Please let me know if my understanding is correct. I have committed the code after removing metrics object parameter from MockStreamsMetrics constructor and referencing the StreamsMetricsImpl in classes where testMetrics() is used . was (Author: chanchal.kafka): Hi Wang , testMetrics() in StreamTaskTest class , ProcessorNodeTest class and NamedCacheTest class. ProcessorNodeTest uses MockStreamsMetrics object from MockProcessorContext. Please let me know if my understanding is correct. I have committed the code after removing metrics object parameter from MockStreamsMetrics constructor and referencing the StreamsMetricsImpl in classes where testMetrics() is used but still MockStreamsMetrics is extending StreamsMetricsImpl. > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Chanchal Singh > Labels: newbie > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16117994#comment-16117994 ] Chanchal Singh edited comment on KAFKA-5676 at 8/8/17 12:04 PM: Hi Wang , testMetrics() in StreamTaskTest class , ProcessorNodeTest class and NamedCacheTest class. ProcessorNodeTest uses MockStreamsMetrics object from MockProcessorContext. Please let me know if my understanding is correct. I have committed the code after removing metrics object parameter from MockStreamsMetrics constructor and referencing the StreamsMetricsImpl in classes where testMetrics() is used but still MockStreamsMetrics is extending StreamsMetricsImpl. was (Author: chanchal.kafka): Hi Wang , testMetrics() in StreamTaskTest class , ProcessorNodeTest class and NamedCacheTest class. ProcessorNodeTest uses MockStreamsMetrics object from MockProcessorContext. Please let me know if my understanding is correct. I have committed the code after removing metrics object parameter from MockStreamsMetrics constructor but still MockStreamsMetrics is extending StreamsMetricsImpl. > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Chanchal Singh > Labels: newbie > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16117994#comment-16117994 ] Chanchal Singh edited comment on KAFKA-5676 at 8/8/17 11:19 AM: Hi Wang , testMetrics() in StreamTaskTest class , ProcessorNodeTest class and NamedCacheTest class. ProcessorNodeTest uses MockStreamsMetrics object from MockProcessorContext. Please let me know if my understanding is correct. I have committed the code after removing metrics object parameter from MockStreamsMetrics constructor but still MockStreamsMetrics is extending StreamsMetricsImpl. was (Author: chanchal.kafka): Hi Wang , testMetrics() in StreamTaskTest class and ProcessorNodeTest class . ProcessorNodeTest uses MockStreamsMetrics object from MockProcessorContext. Please let me know if my understanding is correct. I have committed the code after removing metrics object parameter from MockStreamsMetrics constructor but still MockStreamsMetrics is extending StreamsMetricsImpl. > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Chanchal Singh > Labels: newbie > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16115860#comment-16115860 ] Chanchal Singh edited comment on KAFKA-5676 at 8/6/17 5:32 PM: --- Thanks Wang . I tried doing that but found that in few test cases they are dependent on Metrics object modified by StreamsMetricsImpl object and the value of Metrics object is then tested. I am confused about ,how MockStreamMetrics is acting as mock class if its not returning any mocking behaviour. Is there any difference in using StreamsMetricsImpl directly instead of MockStreamMetrics class in current case? was (Author: chanchal.kafka): Thanks Wang . I tried doing that but found that in few test cases they are dependent on Metrics object modified by StreamsMetricsImpl object and the value of Metrics object is then tested. I am also confused how MockStreamMetrics is acting as mock class ff its not returning any mocking behaviour. Is there any difference in using StreamsMetricsImpl directly instead of MockStreamMetrics class in current case? > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Chanchal Singh > Labels: newbie > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Comment Edited] (KAFKA-5676) MockStreamsMetrics should be in o.a.k.test
[ https://issues.apache.org/jira/browse/KAFKA-5676?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16115860#comment-16115860 ] Chanchal Singh edited comment on KAFKA-5676 at 8/6/17 5:27 PM: --- Thanks Wang . I tried doing that but found that in few test cases they are dependent on Metrics object modified by StreamsMetricsImpl object and the value of Metrics object is then tested. I am also confused how MockStreamMetrics is acting as mock class ff its not returning any mocking behaviour. Is there any difference in using StreamsMetricsImpl directly instead of MockStreamMetrics class in current case? was (Author: chanchal.kafka): Thanks Wang . I tried doing that but found that in few test cases they are dependent on Metrics object modified by StreamsMetricsImpl object and the value of Metrics object is then tested. I am also confused how MockStreamMetrics is acting as mock class ff its not returning any mocking behaviour. Is there any difference in using StreamsMetricsImpl directly instead of MockStreamMetrics class ? > MockStreamsMetrics should be in o.a.k.test > -- > > Key: KAFKA-5676 > URL: https://issues.apache.org/jira/browse/KAFKA-5676 > Project: Kafka > Issue Type: Bug > Components: streams >Reporter: Guozhang Wang >Assignee: Chanchal Singh > Labels: newbie > > {{MockStreamsMetrics}}'s package should be `o.a.k.test` not > `o.a.k.streams.processor.internals`. > In addition, it should not require a {{Metrics}} parameter in its constructor > as it is only needed for its extended base class; the right way of mocking > should be implementing {{StreamsMetrics}} with mock behavior than extended a > real implementaion of {{StreamsMetricsImpl}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)