aboutsummaryrefslogtreecommitdiff
path: root/src/analytics
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-10-05 17:50:05 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-10-05 17:50:05 -0700
commitbd14ad9e6ed9343acc21483c0c44cf0b81d8bae6 (patch)
treec2e2f956c5c4836bff195aaa6ec6544f7f13ecdf /src/analytics
parent9507cd8ed6ec1f7575a850333f73f006309feac8 (diff)
downloadbun-bd14ad9e6ed9343acc21483c0c44cf0b81d8bae6.tar.gz
bun-bd14ad9e6ed9343acc21483c0c44cf0b81d8bae6.tar.zst
bun-bd14ad9e6ed9343acc21483c0c44cf0b81d8bae6.zip
Async analytics works now
Requests are ~60 bytes and the thread mostly sleeps, so it should be pretty low overhead overall.
Diffstat (limited to 'src/analytics')
-rw-r--r--src/analytics/analytics_schema.zig (renamed from src/analytics/analytics.zig)6
-rw-r--r--src/analytics/analytics_thread.zig62
-rw-r--r--src/analytics/schema.peechy4
3 files changed, 49 insertions, 23 deletions
diff --git a/src/analytics/analytics.zig b/src/analytics/analytics_schema.zig
index beeddb34b..917422ba5 100644
--- a/src/analytics/analytics.zig
+++ b/src/analytics/analytics_schema.zig
@@ -281,7 +281,7 @@ pub fn Writer(comptime WritableStream: type) type {
pub const ByteWriter = Writer(*std.io.FixedBufferStream([]u8));
pub const FileWriter = Writer(std.fs.File);
-pub const Analytics = struct {
+pub const analytics = struct {
pub const OperatingSystem = enum(u8) {
_none,
/// linux
@@ -333,14 +333,14 @@ pub const Analytics = struct {
this.os = try reader.readValue(OperatingSystem);
this.arch = try reader.readValue(Architecture);
- this.version = try reader.readValue([]const u8);
+ this.version = try reader.readArray(u8);
return this;
}
pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
try writer.writeEnum(this.os);
try writer.writeEnum(this.arch);
- try writer.writeValue(this.version);
+ try writer.writeArray(u8, this.version);
}
};
diff --git a/src/analytics/analytics_thread.zig b/src/analytics/analytics_thread.zig
index 2f4998c66..5484c3c0f 100644
--- a/src/analytics/analytics_thread.zig
+++ b/src/analytics/analytics_thread.zig
@@ -5,8 +5,8 @@ const std = @import("std");
const HTTPClient = @import("../http_client.zig");
const URL = @import("../query_string_map.zig").URL;
const Fs = @import("../fs.zig");
-const Analytics = @import("./analytics.zig").Analytics;
-const Writer = @import("./analytics.zig").Writer;
+const Analytics = @import("./analytics_schema.zig").analytics;
+const Writer = @import("./analytics_schema.zig").Writer;
const Headers = @import("../javascript/jsc/webcore/response.zig").Headers;
pub const EventName = enum(u8) {
@@ -18,6 +18,7 @@ pub const EventName = enum(u8) {
};
var random: std.rand.DefaultPrng = undefined;
+const DotEnv = @import("../env_loader.zig");
const platform_arch = if (Environment.isAarch64) Analytics.Architecture.arm else Analytics.Architecture.x64;
@@ -83,7 +84,7 @@ pub const GenerateHeader = struct {
pub fn forMac() Analytics.Platform {
std.mem.set(u8, std.mem.span(&osversion_name), 0);
- var platform = Analytics.Platform{ .os = Analytics.OperatingSystem.macos, .version = "", .arch = platform_arch };
+ var platform = Analytics.Platform{ .os = Analytics.OperatingSystem.macos, .version = &[_]u8{}, .arch = platform_arch };
var osversion_name_buf: [2]c_int = undefined;
var osversion_name_ptr = osversion_name.len - 1;
var len = osversion_name.len - 1;
@@ -169,31 +170,51 @@ pub fn enqueue(comptime name: EventName) void {
if (disabled) return;
if (!has_loaded) {
- defer has_loaded = true;
-
- event_queue = EventQueue.init(std.heap.c_allocator);
- spawn() catch |err| {
- if (comptime isDebug) {
- Output.prettyErrorln("[Analytics] error spawning thread {s}", .{@errorName(err)});
- Output.flush();
- }
-
- disabled = true;
- return;
- };
+ if (!start()) return;
}
- _ = event_queue.tryWriteItem(Event.init(name)) catch false;
+ var items = [_]Event{Event.init(name)};
+ _ = event_queue.write(&items) catch false;
+ std.Thread.Futex.wake(&counter, 1);
}
pub var thread: std.Thread = undefined;
+var counter: std.atomic.Atomic(u32) = undefined;
-pub fn spawn() !void {
+fn start() bool {
+ @setCold(true);
+
+ defer has_loaded = true;
+ counter = std.atomic.Atomic(u32).init(0);
+
+ event_queue = EventQueue.init(std.heap.c_allocator);
+ spawn() catch |err| {
+ if (comptime isDebug) {
+ Output.prettyErrorln("[Analytics] error spawning thread {s}", .{@errorName(err)});
+ Output.flush();
+ }
+
+ disabled = true;
+ return false;
+ };
+ return true;
+}
+
+fn spawn() !void {
@setCold(true);
has_loaded = true;
thread = try std.Thread.spawn(.{}, readloop, .{});
}
+const headers_buf: string = "Content-Type binary/peechy";
+const header_entry = Headers.Kv{
+ .name = .{ .offset = 0, .length = @intCast(u32, "Content-Type".len) },
+ .value = .{
+ .offset = std.mem.indexOf(u8, headers_buf, "binary/peechy").?,
+ .length = @intCast(u32, "binary/peechy".len),
+ },
+};
+
fn readloop() anyerror!void {
defer disabled = true;
Output.Source.configureThread();
@@ -201,8 +222,13 @@ fn readloop() anyerror!void {
thread.setName("Analytics") catch {};
var event_list = EventList.init();
+ event_list.client.verbose = FeatureFlags.verbose_analytics;
+ event_list.client.header_entries.append(default_allocator, header_entry) catch unreachable;
+ event_list.client.header_buf = headers_buf;
+
// everybody's random should be random
while (true) {
+ // Wait for the next event by blocking
while (event_queue.tryReadItem() catch null) |item| {
event_list.push(item);
}
@@ -211,7 +237,7 @@ fn readloop() anyerror!void {
event_list.flush();
}
- event_queue.getters.wait(&event_queue.mutex);
+ std.Thread.Futex.wait(&counter, counter.load(.Acquire), null) catch unreachable;
}
}
diff --git a/src/analytics/schema.peechy b/src/analytics/schema.peechy
index 4ae230fa4..0caad6615 100644
--- a/src/analytics/schema.peechy
+++ b/src/analytics/schema.peechy
@@ -1,4 +1,4 @@
-package Analytics;
+package analytics;
smol OperatingSystem {
linux = 1;
@@ -15,7 +15,7 @@ smol Architecture {
struct Platform {
OperatingSystem os;
Architecture arch;
- string version;
+ byte[] version;
}
enum EventKind {