-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add alternative cpu profiler for jvms without jfr
- Loading branch information
Showing
15 changed files
with
383 additions
and
253 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
...rc/main/java/com/splunk/opentelemetry/profiler/contextstorage/AbstractContextStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Copyright Splunk Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.splunk.opentelemetry.profiler.contextstorage; | ||
|
||
import io.opentelemetry.api.trace.Span; | ||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.context.ContextStorage; | ||
import io.opentelemetry.context.Scope; | ||
import javax.annotation.Nullable; | ||
|
||
abstract class AbstractContextStorage implements ContextStorage { | ||
|
||
private final ContextStorage delegate; | ||
private final ThreadLocal<Span> activeSpan = ThreadLocal.withInitial(Span::getInvalid); | ||
|
||
AbstractContextStorage(ContextStorage delegate) { | ||
this.delegate = delegate; | ||
} | ||
|
||
@Override | ||
public Scope attach(Context toAttach) { | ||
Scope delegatedScope = delegate.attach(toAttach); | ||
Span span = Span.fromContext(toAttach); | ||
Span current = activeSpan.get(); | ||
// do nothing when active span didn't change | ||
// do nothing if the span isn't sampled | ||
if (span == current || !span.getSpanContext().isSampled()) { | ||
return delegatedScope; | ||
} | ||
|
||
// mark new span as active and generate event | ||
activeSpan.set(span); | ||
activateSpan(span); | ||
return () -> { | ||
// restore previous active span | ||
activeSpan.set(current); | ||
activateSpan(current); | ||
delegatedScope.close(); | ||
}; | ||
} | ||
|
||
protected abstract void activateSpan(Span span); | ||
|
||
@Nullable | ||
@Override | ||
public Context current() { | ||
return delegate.current(); | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
...er/src/main/java/com/splunk/opentelemetry/profiler/contextstorage/JavaContextStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright Splunk Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.splunk.opentelemetry.profiler.contextstorage; | ||
|
||
import io.opentelemetry.api.trace.Span; | ||
import io.opentelemetry.api.trace.SpanContext; | ||
import io.opentelemetry.context.ContextStorage; | ||
import io.opentelemetry.instrumentation.api.internal.cache.Cache; | ||
|
||
// active context tracking for java profiler | ||
public class JavaContextStorage extends AbstractContextStorage { | ||
|
||
public static final Cache<Thread, SpanContext> activeContext = Cache.weak(); | ||
private static final Guard NOP = () -> {}; | ||
private static final BlockingGuard GUARD = new BlockingGuard(); | ||
private static volatile Guard guard = NOP; | ||
|
||
public JavaContextStorage(ContextStorage delegate) { | ||
super(delegate); | ||
} | ||
|
||
public static void block() { | ||
guard = GUARD; | ||
} | ||
|
||
public static void unblock() { | ||
guard = NOP; | ||
GUARD.release(); | ||
} | ||
|
||
@Override | ||
protected void activateSpan(Span span) { | ||
// when taking thread dump we block all thread that attempt to modify the active contexts | ||
guard.stop(); | ||
|
||
SpanContext context = span.getSpanContext(); | ||
if (context.isValid()) { | ||
activeContext.put(Thread.currentThread(), context); | ||
} else { | ||
activeContext.remove(Thread.currentThread()); | ||
} | ||
} | ||
|
||
private interface Guard { | ||
void stop(); | ||
} | ||
|
||
private static class BlockingGuard implements Guard { | ||
|
||
@Override | ||
public synchronized void stop() { | ||
try { | ||
while (guard == GUARD) { | ||
wait(); | ||
} | ||
} catch (InterruptedException exception) { | ||
Thread.currentThread().interrupt(); | ||
} | ||
} | ||
|
||
synchronized void release() { | ||
notifyAll(); | ||
} | ||
} | ||
} |
Oops, something went wrong.