Skip to content

Commit 9d294bb

Browse files
fixes
1 parent 751fe67 commit 9d294bb

24 files changed

Lines changed: 1020 additions & 161 deletions

File tree

sdk/runanywhere-commons/include/rac/core/rac_analytics_events.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,60 @@ RAC_API rac_result_t rac_analytics_events_set_public_callback(rac_public_event_c
510510
*/
511511
RAC_API rac_bool_t rac_analytics_events_has_public_callback(void);
512512

513+
// =============================================================================
514+
// PLATFORM EMIT HELPERS
515+
// =============================================================================
516+
//
517+
// C-linkage convenience functions for platform SDKs (Web, Kotlin) that need to
518+
// emit analytics events from outside the C++ component layer. Each function
519+
// accepts individual parameters, constructs the C struct internally, and calls
520+
// rac_analytics_event_emit(). On the Web SDK these are called via Emscripten
521+
// ccall() which handles string marshalling automatically.
522+
523+
RAC_API void rac_analytics_emit_stt_model_load_completed(
524+
const char* model_id, const char* model_name, double duration_ms, int32_t framework);
525+
526+
RAC_API void rac_analytics_emit_stt_model_load_failed(
527+
const char* model_id, int32_t error_code, const char* error_message);
528+
529+
RAC_API void rac_analytics_emit_stt_transcription_completed(
530+
const char* transcription_id, const char* model_id, const char* text,
531+
float confidence, double duration_ms, double audio_length_ms,
532+
int32_t audio_size_bytes, int32_t word_count, double real_time_factor,
533+
const char* language, int32_t sample_rate, int32_t framework);
534+
535+
RAC_API void rac_analytics_emit_stt_transcription_failed(
536+
const char* transcription_id, const char* model_id,
537+
int32_t error_code, const char* error_message);
538+
539+
RAC_API void rac_analytics_emit_tts_voice_load_completed(
540+
const char* model_id, const char* model_name, double duration_ms, int32_t framework);
541+
542+
RAC_API void rac_analytics_emit_tts_voice_load_failed(
543+
const char* model_id, int32_t error_code, const char* error_message);
544+
545+
RAC_API void rac_analytics_emit_tts_synthesis_completed(
546+
const char* synthesis_id, const char* model_id,
547+
int32_t character_count, double audio_duration_ms, int32_t audio_size_bytes,
548+
double processing_duration_ms, double characters_per_second,
549+
int32_t sample_rate, int32_t framework);
550+
551+
RAC_API void rac_analytics_emit_tts_synthesis_failed(
552+
const char* synthesis_id, const char* model_id,
553+
int32_t error_code, const char* error_message);
554+
555+
RAC_API void rac_analytics_emit_vad_speech_started(void);
556+
557+
RAC_API void rac_analytics_emit_vad_speech_ended(double speech_duration_ms, float energy_level);
558+
559+
RAC_API void rac_analytics_emit_model_download_started(const char* model_id);
560+
561+
RAC_API void rac_analytics_emit_model_download_completed(
562+
const char* model_id, int64_t file_size_bytes, double duration_ms);
563+
564+
RAC_API void rac_analytics_emit_model_download_failed(
565+
const char* model_id, const char* error_message);
566+
513567
// =============================================================================
514568
// DEFAULT EVENT DATA
515569
// =============================================================================

sdk/runanywhere-commons/src/core/events.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,169 @@ rac_bool_t rac_analytics_events_has_public_callback(void) {
126126
return state.public_callback != nullptr ? RAC_TRUE : RAC_FALSE;
127127
}
128128

129+
// =============================================================================
130+
// PLATFORM EMIT HELPERS (C-linkage, callable from WASM via ccall)
131+
// =============================================================================
132+
133+
void rac_analytics_emit_stt_model_load_completed(const char* model_id, const char* model_name,
134+
double duration_ms, int32_t framework) {
135+
rac_analytics_event_data_t event = {};
136+
event.type = RAC_EVENT_STT_MODEL_LOAD_COMPLETED;
137+
event.data.stt_transcription = RAC_ANALYTICS_STT_TRANSCRIPTION_DEFAULT;
138+
event.data.stt_transcription.model_id = model_id;
139+
event.data.stt_transcription.model_name = model_name;
140+
event.data.stt_transcription.duration_ms = duration_ms;
141+
event.data.stt_transcription.framework = static_cast<rac_inference_framework_t>(framework);
142+
event.data.stt_transcription.error_code = RAC_SUCCESS;
143+
rac_analytics_event_emit(RAC_EVENT_STT_MODEL_LOAD_COMPLETED, &event);
144+
}
145+
146+
void rac_analytics_emit_stt_model_load_failed(const char* model_id, int32_t error_code,
147+
const char* error_message) {
148+
rac_analytics_event_data_t event = {};
149+
event.type = RAC_EVENT_STT_MODEL_LOAD_FAILED;
150+
event.data.stt_transcription = RAC_ANALYTICS_STT_TRANSCRIPTION_DEFAULT;
151+
event.data.stt_transcription.model_id = model_id;
152+
event.data.stt_transcription.error_code = static_cast<rac_result_t>(error_code);
153+
event.data.stt_transcription.error_message = error_message;
154+
rac_analytics_event_emit(RAC_EVENT_STT_MODEL_LOAD_FAILED, &event);
155+
}
156+
157+
void rac_analytics_emit_stt_transcription_completed(
158+
const char* transcription_id, const char* model_id, const char* text, float confidence,
159+
double duration_ms, double audio_length_ms, int32_t audio_size_bytes, int32_t word_count,
160+
double real_time_factor, const char* language, int32_t sample_rate, int32_t framework) {
161+
rac_analytics_event_data_t event = {};
162+
event.type = RAC_EVENT_STT_TRANSCRIPTION_COMPLETED;
163+
event.data.stt_transcription.transcription_id = transcription_id;
164+
event.data.stt_transcription.model_id = model_id;
165+
event.data.stt_transcription.text = text;
166+
event.data.stt_transcription.confidence = confidence;
167+
event.data.stt_transcription.duration_ms = duration_ms;
168+
event.data.stt_transcription.audio_length_ms = audio_length_ms;
169+
event.data.stt_transcription.audio_size_bytes = audio_size_bytes;
170+
event.data.stt_transcription.word_count = word_count;
171+
event.data.stt_transcription.real_time_factor = real_time_factor;
172+
event.data.stt_transcription.language = language;
173+
event.data.stt_transcription.sample_rate = sample_rate;
174+
event.data.stt_transcription.framework = static_cast<rac_inference_framework_t>(framework);
175+
event.data.stt_transcription.error_code = RAC_SUCCESS;
176+
rac_analytics_event_emit(RAC_EVENT_STT_TRANSCRIPTION_COMPLETED, &event);
177+
}
178+
179+
void rac_analytics_emit_stt_transcription_failed(const char* transcription_id,
180+
const char* model_id, int32_t error_code,
181+
const char* error_message) {
182+
rac_analytics_event_data_t event = {};
183+
event.type = RAC_EVENT_STT_TRANSCRIPTION_FAILED;
184+
event.data.stt_transcription = RAC_ANALYTICS_STT_TRANSCRIPTION_DEFAULT;
185+
event.data.stt_transcription.transcription_id = transcription_id;
186+
event.data.stt_transcription.model_id = model_id;
187+
event.data.stt_transcription.error_code = static_cast<rac_result_t>(error_code);
188+
event.data.stt_transcription.error_message = error_message;
189+
rac_analytics_event_emit(RAC_EVENT_STT_TRANSCRIPTION_FAILED, &event);
190+
}
191+
192+
void rac_analytics_emit_tts_voice_load_completed(const char* model_id, const char* model_name,
193+
double duration_ms, int32_t framework) {
194+
rac_analytics_event_data_t event = {};
195+
event.type = RAC_EVENT_TTS_VOICE_LOAD_COMPLETED;
196+
event.data.tts_synthesis = RAC_ANALYTICS_TTS_SYNTHESIS_DEFAULT;
197+
event.data.tts_synthesis.model_id = model_id;
198+
event.data.tts_synthesis.model_name = model_name;
199+
event.data.tts_synthesis.processing_duration_ms = duration_ms;
200+
event.data.tts_synthesis.framework = static_cast<rac_inference_framework_t>(framework);
201+
event.data.tts_synthesis.error_code = RAC_SUCCESS;
202+
rac_analytics_event_emit(RAC_EVENT_TTS_VOICE_LOAD_COMPLETED, &event);
203+
}
204+
205+
void rac_analytics_emit_tts_voice_load_failed(const char* model_id, int32_t error_code,
206+
const char* error_message) {
207+
rac_analytics_event_data_t event = {};
208+
event.type = RAC_EVENT_TTS_VOICE_LOAD_FAILED;
209+
event.data.tts_synthesis = RAC_ANALYTICS_TTS_SYNTHESIS_DEFAULT;
210+
event.data.tts_synthesis.model_id = model_id;
211+
event.data.tts_synthesis.error_code = static_cast<rac_result_t>(error_code);
212+
event.data.tts_synthesis.error_message = error_message;
213+
rac_analytics_event_emit(RAC_EVENT_TTS_VOICE_LOAD_FAILED, &event);
214+
}
215+
216+
void rac_analytics_emit_tts_synthesis_completed(
217+
const char* synthesis_id, const char* model_id, int32_t character_count,
218+
double audio_duration_ms, int32_t audio_size_bytes, double processing_duration_ms,
219+
double characters_per_second, int32_t sample_rate, int32_t framework) {
220+
rac_analytics_event_data_t event = {};
221+
event.type = RAC_EVENT_TTS_SYNTHESIS_COMPLETED;
222+
event.data.tts_synthesis.synthesis_id = synthesis_id;
223+
event.data.tts_synthesis.model_id = model_id;
224+
event.data.tts_synthesis.character_count = character_count;
225+
event.data.tts_synthesis.audio_duration_ms = audio_duration_ms;
226+
event.data.tts_synthesis.audio_size_bytes = audio_size_bytes;
227+
event.data.tts_synthesis.processing_duration_ms = processing_duration_ms;
228+
event.data.tts_synthesis.characters_per_second = characters_per_second;
229+
event.data.tts_synthesis.sample_rate = sample_rate;
230+
event.data.tts_synthesis.framework = static_cast<rac_inference_framework_t>(framework);
231+
event.data.tts_synthesis.error_code = RAC_SUCCESS;
232+
rac_analytics_event_emit(RAC_EVENT_TTS_SYNTHESIS_COMPLETED, &event);
233+
}
234+
235+
void rac_analytics_emit_tts_synthesis_failed(const char* synthesis_id, const char* model_id,
236+
int32_t error_code, const char* error_message) {
237+
rac_analytics_event_data_t event = {};
238+
event.type = RAC_EVENT_TTS_SYNTHESIS_FAILED;
239+
event.data.tts_synthesis = RAC_ANALYTICS_TTS_SYNTHESIS_DEFAULT;
240+
event.data.tts_synthesis.synthesis_id = synthesis_id;
241+
event.data.tts_synthesis.model_id = model_id;
242+
event.data.tts_synthesis.error_code = static_cast<rac_result_t>(error_code);
243+
event.data.tts_synthesis.error_message = error_message;
244+
rac_analytics_event_emit(RAC_EVENT_TTS_SYNTHESIS_FAILED, &event);
245+
}
246+
247+
void rac_analytics_emit_vad_speech_started(void) {
248+
rac_analytics_event_data_t event = {};
249+
event.type = RAC_EVENT_VAD_SPEECH_STARTED;
250+
event.data.vad = RAC_ANALYTICS_VAD_DEFAULT;
251+
rac_analytics_event_emit(RAC_EVENT_VAD_SPEECH_STARTED, &event);
252+
}
253+
254+
void rac_analytics_emit_vad_speech_ended(double speech_duration_ms, float energy_level) {
255+
rac_analytics_event_data_t event = {};
256+
event.type = RAC_EVENT_VAD_SPEECH_ENDED;
257+
event.data.vad.speech_duration_ms = speech_duration_ms;
258+
event.data.vad.energy_level = energy_level;
259+
rac_analytics_event_emit(RAC_EVENT_VAD_SPEECH_ENDED, &event);
260+
}
261+
262+
void rac_analytics_emit_model_download_started(const char* model_id) {
263+
rac_analytics_event_data_t event = {};
264+
event.type = RAC_EVENT_MODEL_DOWNLOAD_STARTED;
265+
event.data.model_download = RAC_ANALYTICS_MODEL_DOWNLOAD_DEFAULT;
266+
event.data.model_download.model_id = model_id;
267+
rac_analytics_event_emit(RAC_EVENT_MODEL_DOWNLOAD_STARTED, &event);
268+
}
269+
270+
void rac_analytics_emit_model_download_completed(const char* model_id, int64_t file_size_bytes,
271+
double duration_ms) {
272+
rac_analytics_event_data_t event = {};
273+
event.type = RAC_EVENT_MODEL_DOWNLOAD_COMPLETED;
274+
event.data.model_download = RAC_ANALYTICS_MODEL_DOWNLOAD_DEFAULT;
275+
event.data.model_download.model_id = model_id;
276+
event.data.model_download.size_bytes = file_size_bytes;
277+
event.data.model_download.duration_ms = duration_ms;
278+
event.data.model_download.progress = 100.0;
279+
rac_analytics_event_emit(RAC_EVENT_MODEL_DOWNLOAD_COMPLETED, &event);
280+
}
281+
282+
void rac_analytics_emit_model_download_failed(const char* model_id, const char* error_message) {
283+
rac_analytics_event_data_t event = {};
284+
event.type = RAC_EVENT_MODEL_DOWNLOAD_FAILED;
285+
event.data.model_download = RAC_ANALYTICS_MODEL_DOWNLOAD_DEFAULT;
286+
event.data.model_download.model_id = model_id;
287+
event.data.model_download.error_code = RAC_ERROR_DOWNLOAD_FAILED;
288+
event.data.model_download.error_message = error_message;
289+
rac_analytics_event_emit(RAC_EVENT_MODEL_DOWNLOAD_FAILED, &event);
290+
}
291+
129292
} // extern "C"
130293

