Add ability to suppress logging of known unsuccessful API calls (#5526)

This commit is contained in:
Paul Hawke 2024-02-08 15:55:56 -06:00 committed by GitHub
parent ba11f0d06e
commit c6cb97e199
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 46 additions and 3 deletions

View file

@ -43,7 +43,7 @@ class MediaDataExtractor @Inject constructor(private val mediaClient: MediaClien
return Single.ambArray( return Single.ambArray(
mediaClient.getMediaById(PAGE_ID_PREFIX + media.pageId) mediaClient.getMediaById(PAGE_ID_PREFIX + media.pageId)
.onErrorResumeNext { Single.never() }, .onErrorResumeNext { Single.never() },
mediaClient.getMedia(media.filename) mediaClient.getMediaSuppressingErrors(media.filename)
.onErrorResumeNext { Single.never() } .onErrorResumeNext { Single.never() }
) )

View file

@ -67,6 +67,8 @@ public final class OkHttpConnectionFactory {
} }
public static class UnsuccessfulResponseInterceptor implements Interceptor { public static class UnsuccessfulResponseInterceptor implements Interceptor {
private static final String SUPPRESS_ERROR_LOG = "x-commons-suppress-error-log";
public static final String SUPPRESS_ERROR_LOG_HEADER = SUPPRESS_ERROR_LOG+": true";
private static final List<String> DO_NOT_INTERCEPT = Collections.singletonList( private static final List<String> DO_NOT_INTERCEPT = Collections.singletonList(
"api.php?format=json&formatversion=2&errorformat=plaintext&action=upload&ignorewarnings=1"); "api.php?format=json&formatversion=2&errorformat=plaintext&action=upload&ignorewarnings=1");
@ -75,7 +77,16 @@ public final class OkHttpConnectionFactory {
@Override @Override
@NonNull @NonNull
public Response intercept(@NonNull final Chain chain) throws IOException { public Response intercept(@NonNull final Chain chain) throws IOException {
final Response rsp = chain.proceed(chain.request()); final Request rq = chain.request();
// If the request contains our special "suppress errors" header, make note of it
// but don't pass that on to the server.
final boolean suppressErrors = rq.headers().names().contains(SUPPRESS_ERROR_LOG);
final Request request = rq.newBuilder()
.removeHeader(SUPPRESS_ERROR_LOG)
.build();
final Response rsp = chain.proceed(request);
// Do not intercept certain requests and let the caller handle the errors // Do not intercept certain requests and let the caller handle the errors
if(isExcludedUrl(chain.request())) { if(isExcludedUrl(chain.request())) {
@ -89,7 +100,12 @@ public final class OkHttpConnectionFactory {
} }
} }
} catch (final IOException e) { } catch (final IOException e) {
Timber.e(e); // Log the error as debug (and therefore, "expected") or at error level
if (suppressErrors) {
Timber.d(e, "Suppressed (known / expected) error");
} else {
Timber.e(e);
}
} }
return rsp; return rsp;
} }

View file

@ -130,6 +130,17 @@ class MediaClient @Inject constructor(
.map { it.first() } .map { it.first() }
} }
/**
* Fetches Media object from the imageInfo API but suppress (known) errors
*
* @param titles the tiles to be searched for. Can be filename or template name
* @return
*/
fun getMediaSuppressingErrors(titles: String?): Single<Media> {
return responseMapper(mediaInterface.getMediaSuppressingErrors(titles))
.map { it.first() }
}
/** /**
* The method returns the picture of the day * The method returns the picture of the day
* *

View file

@ -1,9 +1,12 @@
package fr.free.nrw.commons.media; package fr.free.nrw.commons.media;
import static fr.free.nrw.commons.OkHttpConnectionFactory.UnsuccessfulResponseInterceptor.SUPPRESS_ERROR_LOG_HEADER;
import io.reactivex.Single; import io.reactivex.Single;
import java.util.Map; import java.util.Map;
import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse; import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse;
import retrofit2.http.GET; import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Query; import retrofit2.http.Query;
import retrofit2.http.QueryMap; import retrofit2.http.QueryMap;
@ -103,6 +106,17 @@ public interface MediaInterface {
MEDIA_PARAMS_WITH_CATEGORY_DETAILS) MEDIA_PARAMS_WITH_CATEGORY_DETAILS)
Single<MwQueryResponse> getMedia(@Query("titles") String title); Single<MwQueryResponse> getMedia(@Query("titles") String title);
/**
* Fetches Media object from the imageInfo API but suppress (known) errors
*
* @param title the tiles to be searched for. Can be filename or template name
* @return
*/
@GET("w/api.php?action=query&format=json&formatversion=2" +
MEDIA_PARAMS_WITH_CATEGORY_DETAILS)
@Headers(SUPPRESS_ERROR_LOG_HEADER)
Single<MwQueryResponse> getMediaSuppressingErrors(@Query("titles") String title);
/** /**
* Fetches Media object from the imageInfo API * Fetches Media object from the imageInfo API
* *
@ -111,6 +125,7 @@ public interface MediaInterface {
*/ */
@GET("w/api.php?action=query&format=json&formatversion=2" + @GET("w/api.php?action=query&format=json&formatversion=2" +
MEDIA_PARAMS) MEDIA_PARAMS)
@Headers(SUPPRESS_ERROR_LOG_HEADER)
Single<MwQueryResponse> getMediaById(@Query("pageids") String pageIds); Single<MwQueryResponse> getMediaById(@Query("pageids") String pageIds);
/** /**
@ -125,6 +140,7 @@ public interface MediaInterface {
Single<MwQueryResponse> getMediaWithGenerator(@Query("titles") String title); Single<MwQueryResponse> getMediaWithGenerator(@Query("titles") String title);
@GET("w/api.php?format=json&action=parse&prop=text") @GET("w/api.php?format=json&action=parse&prop=text")
@Headers(SUPPRESS_ERROR_LOG_HEADER)
Single<MwParseResponse> getPageHtml(@Query("page") String title); Single<MwParseResponse> getPageHtml(@Query("page") String title);
/** /**