Skip to content

[Feature] Support collecting database connection pool metric,support dbcp2/druid/hikari#96

Merged
wu-sheng merged 27 commits intoapache:mainfrom
sunOnly:main
Feb 11, 2022
Merged

[Feature] Support collecting database connection pool metric,support dbcp2/druid/hikari#96
wu-sheng merged 27 commits intoapache:mainfrom
sunOnly:main

Conversation

@sunOnly
Copy link
Copy Markdown
Contributor

@sunOnly sunOnly commented Jan 24, 2022

  • If this pull request closes/resolves/fixes an existing issue, replace the issue number. Closes #.
  • Update the CHANGES log.

@wu-sheng
Copy link
Copy Markdown
Member

Please follow the discussion starting from #95 (comment).

Don't build the register mechanism. This is not a good practice.

Also, follow this, #95 (comment), meter plugin test is required like the trace plugin test.

@wu-sheng
Copy link
Copy Markdown
Member

Are you going to update this PR? No update for 3 days.

sunOnly and others added 5 commits January 28, 2022 10:21
[Feature] Support collecting database connection pool metric,support
druid/hikari/dbcp2#8450
:wq
Merge branch 'main' of github.com:sunOnly/skywalking-java into main
@wu-sheng
Copy link
Copy Markdown
Member

Please fix CI and follow the comments. Then, you need to add plugin tests.

@lujiajing1126
Copy link
Copy Markdown
Contributor

Additionally for HikariCP, they have some extra metrics at runtime,

https://github.com/brettwooldridge/HikariCP/blob/dev/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java

Are you going to consider these?

@wu-sheng
Copy link
Copy Markdown
Member

The other undertow thread pool PR has been merged. You could take a reference.

@wu-sheng
Copy link
Copy Markdown
Member

wu-sheng commented Feb 7, 2022

@sunOnly Are you going to continue on this?

@sunOnly
Copy link
Copy Markdown
Contributor Author

sunOnly commented Feb 7, 2022

@sunOnly Are you going to continue on this?
Yes

@wu-sheng
Copy link
Copy Markdown
Member

wu-sheng commented Feb 7, 2022

Thanks for the feedback.

new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("setUrl");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just a final comment:

As I've stated before, we have to be careful with the interceptor points for Alibaba/Druid and HikariCP. But I'am not quite familiar with this dbcp2 DataSource.

So, could you please justify the choice of this interceptor point?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@sunOnly First of all, good to see the tests passed. Let's follow this one. #setUrl is not a good point to begin the monitoring, because in the runtime, a datasource could be not-created at this moment, even never(code bug).

I was looking through the codes, it is likely createDataSource is a better method to begin all metrics registration and reporting. Meanwhile, I understand you intercept #setUrl is to get the URL parameter, I noticed there is getUrl method in the class, but with a synchronized, which I have concerns about deadlock. So, it is better you keep this setUrl method intercepting, but keep the value of URL into the EnhancedInstance#setSkyWalkingDynamicField. Then in new createDataSource interceptor, you could use #getSkyWalkingDynamicField to read this.

This would be more robust.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@sunOnly First of all, good to see the tests passed. Let's follow this one. #setUrl is not a good point to begin the monitoring, because in the runtime, a datasource could be not-created at this moment, even never(code bug).

I was looking through the codes, it is likely createDataSource is a better method to begin all metrics registration and reporting. Meanwhile, I understand you intercept #setUrl is to get the URL parameter, I noticed there is getUrl method in the class, but with a synchronized, which I have concerns about deadlock. So, it is better you keep this setUrl method intercepting, but keep the value of URL into the EnhancedInstance#setSkyWalkingDynamicField. Then in new createDataSource interceptor, you could use #getSkyWalkingDynamicField to read this.

This would be more robust.
get

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was looking through the codes, it is likely createDataSource is a better method to begin all metrics registration and reporting. Meanwhile, I understand you intercept #setUrl is to get the URL parameter, I noticed there is getUrl method in the class, but with a synchronized, which I have concerns about deadlock. So, it is better you keep this setUrl method intercepting, but keep the value of URL into the EnhancedInstance#setSkyWalkingDynamicField. Then in new createDataSource interceptor, you could use #getSkyWalkingDynamicField to read this.