131294
// =============================================================================

sdk/runanywhere-web/packages/core/src/Infrastructure/ModelDownloader.ts

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import { EventBus } from '../Foundation/EventBus';
1010
import { SDKLogger } from '../Foundation/SDKLogger';
11-
import { HTTPService } from '../services/HTTPService';
11+
import { AnalyticsEmitter } from '../services/AnalyticsEmitter';
1212
import { OPFSStorage } from './OPFSStorage';
1313
import type { MetadataMap } from './OPFSStorage';
1414
import type { LocalFileStorage } from './LocalFileStorage';
@@ -217,13 +217,7 @@ export class ModelDownloader {
217217

218218
this.registry.updateModel(modelId, { status: ModelStatus.Downloading, downloadProgress: 0 });
219219
EventBus.shared.emit('model.downloadStarted', SDKEventType.Model, { modelId, url: model.url });
220-
HTTPService.shared.postTelemetryEvent({
221-
event_type: 'model.download.started',
222-
modality: 'download',
223-
model_id: modelId,
224-
framework: 'web',
225-
success: true,
226-
});
220+
AnalyticsEmitter.emitModelDownloadStarted(modelId);
227221

228222
try {
229223
const totalFiles = 1 + (model.additionalFiles?.length ?? 0);
@@ -312,26 +306,12 @@ export class ModelDownloader {
312306
filesTotal: totalFiles,
313307
});
314308
EventBus.shared.emit('model.downloadCompleted', SDKEventType.Model, { modelId, sizeBytes: totalSize });
315-
HTTPService.shared.postTelemetryEvent({
316-
event_type: 'model.download.completed',
317-
modality: 'download',
318-
model_id: modelId,
319-
framework: 'web',
320-
success: true,
321-
file_size_bytes: totalSize,
322-
});
309+
AnalyticsEmitter.emitModelDownloadCompleted(modelId, totalSize, 0);
323310
} catch (err) {
324311
const message = err instanceof Error ? err.message : String(err);
325312
this.registry.updateModel(modelId, { status: ModelStatus.Error, error: message });
326313
EventBus.shared.emit('model.downloadFailed', SDKEventType.Model, { modelId, error: message });
327-
HTTPService.shared.postTelemetryEvent({
328-
event_type: 'model.download.failed',
329-
modality: 'download',
330-
model_id: modelId,
331-
framework: 'web',
332-
success: false,
333-
error_message: message,
334-
});
314+
AnalyticsEmitter.emitModelDownloadFailed(modelId, message);
335315
}
336316
}
337317

sdk/runanywhere-web/packages/core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,5 @@ export type { InferredModelMeta } from './Infrastructure/ModelFileInference';
8686
// Services
8787
export { HTTPService } from './services/HTTPService';
8888
export type { HTTPServiceConfig, DevModeConfig } from './services/HTTPService';
89+
export { AnalyticsEmitter } from './services/AnalyticsEmitter';
90+
export type { AnalyticsEmitterBackend } from './services/AnalyticsEmitter';

0 commit comments

Comments
 (0)