@goliapkg/sentori-react-native 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/handlers/network.d.ts.map +1 -1
- package/lib/handlers/network.js +11 -0
- package/lib/handlers/network.js.map +1 -1
- package/lib/transport.d.ts +1 -0
- package/lib/transport.d.ts.map +1 -1
- package/lib/transport.js +50 -0
- package/lib/transport.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/transport.test.ts +77 -0
- package/src/handlers/network.ts +10 -0
- package/src/transport.ts +52 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/handlers/network.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/handlers/network.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,qBAAqB,QAAO,IAKxC,CAAC"}
|
package/lib/handlers/network.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { startSpan } from '@goliapkg/sentori-core';
|
|
2
2
|
import { addBreadcrumb } from '../breadcrumbs';
|
|
3
|
+
import { getConfig } from '../config';
|
|
3
4
|
let _installed = false;
|
|
4
5
|
const AUTH_PARAMS = ['token', 'key', 'password', 'secret', 'access_token'];
|
|
6
|
+
// Requests to our own ingest endpoint shouldn't be traced — otherwise
|
|
7
|
+
// every span upload spawns another http.client span, and so on.
|
|
8
|
+
const isIngestUrl = (url) => {
|
|
9
|
+
const base = getConfig()?.ingestUrl;
|
|
10
|
+
return !!base && url.startsWith(base);
|
|
11
|
+
};
|
|
5
12
|
export const installNetworkHandler = () => {
|
|
6
13
|
if (_installed)
|
|
7
14
|
return;
|
|
@@ -17,6 +24,8 @@ function patchFetch() {
|
|
|
17
24
|
globalThis.fetch = (async (input, init) => {
|
|
18
25
|
const start = Date.now();
|
|
19
26
|
const url = extractUrl(input);
|
|
27
|
+
if (isIngestUrl(url))
|
|
28
|
+
return original(input, init);
|
|
20
29
|
const scrubbed = scrubUrl(url);
|
|
21
30
|
const method = (init?.method ??
|
|
22
31
|
(typeof input !== 'string' && 'method' in input
|
|
@@ -87,6 +96,8 @@ function patchXhr() {
|
|
|
87
96
|
return originalOpen.call(this, method, url, ...rest);
|
|
88
97
|
};
|
|
89
98
|
proto.send = function (body) {
|
|
99
|
+
if (isIngestUrl(this.__sentoriUrl ?? ''))
|
|
100
|
+
return originalSend.call(this, body);
|
|
90
101
|
const method = this.__sentoriMethod ?? 'GET';
|
|
91
102
|
const url = scrubUrl(this.__sentoriUrl ?? '');
|
|
92
103
|
const span = startSpan('http.client', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/handlers/network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/handlers/network.ts"],"names":[],"mappings":"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"}
|
package/lib/transport.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Event } from './types';
|
|
2
2
|
export declare const enqueue: (event: Event) => void;
|
|
3
3
|
export declare const startTransport: () => void;
|
|
4
|
+
export declare const flushSpans: () => Promise<void>;
|
|
4
5
|
export declare const flush: () => Promise<void>;
|
|
5
6
|
export declare const drainOfflineQueue: () => Promise<void>;
|
|
6
7
|
export declare const __resetForTests: () => void;
|
package/lib/transport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAqBrC,eAAO,MAAM,OAAO,GAAI,OAAO,KAAK,KAAG,IAUtC,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,IAOjC,CAAC;AAEF,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,IAAI,CAe/C,CAAC;AAqBF,eAAO,MAAM,KAAK,QAAa,OAAO,CAAC,IAAI,CAkB1C,CAAC;AA4FF,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,IAAI,CAatD,CAAC;AAEF,eAAO,MAAM,eAAe,QAAO,IAOlC,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,SAAS,KAAK,EAAY,CAAC;AAE1D;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,WAAW,MAAM,EACjB,OAAO,MAAM,EACb,MAAM,OAAO,KACZ,OAAO,CAAC,IAAI,CAcd,CAAC"}
|
package/lib/transport.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
import { drainSpans } from '@goliapkg/sentori-core';
|
|
1
2
|
import { getConfig } from './config';
|
|
2
3
|
const FLUSH_INTERVAL_MS = 5_000;
|
|
3
4
|
const BATCH_SIZE = 10;
|
|
4
5
|
const MAX_RETRY = 3;
|
|
5
6
|
const STORAGE_KEY = '@sentori/pending';
|
|
6
7
|
const MAX_PERSISTED = 1000;
|
|
8
|
+
// Spans are higher-volume and lower-value than error events: we batch
|
|
9
|
+
// them on their own timer, cap each request at the server's per-batch
|
|
10
|
+
// limit, and drop on failure rather than persisting offline.
|
|
11
|
+
const SPAN_FLUSH_INTERVAL_MS = 10_000;
|
|
12
|
+
const SPAN_BATCH_MAX = 200;
|
|
7
13
|
let _queue = [];
|
|
8
14
|
let _flushTimer = null;
|
|
15
|
+
let _spanTimer = null;
|
|
9
16
|
let _started = false;
|
|
10
17
|
const SDK_VERSION = '0.0.0';
|
|
11
18
|
export const enqueue = (event) => {
|
|
@@ -22,6 +29,46 @@ export const enqueue = (event) => {
|
|
|
22
29
|
};
|
|
23
30
|
export const startTransport = () => {
|
|
24
31
|
_started = true;
|
|
32
|
+
if (!_spanTimer) {
|
|
33
|
+
_spanTimer = setInterval(() => {
|
|
34
|
+
void flushSpans();
|
|
35
|
+
}, SPAN_FLUSH_INTERVAL_MS);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
export const flushSpans = async () => {
|
|
39
|
+
if (!_started)
|
|
40
|
+
return;
|
|
41
|
+
const spans = drainSpans();
|
|
42
|
+
if (spans.length === 0)
|
|
43
|
+
return;
|
|
44
|
+
const config = getConfig();
|
|
45
|
+
if (!config)
|
|
46
|
+
return;
|
|
47
|
+
for (let i = 0; i < spans.length; i += SPAN_BATCH_MAX) {
|
|
48
|
+
const chunk = spans.slice(i, i + SPAN_BATCH_MAX);
|
|
49
|
+
try {
|
|
50
|
+
await sendSpansOnce(chunk, config.ingestUrl, config.token);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// drop the remaining chunks — span uploads aren't worth retrying
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const sendSpansOnce = async (spans, ingestUrl, token) => {
|
|
59
|
+
const resp = await fetch(`${ingestUrl}/v1/spans:batch`, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: {
|
|
62
|
+
'Content-Type': 'application/json',
|
|
63
|
+
Authorization: `Bearer ${token}`,
|
|
64
|
+
'Sentori-Sdk': `react-native/${SDK_VERSION}`,
|
|
65
|
+
},
|
|
66
|
+
body: JSON.stringify({ spans }),
|
|
67
|
+
});
|
|
68
|
+
// 5xx: server overloaded. 4xx (bad token / quota / oversized): also
|
|
69
|
+
// pointless to keep sending. Either way, stop the rest of the batch.
|
|
70
|
+
if (resp.status >= 400)
|
|
71
|
+
throw new Error(`spans-${resp.status}`);
|
|
25
72
|
};
|
|
26
73
|
export const flush = async () => {
|
|
27
74
|
if (!_started)
|
|
@@ -137,6 +184,9 @@ export const __resetForTests = () => {
|
|
|
137
184
|
if (_flushTimer)
|
|
138
185
|
clearTimeout(_flushTimer);
|
|
139
186
|
_flushTimer = null;
|
|
187
|
+
if (_spanTimer)
|
|
188
|
+
clearInterval(_spanTimer);
|
|
189
|
+
_spanTimer = null;
|
|
140
190
|
_started = false;
|
|
141
191
|
};
|
|
142
192
|
export const __peekQueue = () => _queue;
|
package/lib/transport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,IAAI,MAAM,GAAY,EAAE,CAAC;AACzB,IAAI,WAAW,GAAyC,IAAI,CAAC;AAC7D,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,MAAM,WAAW,GAAG,OAAO,CAAC;AAE5B,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAY,EAAQ,EAAE;IAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAChC,KAAK,KAAK,EAAE,CAAC;IACf,CAAC;SAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACxB,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,WAAW,GAAG,IAAI,CAAC;YACnB,KAAK,KAAK,EAAE,CAAC;QACf,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACxB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAS,EAAE;IACvC,QAAQ,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goliapkg/sentori-react-native",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Sentori SDK for React Native
|
|
3
|
+
"version": "0.5.2",
|
|
4
|
+
"description": "Sentori SDK for React Native \u2014 JS-layer error capture, native crash handlers (iOS / Android), batched transport, fetch + react-navigation tracing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://sentori.golia.jp",
|
|
7
7
|
"repository": {
|
|
@@ -7,10 +7,13 @@ import {
|
|
|
7
7
|
mock,
|
|
8
8
|
} from 'bun:test';
|
|
9
9
|
|
|
10
|
+
import { clearSpans, startSpan } from '@goliapkg/sentori-core';
|
|
11
|
+
|
|
10
12
|
import { setConfig, __resetForTests as resetConfig } from '../config';
|
|
11
13
|
import {
|
|
12
14
|
enqueue,
|
|
13
15
|
flush,
|
|
16
|
+
flushSpans,
|
|
14
17
|
startTransport,
|
|
15
18
|
__resetForTests as resetTransport,
|
|
16
19
|
__peekQueue,
|
|
@@ -168,3 +171,77 @@ describe('transport', () => {
|
|
|
168
171
|
expect(__peekQueue()).toHaveLength(0);
|
|
169
172
|
});
|
|
170
173
|
});
|
|
174
|
+
|
|
175
|
+
describe('span flush', () => {
|
|
176
|
+
beforeEach(() => {
|
|
177
|
+
resetConfig();
|
|
178
|
+
resetTransport();
|
|
179
|
+
clearSpans();
|
|
180
|
+
setConfig({
|
|
181
|
+
token: 'st_pk_test',
|
|
182
|
+
release: 'app@1.0.0+1',
|
|
183
|
+
environment: 'test',
|
|
184
|
+
ingestUrl: 'http://localhost:8080',
|
|
185
|
+
enabled: true,
|
|
186
|
+
});
|
|
187
|
+
startTransport();
|
|
188
|
+
});
|
|
189
|
+
afterEach(() => {
|
|
190
|
+
globalThis.fetch = originalFetch;
|
|
191
|
+
clearSpans();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('POSTs buffered spans to /v1/spans:batch', async () => {
|
|
195
|
+
const calls: { url: string; init?: RequestInit }[] = [];
|
|
196
|
+
globalThis.fetch = mock(async (url: string | URL | Request, init?: RequestInit) => {
|
|
197
|
+
calls.push({ url: String(url), init });
|
|
198
|
+
return new Response(null, { status: 202 });
|
|
199
|
+
}) as typeof fetch;
|
|
200
|
+
|
|
201
|
+
startSpan('http.client', { name: 'GET /a' }).finish({ status: 'ok' });
|
|
202
|
+
startSpan('http.client', { name: 'GET /b' }).finish({ status: 'error' });
|
|
203
|
+
await flushSpans();
|
|
204
|
+
|
|
205
|
+
expect(calls).toHaveLength(1);
|
|
206
|
+
expect(calls[0]?.url).toBe('http://localhost:8080/v1/spans:batch');
|
|
207
|
+
const body = JSON.parse((calls[0]?.init?.body as string) ?? '{}');
|
|
208
|
+
expect(body.spans).toHaveLength(2);
|
|
209
|
+
expect(body.spans[0]).toMatchObject({ op: 'http.client', name: 'GET /a', status: 'ok' });
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('no-op when the span buffer is empty', async () => {
|
|
213
|
+
let attempts = 0;
|
|
214
|
+
globalThis.fetch = mock(async () => {
|
|
215
|
+
attempts++;
|
|
216
|
+
return new Response(null, { status: 202 });
|
|
217
|
+
}) as typeof fetch;
|
|
218
|
+
await flushSpans();
|
|
219
|
+
expect(attempts).toBe(0);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('splits >200 spans into multiple batches', async () => {
|
|
223
|
+
const sizes: number[] = [];
|
|
224
|
+
globalThis.fetch = mock(async (_url: string | URL | Request, init?: RequestInit) => {
|
|
225
|
+
const body = JSON.parse((init?.body as string) ?? '{}');
|
|
226
|
+
sizes.push(body.spans.length);
|
|
227
|
+
return new Response(null, { status: 202 });
|
|
228
|
+
}) as typeof fetch;
|
|
229
|
+
|
|
230
|
+
for (let i = 0; i < 450; i++) startSpan('http.client', { name: `GET /${i}` }).finish();
|
|
231
|
+
await flushSpans();
|
|
232
|
+
|
|
233
|
+
expect(sizes).toEqual([200, 200, 50]);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('drops on 5xx without retrying', async () => {
|
|
237
|
+
let attempts = 0;
|
|
238
|
+
globalThis.fetch = mock(async () => {
|
|
239
|
+
attempts++;
|
|
240
|
+
return new Response('boom', { status: 503 });
|
|
241
|
+
}) as typeof fetch;
|
|
242
|
+
|
|
243
|
+
startSpan('http.client', { name: 'GET /a' }).finish();
|
|
244
|
+
await flushSpans();
|
|
245
|
+
expect(attempts).toBe(1);
|
|
246
|
+
});
|
|
247
|
+
});
|
package/src/handlers/network.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { startSpan } from '@goliapkg/sentori-core';
|
|
2
2
|
|
|
3
3
|
import { addBreadcrumb } from '../breadcrumbs';
|
|
4
|
+
import { getConfig } from '../config';
|
|
4
5
|
|
|
5
6
|
let _installed = false;
|
|
6
7
|
|
|
7
8
|
const AUTH_PARAMS = ['token', 'key', 'password', 'secret', 'access_token'];
|
|
8
9
|
|
|
10
|
+
// Requests to our own ingest endpoint shouldn't be traced — otherwise
|
|
11
|
+
// every span upload spawns another http.client span, and so on.
|
|
12
|
+
const isIngestUrl = (url: string): boolean => {
|
|
13
|
+
const base = getConfig()?.ingestUrl;
|
|
14
|
+
return !!base && url.startsWith(base);
|
|
15
|
+
};
|
|
16
|
+
|
|
9
17
|
export const installNetworkHandler = (): void => {
|
|
10
18
|
if (_installed) return;
|
|
11
19
|
_installed = true;
|
|
@@ -22,6 +30,7 @@ function patchFetch(): void {
|
|
|
22
30
|
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
23
31
|
const start = Date.now();
|
|
24
32
|
const url = extractUrl(input);
|
|
33
|
+
if (isIngestUrl(url)) return original(input, init);
|
|
25
34
|
const scrubbed = scrubUrl(url);
|
|
26
35
|
const method = (init?.method ??
|
|
27
36
|
(typeof input !== 'string' && 'method' in (input as Request)
|
|
@@ -117,6 +126,7 @@ function patchXhr(): void {
|
|
|
117
126
|
};
|
|
118
127
|
|
|
119
128
|
proto.send = function (this: TracedXhr, body?: Document | XMLHttpRequestBodyInit | null): void {
|
|
129
|
+
if (isIngestUrl(this.__sentoriUrl ?? '')) return originalSend.call(this, body);
|
|
120
130
|
const method = this.__sentoriMethod ?? 'GET';
|
|
121
131
|
const url = scrubUrl(this.__sentoriUrl ?? '');
|
|
122
132
|
const span = startSpan('http.client', {
|
package/src/transport.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { drainSpans } from '@goliapkg/sentori-core';
|
|
2
|
+
|
|
1
3
|
import { getConfig } from './config';
|
|
2
4
|
import type { Event } from './types';
|
|
3
5
|
|
|
@@ -7,8 +9,15 @@ const MAX_RETRY = 3;
|
|
|
7
9
|
const STORAGE_KEY = '@sentori/pending';
|
|
8
10
|
const MAX_PERSISTED = 1000;
|
|
9
11
|
|
|
12
|
+
// Spans are higher-volume and lower-value than error events: we batch
|
|
13
|
+
// them on their own timer, cap each request at the server's per-batch
|
|
14
|
+
// limit, and drop on failure rather than persisting offline.
|
|
15
|
+
const SPAN_FLUSH_INTERVAL_MS = 10_000;
|
|
16
|
+
const SPAN_BATCH_MAX = 200;
|
|
17
|
+
|
|
10
18
|
let _queue: Event[] = [];
|
|
11
19
|
let _flushTimer: ReturnType<typeof setTimeout> | null = null;
|
|
20
|
+
let _spanTimer: ReturnType<typeof setInterval> | null = null;
|
|
12
21
|
let _started = false;
|
|
13
22
|
|
|
14
23
|
const SDK_VERSION = '0.0.0';
|
|
@@ -27,6 +36,47 @@ export const enqueue = (event: Event): void => {
|
|
|
27
36
|
|
|
28
37
|
export const startTransport = (): void => {
|
|
29
38
|
_started = true;
|
|
39
|
+
if (!_spanTimer) {
|
|
40
|
+
_spanTimer = setInterval(() => {
|
|
41
|
+
void flushSpans();
|
|
42
|
+
}, SPAN_FLUSH_INTERVAL_MS);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const flushSpans = async (): Promise<void> => {
|
|
47
|
+
if (!_started) return;
|
|
48
|
+
const spans = drainSpans();
|
|
49
|
+
if (spans.length === 0) return;
|
|
50
|
+
const config = getConfig();
|
|
51
|
+
if (!config) return;
|
|
52
|
+
for (let i = 0; i < spans.length; i += SPAN_BATCH_MAX) {
|
|
53
|
+
const chunk = spans.slice(i, i + SPAN_BATCH_MAX);
|
|
54
|
+
try {
|
|
55
|
+
await sendSpansOnce(chunk, config.ingestUrl, config.token);
|
|
56
|
+
} catch {
|
|
57
|
+
// drop the remaining chunks — span uploads aren't worth retrying
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const sendSpansOnce = async (
|
|
64
|
+
spans: unknown[],
|
|
65
|
+
ingestUrl: string,
|
|
66
|
+
token: string,
|
|
67
|
+
): Promise<void> => {
|
|
68
|
+
const resp = await fetch(`${ingestUrl}/v1/spans:batch`, {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers: {
|
|
71
|
+
'Content-Type': 'application/json',
|
|
72
|
+
Authorization: `Bearer ${token}`,
|
|
73
|
+
'Sentori-Sdk': `react-native/${SDK_VERSION}`,
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify({ spans }),
|
|
76
|
+
});
|
|
77
|
+
// 5xx: server overloaded. 4xx (bad token / quota / oversized): also
|
|
78
|
+
// pointless to keep sending. Either way, stop the rest of the batch.
|
|
79
|
+
if (resp.status >= 400) throw new Error(`spans-${resp.status}`);
|
|
30
80
|
};
|
|
31
81
|
|
|
32
82
|
export const flush = async (): Promise<void> => {
|
|
@@ -158,6 +208,8 @@ export const __resetForTests = (): void => {
|
|
|
158
208
|
_queue = [];
|
|
159
209
|
if (_flushTimer) clearTimeout(_flushTimer);
|
|
160
210
|
_flushTimer = null;
|
|
211
|
+
if (_spanTimer) clearInterval(_spanTimer);
|
|
212
|
+
_spanTimer = null;
|
|
161
213
|
_started = false;
|
|
162
214
|
};
|
|
163
215
|
|