Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
<immutables.version>2.8.3</immutables.version>
<powermock.version>2.0.2</powermock.version>
<objenesis.version>3.0.1</objenesis.version>
<opencensus.version>0.26.0</opencensus.version>

<shade.id>${project.groupId}.githubclient.shade</shade.id>
</properties>
Expand Down Expand Up @@ -170,6 +171,11 @@
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-api</artifactId>
<version>${opencensus.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
Expand Down Expand Up @@ -218,6 +224,18 @@
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-testing</artifactId>
<version>${opencensus.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl</artifactId>
<version>${opencensus.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/spotify/github/Span.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*-
* -\-\-
* github-api
* --
* Copyright (C) 2021 Spotify AB
* --
* 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.spotify.github;

public interface Span extends AutoCloseable {

Span success();

Span failure(Throwable t);

/** Close span. Must be called for any opened span. */
@Override
void close();
}

32 changes: 32 additions & 0 deletions src/main/java/com/spotify/github/Tracer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*-
* -\-\-
* github-api
* --
* Copyright (C) 2021 Spotify AB
* --
* 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.spotify.github;

import java.util.concurrent.CompletionStage;

public interface Tracer {

/** Create scoped span. Span will be closed when future completes. */
Span span(
String path, String method, CompletionStage<?> future);

}

63 changes: 63 additions & 0 deletions src/main/java/com/spotify/github/opencensus/OpenCensusSpan.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*-
* -\-\-
* github-api
* --
* Copyright (C) 2016 - 2021 Spotify AB
* --
* 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.spotify.github.opencensus;
import static java.util.Objects.requireNonNull;
import com.spotify.github.Span;
import com.spotify.github.v3.exceptions.RequestNotOkException;
import io.opencensus.trace.AttributeValue;
import io.opencensus.trace.Status;

class OpenCensusSpan implements Span {

public static final int NOT_FOUND = 404;
public static final int INTERNAL_SERVER_ERROR = 500;
private final io.opencensus.trace.Span span;

OpenCensusSpan(final io.opencensus.trace.Span span) {
this.span = requireNonNull(span);
}

@Override
public Span success() {
span.setStatus(Status.OK);
return this;
}

@Override
public Span failure(final Throwable t) {
if (t instanceof RequestNotOkException) {
RequestNotOkException ex = (RequestNotOkException) t;
span.putAttribute("http.status_code", AttributeValue.longAttributeValue(ex.statusCode()));
span.putAttribute("message", AttributeValue.stringAttributeValue(ex.getMessage()));
if (ex.statusCode() - INTERNAL_SERVER_ERROR >= 0) {
span.putAttribute("error", AttributeValue.booleanAttributeValue(true));
}
}
span.setStatus(Status.UNKNOWN);
return this;
}

@Override
public void close() {
span.end();
}
}

71 changes: 71 additions & 0 deletions src/main/java/com/spotify/github/opencensus/OpenCensusTracer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*-
* -\-\-
* github-api
* --
* Copyright (C) 2021 Spotify AB
* --
* 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.spotify.github.opencensus;

import com.spotify.github.Span;
import com.spotify.github.Tracer;
import io.opencensus.trace.Tracing;

import java.util.concurrent.CompletionStage;

import static io.opencensus.trace.AttributeValue.stringAttributeValue;
import static io.opencensus.trace.Span.Kind.CLIENT;
import static java.util.Objects.requireNonNull;

public class OpenCensusTracer implements Tracer {

private static final io.opencensus.trace.Tracer TRACER = Tracing.getTracer();

@Override
public Span span(final String name, final String method, final CompletionStage<?> future) {
return internalSpan(name, method, future);
}

@SuppressWarnings("MustBeClosedChecker")
private Span internalSpan(
final String path,
final String method,
final CompletionStage<?> future) {
requireNonNull(path);
requireNonNull(future);

final io.opencensus.trace.Span ocSpan =
TRACER.spanBuilder("GitHub Request").setSpanKind(CLIENT).startSpan();

ocSpan.putAttribute("component", stringAttributeValue("github-api-client"));
ocSpan.putAttribute("peer.service", stringAttributeValue("github"));
ocSpan.putAttribute("http.url", stringAttributeValue(path));
ocSpan.putAttribute("method", stringAttributeValue(method));
final Span span = new OpenCensusSpan(ocSpan);

future.whenComplete(
(result, t) -> {
if (t == null) {
span.success();
} else {
span.failure(t);
}
span.close();
});

return span;
}
}
10 changes: 9 additions & 1 deletion src/main/java/com/spotify/github/v3/clients/GitHubClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static okhttp3.MediaType.parse;

import com.fasterxml.jackson.core.type.TypeReference;
import com.spotify.github.Tracer;
import com.spotify.github.jackson.Json;
import com.spotify.github.v3.checks.AccessToken;
import com.spotify.github.v3.comment.Comment;
Expand Down Expand Up @@ -65,6 +66,8 @@
*/
public class GitHubClient {

private Tracer tracer = NoopTracer.INSTANCE;

static final Consumer<Response> IGNORE_RESPONSE_CONSUMER = (response) -> {
if (response.body() != null) {
response.body().close();
Expand Down Expand Up @@ -300,6 +303,11 @@ static String responseBodyUnchecked(final Response response) {
}
}

public GitHubClient withTracer(final Tracer tracer) {
this.tracer = tracer;
return this;
}

public Optional<byte[]> getPrivateKey() {
return Optional.ofNullable(privateKey);
}
Expand Down Expand Up @@ -724,7 +732,7 @@ public void onResponse(final Call call, final Response response) {
});
}
});

tracer.span(request.url().toString(), request.method(), future);
return future;
}

Expand Down
57 changes: 57 additions & 0 deletions src/main/java/com/spotify/github/v3/clients/NoopTracer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*-
* -\-\-
* github-api
* --
* Copyright (C) 2021 Spotify AB
* --
* 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.spotify.github.v3.clients;
import com.spotify.github.Span;
import com.spotify.github.Tracer;

import java.util.concurrent.CompletionStage;

public class NoopTracer implements Tracer {

public static final NoopTracer INSTANCE = new NoopTracer();
private static final Span SPAN =
new Span() {
@Override
public Span success() {
return this;
}

@Override
public Span failure(final Throwable t) {
return this;
}

@Override
public void close() {}
};

private NoopTracer() {}

@Override
public Span span(
final String path,
final String method,
final CompletionStage<?> future) {
return SPAN;
}

}

Loading