What about using jmxRegister() called within createDataSource() (if dataSource is not created) as the interception point?

Since every call to getConnection() will invoke createDataSource(), the performance may be impacted. It also exists from 2.0.1 to 2.9.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since every call to getConnection() will invoke createDataSource()

Really? This doesn't seem reasonable.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about using jmxRegister() called within createDataSource() (if dataSource is not created) as the interception point?

@sunOnly Could you try this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since every call to getConnection() will invoke createDataSource()

Really? This doesn't seem reasonable.

https://github.com/apache/commons-dbcp/blob/466091e51d875d2a4499adbbb63058e32ad5a7c7/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java#L732

Seems so.

@wu-sheng
Copy link
Copy Markdown
Member

wu-sheng commented Feb 9, 2022

It seems one changed case still fails.

@wu-sheng wu-sheng added feature and removed enhancement New feature or request labels Feb 11, 2022
@wu-sheng
Copy link
Copy Markdown
Member

Another question, I noticed in the commit log, there are 2 ID, one is @sunOnly (GitHub), the other is xiaojianjun. Are these belong to the same person?

@sunOnly
Copy link
Copy Markdown
Contributor Author

sunOnly commented Feb 11, 2022

Another question, I noticed in the commit log, there are 2 ID, one is @sunOnly (GitHub), the other is xiaojianjun. Are these belong to the same person?

It's the same person

@wu-sheng
Copy link
Copy Markdown
Member

Please follow the comment above, there is one more todo.

Comment thread test/plugin/pom.xml
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
<sourceDirectory>${project.build.testSourceDirectory}</sourceDirectory>
<sourceDirectory>scenarios/dbcp-2.x-scenario</sourceDirectory>
<sourceDirectory>scenarios/druid-1.x-scenario</sourceDirectory>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please remove these declare, this should be generated by CI.

@wu-sheng
Copy link
Copy Markdown
Member

@lujiajing1126 Please recheck.

wu-sheng
wu-sheng previously approved these changes Feb 11, 2022
Copy link
Copy Markdown
Member

@wu-sheng wu-sheng left a comment

Choose a reason for hiding this comment

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

Once tests pass, I am good.

public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
ConnectionInfo connectionInfo = URLParser.parser((String) allArguments[0]);
String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer();
if (tagValue != null) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As I understood, it could not be null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As I understood, it could not be null?

The external call may be set to null

As I understood, it could not be null?
change to
if (allArguments[0] != null) {
ConnectionInfo connectionInfo = URLParser.parser((String) allArguments[0]);
String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer();
objInst.setSkyWalkingDynamicField(tagValue);
}

Copy link
Copy Markdown
Member

@wu-sheng wu-sheng Feb 11, 2022

Choose a reason for hiding this comment

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

I think he means _ is in the string combining. So, it can't be null.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think he means _ is in the string combining. So, it can't be null.

Exactly.

new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("setUrl");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was looking through the codes, it is likely createDataSource is a better method to begin all metrics registration and reporting. Meanwhile, I understand you intercept #setUrl is to get the URL parameter, I noticed there is getUrl method in the class, but with a synchronized, which I have concerns about deadlock. So, it is better you keep this setUrl method intercepting, but keep the value of URL into the EnhancedInstance#setSkyWalkingDynamicField. Then in new createDataSource interceptor, you could use #getSkyWalkingDynamicField to read this.

What about using jmxRegister() called within createDataSource() (if dataSource is not created) as the interception point?

Since every call to getConnection() will invoke createDataSource(), the performance may be impacted. It also exists from 2.0.1 to 2.9.0.

@lujiajing1126
Copy link
Copy Markdown
Contributor

lujiajing1126 commented Feb 11, 2022

I'm good with the last version. Let's wait for the CI.

Copy link
Copy Markdown
Contributor

@lujiajing1126 lujiajing1126 left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for your patience!

@wu-sheng wu-sheng merged commit 00cf97e into apache:main Feb 11, 2022
GuoHaoZai pushed a commit to GuoHaoZai/skywalking-java that referenced this pull request Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants