forked from getsentry/sentry-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnvelopeSender.java
More file actions
139 lines (126 loc) · 4.5 KB
/
EnvelopeSender.java
File metadata and controls
139 lines (126 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package io.sentry;
import io.sentry.cache.EnvelopeCache;
import io.sentry.hints.Flushable;
import io.sentry.hints.Retryable;
import io.sentry.util.HintUtils;
import io.sentry.util.Objects;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ApiStatus.Internal
public final class EnvelopeSender extends DirectoryProcessor implements IEnvelopeSender {
private final @NotNull IHub hub;
private final @NotNull ISerializer serializer;
private final @NotNull ILogger logger;
public EnvelopeSender(
final @NotNull IHub hub,
final @NotNull ISerializer serializer,
final @NotNull ILogger logger,
final long flushTimeoutMillis) {
super(logger, flushTimeoutMillis);
this.hub = Objects.requireNonNull(hub, "Hub 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, final @NotNull Hint hint) {
if (!file.isFile()) {
logger.log(SentryLevel.DEBUG, "'%s' is not a file.", file.getAbsolutePath());
return;
}
if (!isRelevantFileName(file.getName())) {
logger.log(
SentryLevel.DEBUG, "File '%s' doesn't match extension expected.", file.getAbsolutePath());
return;
}
if (!file.getParentFile().canWrite()) {
logger.log(
SentryLevel.WARNING,
"File '%s' cannot be deleted so it will not be processed.",
file.getAbsolutePath());
return;
}
try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) {
SentryEnvelope envelope = serializer.deserializeEnvelope(is);
if (envelope == null) {
logger.log(
SentryLevel.ERROR, "Failed to deserialize cached envelope %s", file.getAbsolutePath());
} else {
hub.captureEnvelope(envelope, hint);
}
HintUtils.runIfHasTypeLogIfNot(
hint,
Flushable.class,
logger,
(flushable) -> {
if (!flushable.waitFlush()) {
logger.log(SentryLevel.WARNING, "Timed out waiting for envelope submission.");
}
});
} catch (FileNotFoundException e) {
logger.log(SentryLevel.ERROR, e, "File '%s' cannot be found.", file.getAbsolutePath());
} catch (IOException e) {
logger.log(SentryLevel.ERROR, e, "I/O on file '%s' failed.", file.getAbsolutePath());
} catch (Throwable e) {
logger.log(
SentryLevel.ERROR, e, "Failed to capture cached envelope %s", file.getAbsolutePath());
HintUtils.runIfHasTypeLogIfNot(
hint,
Retryable.class,
logger,
(retryable) -> {
retryable.setRetry(false);
logger.log(SentryLevel.INFO, e, "File '%s' won't retry.", file.getAbsolutePath());
});
} finally {
// Unless the transport marked this to be retried, it'll be deleted.
HintUtils.runIfHasTypeLogIfNot(
hint,
Retryable.class,
logger,
(retryable) -> {
if (!retryable.isRetry()) {
safeDelete(file, "after trying to capture it");
logger.log(SentryLevel.DEBUG, "Deleted file %s.", file.getAbsolutePath());
} else {
logger.log(
SentryLevel.INFO,
"File not deleted since retry was marked. %s.",
file.getAbsolutePath());
}
});
}
}
@Override
protected boolean isRelevantFileName(final @NotNull String fileName) {
return fileName.endsWith(EnvelopeCache.SUFFIX_ENVELOPE_FILE);
}
@Override
public void processEnvelopeFile(final @NotNull String path, final @NotNull Hint hint) {
Objects.requireNonNull(path, "Path is required.");
processFile(new File(path), hint);
}
private void safeDelete(final @NotNull File file, final @NotNull String errorMessageSuffix) {
try {
if (!file.delete()) {
logger.log(
SentryLevel.ERROR,
"Failed to delete '%s' %s",
file.getAbsolutePath(),
errorMessageSuffix);
}
} catch (Throwable e) {
logger.log(
SentryLevel.ERROR,
e,
"Failed to delete '%s' %s",
file.getAbsolutePath(),
errorMessageSuffix);
}
}
}