Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.sentry.core.EnvelopeSender Maven / Gradle / Ivy
package io.sentry.core;
import static io.sentry.core.SentryLevel.ERROR;
import static io.sentry.core.cache.SessionCache.PREFIX_CURRENT_SESSION_FILE;
import io.sentry.core.hints.Flushable;
import io.sentry.core.hints.Retryable;
import io.sentry.core.hints.SubmissionResult;
import io.sentry.core.util.CollectionUtils;
import io.sentry.core.util.LogUtils;
import io.sentry.core.util.Objects;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ApiStatus.Internal
public final class EnvelopeSender extends DirectoryProcessor implements IEnvelopeSender {
@SuppressWarnings("CharsetObjectCanBeUsed")
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final @NotNull IHub hub;
private final @NotNull IEnvelopeReader envelopeReader;
private final @NotNull ISerializer serializer;
private final @NotNull ILogger logger;
public EnvelopeSender(
final @NotNull IHub hub,
final @NotNull IEnvelopeReader envelopeReader,
final @NotNull ISerializer serializer,
final @NotNull ILogger logger,
final long flushTimeoutMillis) {
super(logger, flushTimeoutMillis);
this.hub = Objects.requireNonNull(hub, "Hub is required.");
this.envelopeReader = Objects.requireNonNull(envelopeReader, "Envelope reader is required.");
this.serializer = Objects.requireNonNull(serializer, "Serializer is required.");
this.logger = Objects.requireNonNull(logger, "Logger is required.");
}
@Override
protected void processFile(final @NotNull File file, @Nullable Object hint) {
Objects.requireNonNull(file, "File is required.");
if (!isRelevantFileName(file.getName())) {
logger.log(SentryLevel.DEBUG, "File '%s' should be ignored.", file.getAbsolutePath());
return;
}
try (final InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
final SentryEnvelope envelope = envelopeReader.read(stream);
if (envelope == null) {
logger.log(
SentryLevel.ERROR,
"Stream from path %s resulted in a null envelope.",
file.getAbsolutePath());
} else {
processEnvelope(envelope, hint);
logger.log(SentryLevel.DEBUG, "File '%s' is done.", file.getAbsolutePath());
}
} catch (IOException e) {
logger.log(SentryLevel.ERROR, "Error processing envelope.", e);
} finally {
if (hint instanceof Retryable) {
if (!((Retryable) hint).isRetry()) {
try {
if (!file.delete()) {
logger.log(SentryLevel.ERROR, "Failed to delete: %s", file.getAbsolutePath());
}
} catch (RuntimeException e) {
logger.log(SentryLevel.ERROR, e, "Failed to delete: %s", file.getAbsolutePath());
}
}
} else {
LogUtils.logIfNotRetryable(logger, hint);
}
}
}
@Override
protected boolean isRelevantFileName(final @Nullable String fileName) {
// ignore current.envelope
return fileName != null && !fileName.startsWith(PREFIX_CURRENT_SESSION_FILE);
// TODO: Use an extension to filter out relevant files
}
@Override
public void processEnvelopeFile(@NotNull String path, @Nullable Object hint) {
Objects.requireNonNull(path, "Path is required.");
processFile(new File(path), hint);
}
private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Nullable Object hint)
throws IOException {
logger.log(
SentryLevel.DEBUG,
"Processing Envelope with %d item(s)",
CollectionUtils.size(envelope.getItems()));
int items = 0;
for (final SentryEnvelopeItem item : envelope.getItems()) {
items++;
if (item.getHeader() == null) {
logger.log(SentryLevel.ERROR, "Item %d has no header", items);
continue;
}
if (SentryItemType.Event.equals(item.getHeader().getType())) {
try (final Reader eventReader =
new BufferedReader(
new InputStreamReader(new ByteArrayInputStream(item.getData()), UTF_8))) {
SentryEvent event = serializer.deserializeEvent(eventReader);
if (event == null) {
logger.log(
SentryLevel.ERROR,
"Item %d of type %s returned null by the parser.",
items,
item.getHeader().getType());
} else {
if (envelope.getHeader().getEventId() != null
&& !envelope.getHeader().getEventId().equals(event.getEventId())) {
logger.log(
SentryLevel.ERROR,
"Item %d of has a different event id (%s) to the envelope header (%s)",
items,
envelope.getHeader().getEventId(),
event.getEventId());
continue;
}
hub.captureEvent(event, hint);
logger.log(SentryLevel.DEBUG, "Item %d is being captured.", items);
if (hint instanceof Flushable) {
if (!((Flushable) hint).waitFlush()) {
logger.log(
SentryLevel.WARNING,
"Timed out waiting for event submission: %s",
event.getEventId());
// TODO: find out about the time out
// if (hint instanceof Retryable) {
// ((Retryable) hint).setRetry(true);
// }
break;
}
} else {
LogUtils.logIfNotFlushable(logger, hint);
}
}
} catch (Exception e) {
logger.log(ERROR, "Item failed to process.", e);
}
} else if (SentryItemType.Session.equals(item.getHeader().getType())) {
try (final Reader reader =
new BufferedReader(
new InputStreamReader(new ByteArrayInputStream(item.getData()), UTF_8))) {
final Session session = serializer.deserializeSession(reader);
if (session == null) {
logger.log(
SentryLevel.ERROR,
"Item %d of type %s returned null by the parser.",
items,
item.getHeader().getType());
} else {
// TODO: Bundle all session in a single envelope
hub.captureEnvelope(SentryEnvelope.fromSession(serializer, session), hint);
logger.log(SentryLevel.DEBUG, "Item %d is being captured.", items);
if (hint instanceof Flushable) {
logger.log(SentryLevel.DEBUG, "Going to wait flush %d item.", items);
if (!((Flushable) hint).waitFlush()) {
logger.log(
SentryLevel.WARNING,
"Timed out waiting for item submission: %s",
session.getSessionId());
// TODO: find out about the time out
// if (hint instanceof Retryable) {
// ((Retryable) hint).setRetry(true);
// }
break;
}
logger.log(SentryLevel.DEBUG, "Flushed %d item.", items);
} else {
LogUtils.logIfNotFlushable(logger, hint);
}
}
} catch (Exception e) {
logger.log(ERROR, "Item failed to process.", e);
}
} else {
// TODO: Handle attachments and other types
logger.log(
SentryLevel.WARNING, "Item %d of type: %s ignored.", items, item.getHeader().getType());
}
if (hint instanceof SubmissionResult) {
if (!((SubmissionResult) hint).isSuccess()) {
// Failed to send an item of the envelope: Stop attempting to send the rest (an attachment
// without the event that created it isn't useful)
logger.log(
SentryLevel.WARNING,
"Envelope had a failed capture at item %d. No more items will be sent.",
items);
break;
}
} else {
LogUtils.logIfNotSubmissionResult(logger, hint);
}
}
}
}