@rivetkit/effect 2.3.3-rc.1 → 2.3.3-rc.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/dist/Actor.d.ts +2 -3
- package/dist/Actor.d.ts.map +1 -1
- package/dist/Actor.js +2 -2
- package/dist/Actor.js.map +1 -1
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +6 -4
- package/dist/Client.js.map +1 -1
- package/dist/Registry.d.ts +69 -7
- package/dist/Registry.d.ts.map +1 -1
- package/dist/Registry.js +93 -40
- package/dist/Registry.js.map +1 -1
- package/dist/RivetError.d.ts +18 -3
- package/dist/RivetError.d.ts.map +1 -1
- package/dist/RivetError.js +31 -0
- package/dist/RivetError.js.map +1 -1
- package/dist/RivetLogger.d.ts +41 -0
- package/dist/RivetLogger.d.ts.map +1 -0
- package/dist/RivetLogger.js +41 -0
- package/dist/RivetLogger.js.map +1 -0
- package/dist/State.d.ts +92 -56
- package/dist/State.d.ts.map +1 -1
- package/dist/State.js +51 -57
- package/dist/State.js.map +1 -1
- package/dist/internal/ActorInstanceManager.d.ts.map +1 -1
- package/dist/internal/ActorInstanceManager.js +4 -4
- package/dist/internal/ActorInstanceManager.js.map +1 -1
- package/dist/internal/ActorStateAdapter.d.ts +1 -1
- package/dist/internal/ActorStateAdapter.d.ts.map +1 -1
- package/dist/internal/ActorStateAdapter.js +2 -7
- package/dist/internal/ActorStateAdapter.js.map +1 -1
- package/dist/internal/StateOptions.d.ts +1 -0
- package/dist/internal/StateOptions.d.ts.map +1 -1
- package/dist/internal/logging.d.ts +6 -7
- package/dist/internal/logging.d.ts.map +1 -1
- package/dist/internal/logging.js +78 -102
- package/dist/internal/logging.js.map +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +1 -1
- package/dist/mod.js.map +1 -1
- package/package.json +3 -3
- package/src/Actor.test-d.ts +32 -0
- package/src/Actor.ts +29 -4
- package/src/Client.test.ts +21 -18
- package/src/Client.ts +6 -4
- package/src/Registry.test.ts +7 -11
- package/src/Registry.ts +116 -50
- package/src/RivetError.test.ts +11 -0
- package/src/RivetError.ts +37 -0
- package/src/RivetLogger.ts +60 -0
- package/src/State.test.ts +163 -4
- package/src/State.ts +293 -97
- package/src/internal/ActorInstanceManager.ts +4 -10
- package/src/internal/ActorStateAdapter.ts +5 -11
- package/src/internal/StateOptions.ts +4 -0
- package/src/internal/logging.test.ts +65 -88
- package/src/internal/logging.ts +103 -143
- package/src/mod.ts +1 -1
- package/dist/Logger.d.ts +0 -29
- package/dist/Logger.d.ts.map +0 -1
- package/dist/Logger.js +0 -31
- package/dist/Logger.js.map +0 -1
- package/src/Logger.ts +0 -43
|
@@ -77,7 +77,9 @@ export const make = Effect.fnUntraced(function* <
|
|
|
77
77
|
const scope = yield* Scope.make();
|
|
78
78
|
return yield* Effect.gen(function* () {
|
|
79
79
|
const state = stateAdapter
|
|
80
|
-
? yield* stateAdapter
|
|
80
|
+
? yield* stateAdapter
|
|
81
|
+
.makeStateView(c)
|
|
82
|
+
.pipe(Effect.provideService(Scope.Scope, scope))
|
|
81
83
|
: undefined;
|
|
82
84
|
const context = makeContext(c, scope);
|
|
83
85
|
const actionHandlers = yield* wakeHandler(
|
|
@@ -105,15 +107,7 @@ export const make = Effect.fnUntraced(function* <
|
|
|
105
107
|
return {
|
|
106
108
|
get: (actorId: string) => instances.get(actorId),
|
|
107
109
|
onWake: async (c: WakeContext<StateDefinition, Database>) => {
|
|
108
|
-
await runPromise(
|
|
109
|
-
makeInstance(c).pipe(
|
|
110
|
-
Effect.tap((instance) =>
|
|
111
|
-
Effect.sync(() => {
|
|
112
|
-
instances.set(c.actorId, instance);
|
|
113
|
-
}),
|
|
114
|
-
),
|
|
115
|
-
),
|
|
116
|
-
);
|
|
110
|
+
instances.set(c.actorId, await runPromise(makeInstance(c)));
|
|
117
111
|
},
|
|
118
112
|
onStateChange: stateAdapter
|
|
119
113
|
? (
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Effect, type Fiber, Schema
|
|
1
|
+
import { Effect, type Fiber, Schema } from "effect";
|
|
2
2
|
import * as State from "../State.ts";
|
|
3
3
|
import type * as StateOptions from "./StateOptions.ts";
|
|
4
4
|
|
|
5
5
|
export type ActorState<StateDefinition extends StateOptions.Any> = State.State<
|
|
6
6
|
StateOptions.Decoded<StateDefinition>,
|
|
7
|
-
Schema.SchemaError
|
|
7
|
+
Schema.SchemaError,
|
|
8
|
+
StateOptions.Services<StateDefinition>
|
|
8
9
|
>;
|
|
9
10
|
|
|
10
11
|
type StateInstance<StateDefinition extends StateOptions.Any> = {
|
|
@@ -71,15 +72,8 @@ export const make = Effect.fnUntraced(function* <
|
|
|
71
72
|
const state = yield* Effect.fromNullishOr(
|
|
72
73
|
instance.state,
|
|
73
74
|
).pipe(Effect.orDie);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
state.semaphore,
|
|
77
|
-
Effect.gen(function* () {
|
|
78
|
-
const decoded = yield* stateCodec
|
|
79
|
-
.decodeUnknown(newState)
|
|
80
|
-
.pipe(Effect.orDie);
|
|
81
|
-
State.publishUnsafe(state, decoded);
|
|
82
|
-
}),
|
|
75
|
+
yield* state[State.RuntimeTypeId].publishEffect(
|
|
76
|
+
stateCodec.decodeUnknown(newState).pipe(Effect.orDie),
|
|
83
77
|
);
|
|
84
78
|
}),
|
|
85
79
|
);
|
|
@@ -10,6 +10,10 @@ export interface Any {
|
|
|
10
10
|
readonly initialValue: () => unknown;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export type Services<State extends Any> =
|
|
14
|
+
| State["schema"]["DecodingServices"]
|
|
15
|
+
| State["schema"]["EncodingServices"];
|
|
16
|
+
|
|
13
17
|
export type Encoded<State extends Any> =
|
|
14
18
|
| State["schema"]["Encoded"]
|
|
15
19
|
| ([State] extends [never] ? undefined : never);
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { assert, describe, it } from "@effect/vitest";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
ConfigProvider,
|
|
5
|
-
Effect,
|
|
6
|
-
Layer,
|
|
7
|
-
Logger as EffectLogger,
|
|
8
|
-
References,
|
|
9
|
-
} from "effect";
|
|
10
|
-
import type { Logger as PinoLogger } from "rivetkit/log";
|
|
2
|
+
import { ConfigProvider, Effect, Logger, References } from "effect";
|
|
3
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
11
4
|
import * as Logging from "./logging.ts";
|
|
12
5
|
|
|
13
6
|
type LogEntry = {
|
|
@@ -16,7 +9,7 @@ type LogEntry = {
|
|
|
16
9
|
readonly msg: string | undefined;
|
|
17
10
|
};
|
|
18
11
|
|
|
19
|
-
function makeTestLogger(entries: Array<LogEntry>):
|
|
12
|
+
function makeTestLogger(entries: Array<LogEntry>): RivetkitLog.Logger {
|
|
20
13
|
const logger: Record<string, unknown> = {};
|
|
21
14
|
for (const level of ["trace", "debug", "info", "warn", "error", "fatal"]) {
|
|
22
15
|
logger[level] = (
|
|
@@ -27,7 +20,7 @@ function makeTestLogger(entries: Array<LogEntry>): PinoLogger {
|
|
|
27
20
|
};
|
|
28
21
|
}
|
|
29
22
|
|
|
30
|
-
return logger as unknown as
|
|
23
|
+
return logger as unknown as RivetkitLog.Logger;
|
|
31
24
|
}
|
|
32
25
|
|
|
33
26
|
describe("internal/logging", () => {
|
|
@@ -65,23 +58,21 @@ describe("internal/logging", () => {
|
|
|
65
58
|
key: "room-1",
|
|
66
59
|
actorId: "actor-1",
|
|
67
60
|
}),
|
|
68
|
-
Effect.provide(
|
|
69
|
-
EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
|
|
70
|
-
),
|
|
61
|
+
Effect.provide(Logger.layer([Logging.makeLogger(baseLogger)])),
|
|
71
62
|
);
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
64
|
+
const entry = entries[0];
|
|
65
|
+
assert.ok(entry !== undefined);
|
|
66
|
+
assert.strictEqual(entry.level, "info");
|
|
67
|
+
assert.strictEqual(entry.msg, "room awake");
|
|
68
|
+
assert.deepStrictEqual(entry.fields, {
|
|
69
|
+
roomId: "abc",
|
|
70
|
+
actor: "ChatRoom",
|
|
71
|
+
key: "room-1",
|
|
72
|
+
actorId: "actor-1",
|
|
73
|
+
fiberId: entry.fields.fiberId,
|
|
74
|
+
});
|
|
75
|
+
assert.strictEqual(typeof entry.fields.fiberId, "string");
|
|
85
76
|
}),
|
|
86
77
|
);
|
|
87
78
|
|
|
@@ -92,9 +83,7 @@ describe("internal/logging", () => {
|
|
|
92
83
|
const error = new Error("room failed to wake");
|
|
93
84
|
|
|
94
85
|
yield* Effect.logError(error).pipe(
|
|
95
|
-
Effect.provide(
|
|
96
|
-
EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
|
|
97
|
-
),
|
|
86
|
+
Effect.provide(Logger.layer([Logging.makeLogger(baseLogger)])),
|
|
98
87
|
);
|
|
99
88
|
|
|
100
89
|
const entry = entries[0];
|
|
@@ -115,9 +104,7 @@ describe("internal/logging", () => {
|
|
|
115
104
|
actorId: "actor-1",
|
|
116
105
|
action: "SendMessage",
|
|
117
106
|
}).pipe(
|
|
118
|
-
Effect.provide(
|
|
119
|
-
EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
|
|
120
|
-
),
|
|
107
|
+
Effect.provide(Logger.layer([Logging.makeLogger(baseLogger)])),
|
|
121
108
|
);
|
|
122
109
|
|
|
123
110
|
const entry = entries[0];
|
|
@@ -130,17 +117,7 @@ describe("internal/logging", () => {
|
|
|
130
117
|
}),
|
|
131
118
|
);
|
|
132
119
|
|
|
133
|
-
it.effect(
|
|
134
|
-
"uses References.MinimumLogLevel when creating the base logger",
|
|
135
|
-
() =>
|
|
136
|
-
Effect.gen(function* () {
|
|
137
|
-
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
138
|
-
|
|
139
|
-
assert.strictEqual(baseLogger.level, "debug");
|
|
140
|
-
}).pipe(Effect.provideService(References.MinimumLogLevel, "Debug")),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
it.effect("accepts the shared Pino RIVET_LOG_LEVEL values", () =>
|
|
120
|
+
it.effect("accepts RIVET_LOG_LEVEL values", () =>
|
|
144
121
|
Effect.gen(function* () {
|
|
145
122
|
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
146
123
|
|
|
@@ -157,25 +134,24 @@ describe("internal/logging", () => {
|
|
|
157
134
|
),
|
|
158
135
|
);
|
|
159
136
|
|
|
160
|
-
it.effect("
|
|
137
|
+
it.effect("accepts uppercase RIVET_LOG_LEVEL values", () =>
|
|
161
138
|
Effect.gen(function* () {
|
|
162
139
|
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
163
140
|
|
|
164
141
|
assert.strictEqual(baseLogger.level, "debug");
|
|
165
142
|
}).pipe(
|
|
166
|
-
Effect.provideService(References.MinimumLogLevel, "Debug"),
|
|
167
143
|
Effect.provideService(
|
|
168
144
|
ConfigProvider.ConfigProvider,
|
|
169
145
|
ConfigProvider.fromEnv({
|
|
170
146
|
env: {
|
|
171
|
-
RIVET_LOG_LEVEL: "
|
|
147
|
+
RIVET_LOG_LEVEL: "DEBUG",
|
|
172
148
|
},
|
|
173
149
|
}),
|
|
174
150
|
),
|
|
175
151
|
),
|
|
176
152
|
);
|
|
177
153
|
|
|
178
|
-
it.effect("
|
|
154
|
+
it.effect("ignores Effect-only RIVET_LOG_LEVEL values", () =>
|
|
179
155
|
Effect.gen(function* () {
|
|
180
156
|
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
181
157
|
|
|
@@ -186,36 +162,45 @@ describe("internal/logging", () => {
|
|
|
186
162
|
ConfigProvider.ConfigProvider,
|
|
187
163
|
ConfigProvider.fromEnv({
|
|
188
164
|
env: {
|
|
189
|
-
RIVET_LOG_LEVEL: "
|
|
165
|
+
RIVET_LOG_LEVEL: "None",
|
|
190
166
|
},
|
|
191
167
|
}),
|
|
192
168
|
),
|
|
193
169
|
),
|
|
194
170
|
);
|
|
195
171
|
|
|
196
|
-
it.effect(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
Effect.gen(function* () {
|
|
200
|
-
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
172
|
+
it.effect("falls back to References.MinimumLogLevel without env", () =>
|
|
173
|
+
Effect.gen(function* () {
|
|
174
|
+
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
201
175
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
),
|
|
210
|
-
Effect.provideService(
|
|
211
|
-
ConfigProvider.ConfigProvider,
|
|
212
|
-
ConfigProvider.fromEnv({
|
|
213
|
-
env: {
|
|
214
|
-
RIVET_LOG_LEVEL: "Trace",
|
|
215
|
-
},
|
|
216
|
-
}),
|
|
217
|
-
),
|
|
176
|
+
assert.strictEqual(baseLogger.level, "debug");
|
|
177
|
+
}).pipe(
|
|
178
|
+
Effect.provideService(References.MinimumLogLevel, "Debug"),
|
|
179
|
+
Effect.provideService(
|
|
180
|
+
ConfigProvider.ConfigProvider,
|
|
181
|
+
ConfigProvider.fromEnv({
|
|
182
|
+
env: {},
|
|
183
|
+
}),
|
|
218
184
|
),
|
|
185
|
+
),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
it.effect("RIVET_LOG_LEVEL overrides References.MinimumLogLevel", () =>
|
|
189
|
+
Effect.gen(function* () {
|
|
190
|
+
const baseLogger = yield* Logging.makeDefaultBaseLogger;
|
|
191
|
+
|
|
192
|
+
assert.strictEqual(baseLogger.level, "silent");
|
|
193
|
+
}).pipe(
|
|
194
|
+
Effect.provideService(References.MinimumLogLevel, "Debug"),
|
|
195
|
+
Effect.provideService(
|
|
196
|
+
ConfigProvider.ConfigProvider,
|
|
197
|
+
ConfigProvider.fromEnv({
|
|
198
|
+
env: {
|
|
199
|
+
RIVET_LOG_LEVEL: "silent",
|
|
200
|
+
},
|
|
201
|
+
}),
|
|
202
|
+
),
|
|
203
|
+
),
|
|
219
204
|
);
|
|
220
205
|
|
|
221
206
|
it.effect(
|
|
@@ -229,19 +214,18 @@ describe("internal/logging", () => {
|
|
|
229
214
|
Effect.provideService(References.CurrentLogLevel, "Debug"),
|
|
230
215
|
Effect.provideService(References.MinimumLogLevel, "Debug"),
|
|
231
216
|
Effect.provide(
|
|
232
|
-
|
|
233
|
-
Logging.makeEffectLogger(baseLogger),
|
|
234
|
-
]),
|
|
217
|
+
Logger.layer([Logging.makeLogger(baseLogger)]),
|
|
235
218
|
),
|
|
236
219
|
);
|
|
237
220
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
221
|
+
const entry = entries[0];
|
|
222
|
+
assert.ok(entry !== undefined);
|
|
223
|
+
assert.strictEqual(entry.level, "debug");
|
|
224
|
+
assert.strictEqual(entry.msg, "plain log");
|
|
225
|
+
assert.deepStrictEqual(entry.fields, {
|
|
226
|
+
fiberId: entry.fields.fiberId,
|
|
227
|
+
});
|
|
228
|
+
assert.strictEqual(typeof entry.fields.fiberId, "string");
|
|
245
229
|
}),
|
|
246
230
|
);
|
|
247
231
|
|
|
@@ -256,9 +240,7 @@ describe("internal/logging", () => {
|
|
|
256
240
|
Effect.provideService(References.CurrentLogLevel, "None"),
|
|
257
241
|
Effect.provideService(References.MinimumLogLevel, "All"),
|
|
258
242
|
Effect.provide(
|
|
259
|
-
|
|
260
|
-
Logging.makeEffectLogger(baseLogger),
|
|
261
|
-
]),
|
|
243
|
+
Logger.layer([Logging.makeLogger(baseLogger)]),
|
|
262
244
|
),
|
|
263
245
|
);
|
|
264
246
|
|
|
@@ -276,18 +258,13 @@ describe("internal/logging", () => {
|
|
|
276
258
|
yield* Effect.logInfo("checkout complete").pipe(
|
|
277
259
|
Effect.withLogSpan("checkout"),
|
|
278
260
|
Effect.provide(
|
|
279
|
-
|
|
280
|
-
Logging.makeEffectLogger(baseLogger),
|
|
281
|
-
]),
|
|
261
|
+
Logger.layer([Logging.makeLogger(baseLogger)]),
|
|
282
262
|
),
|
|
283
263
|
);
|
|
284
264
|
|
|
285
265
|
assert.strictEqual(entries.length, 1);
|
|
286
266
|
assert.strictEqual(entries[0]?.level, "info");
|
|
287
267
|
assert.strictEqual(entries[0]?.msg, "checkout complete");
|
|
288
|
-
assert.deepStrictEqual(Object.keys(entries[0]?.fields ?? {}), [
|
|
289
|
-
"spans",
|
|
290
|
-
]);
|
|
291
268
|
const spans = entries[0]?.fields.spans as
|
|
292
269
|
| Record<string, unknown>
|
|
293
270
|
| undefined;
|
package/src/internal/logging.ts
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Cause,
|
|
3
2
|
Config,
|
|
4
3
|
Context,
|
|
5
4
|
Effect,
|
|
6
|
-
Logger
|
|
5
|
+
Logger,
|
|
6
|
+
Option,
|
|
7
|
+
Predicate,
|
|
8
|
+
Record as EffectRecord,
|
|
7
9
|
type LogLevel,
|
|
8
10
|
References,
|
|
9
11
|
} from "effect";
|
|
10
12
|
import type * as Rivetkit from "rivetkit";
|
|
11
|
-
import
|
|
12
|
-
configureDefaultLogger,
|
|
13
|
-
getBaseLogger,
|
|
14
|
-
type Logger as PinoLogger,
|
|
15
|
-
type LogLevel as PinoLogLevel,
|
|
16
|
-
} from "rivetkit/log";
|
|
13
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
17
14
|
|
|
18
15
|
const EMPTY_KEY = "/";
|
|
19
16
|
const KEY_SEPARATOR = "/";
|
|
@@ -24,25 +21,14 @@ type ActorLogContext = {
|
|
|
24
21
|
readonly actorId: string;
|
|
25
22
|
};
|
|
26
23
|
|
|
27
|
-
export class BaseLogger extends Context.Service<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const PinoLevelByEffectLevel: Record<LogLevel.LogLevel, PinoLogLevel> = {
|
|
32
|
-
All: "trace",
|
|
33
|
-
Trace: "trace",
|
|
34
|
-
Debug: "debug",
|
|
35
|
-
Info: "info",
|
|
36
|
-
Warn: "warn",
|
|
37
|
-
Error: "error",
|
|
38
|
-
Fatal: "fatal",
|
|
39
|
-
None: "silent",
|
|
40
|
-
};
|
|
24
|
+
export class BaseLogger extends Context.Service<
|
|
25
|
+
BaseLogger,
|
|
26
|
+
RivetkitLog.Logger
|
|
27
|
+
>()("@rivetkit/effect/RivetLogger/BaseLogger") {}
|
|
41
28
|
|
|
42
|
-
|
|
43
|
-
PinoLevelByEffectLevel[logLevel];
|
|
29
|
+
const RivetkitLogLevels = RivetkitLog.LogLevelSchema.options;
|
|
44
30
|
|
|
45
|
-
const
|
|
31
|
+
const EffectLevelByRivetkitLevel = {
|
|
46
32
|
trace: "Trace",
|
|
47
33
|
debug: "Debug",
|
|
48
34
|
info: "Info",
|
|
@@ -50,56 +36,54 @@ const EffectLevelByPinoLevel: Record<PinoLogLevel, LogLevel.LogLevel> = {
|
|
|
50
36
|
error: "Error",
|
|
51
37
|
fatal: "Fatal",
|
|
52
38
|
silent: "None",
|
|
53
|
-
}
|
|
39
|
+
} as const satisfies Record<
|
|
40
|
+
RivetkitLog.LogLevel,
|
|
41
|
+
Exclude<LogLevel.LogLevel, "All">
|
|
42
|
+
>;
|
|
43
|
+
|
|
44
|
+
const RivetkitLevelByEffectLevel = {
|
|
45
|
+
...Object.fromEntries(
|
|
46
|
+
RivetkitLogLevels.map((level) => [
|
|
47
|
+
EffectLevelByRivetkitLevel[level],
|
|
48
|
+
level,
|
|
49
|
+
]),
|
|
50
|
+
),
|
|
51
|
+
All: "trace",
|
|
52
|
+
} as Record<LogLevel.LogLevel, RivetkitLog.LogLevel>;
|
|
54
53
|
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
return EffectLevelByPinoLevel[pinoLevel as PinoLogLevel];
|
|
60
|
-
}
|
|
54
|
+
const rivetLogLevelFromEnv = Config.string("RIVET_LOG_LEVEL").pipe(
|
|
55
|
+
Effect.option,
|
|
56
|
+
Effect.map((maybeRivetLogLevel) => {
|
|
57
|
+
if (Option.isNone(maybeRivetLogLevel)) return Option.none();
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
const parsed = RivetkitLog.LogLevelSchema.safeParse(
|
|
60
|
+
maybeRivetLogLevel.value.toLowerCase(),
|
|
61
|
+
);
|
|
62
|
+
return parsed.success ? Option.some(parsed.data) : Option.none();
|
|
63
63
|
}),
|
|
64
64
|
);
|
|
65
65
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
66
|
+
export const makeDefaultBaseLogger: Effect.Effect<RivetkitLog.Logger> =
|
|
67
|
+
Effect.gen(function* () {
|
|
68
|
+
const maybeRivetLogLevel = yield* rivetLogLevelFromEnv;
|
|
69
|
+
const logLevel = Option.isSome(maybeRivetLogLevel)
|
|
70
|
+
? maybeRivetLogLevel.value
|
|
71
|
+
: RivetkitLevelByEffectLevel[yield* References.MinimumLogLevel];
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const context = yield* Effect.context();
|
|
74
|
-
const providedMinimumLogLevel = Context.getOrUndefined(
|
|
75
|
-
context,
|
|
76
|
-
References.MinimumLogLevel,
|
|
73
|
+
return yield* Effect.sync(() =>
|
|
74
|
+
RivetkitLog.makeDefaultLogger(logLevel),
|
|
77
75
|
);
|
|
78
|
-
|
|
79
|
-
const logLevel =
|
|
80
|
-
providedMinimumLogLevel !== undefined
|
|
81
|
-
? providedMinimumLogLevel
|
|
82
|
-
: envLogLevel._tag === "Some"
|
|
83
|
-
? envLogLevel.value
|
|
84
|
-
: yield* References.MinimumLogLevel;
|
|
85
|
-
|
|
86
|
-
return yield* Effect.sync(() => {
|
|
87
|
-
configureDefaultLogger(toPinoLevel(logLevel));
|
|
88
|
-
return getBaseLogger();
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
);
|
|
76
|
+
});
|
|
92
77
|
|
|
93
|
-
export const getOrCreateBaseLogger: Effect.Effect<
|
|
94
|
-
function* () {
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
return
|
|
78
|
+
export const getOrCreateBaseLogger: Effect.Effect<RivetkitLog.Logger> =
|
|
79
|
+
Effect.gen(function* () {
|
|
80
|
+
const maybeBaseLogger = yield* Effect.serviceOption(BaseLogger);
|
|
81
|
+
if (Option.isSome(maybeBaseLogger)) {
|
|
82
|
+
return maybeBaseLogger.value;
|
|
98
83
|
}
|
|
99
84
|
|
|
100
85
|
return yield* makeDefaultBaseLogger;
|
|
101
|
-
}
|
|
102
|
-
);
|
|
86
|
+
});
|
|
103
87
|
|
|
104
88
|
export function makeActorLogAnnotations(context: ActorLogContext): {
|
|
105
89
|
readonly actor: string;
|
|
@@ -131,59 +115,64 @@ export function serializeActorKey(key: Rivetkit.ActorKey): string {
|
|
|
131
115
|
.join(KEY_SEPARATOR);
|
|
132
116
|
}
|
|
133
117
|
|
|
134
|
-
function
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
export function makeLogger(
|
|
119
|
+
baseLogger: RivetkitLog.Logger,
|
|
120
|
+
): Logger.Logger<unknown, void> {
|
|
121
|
+
return Logger.make((options) => {
|
|
122
|
+
if (options.logLevel === "None") return;
|
|
123
|
+
const rivetkitLevel = RivetkitLevelByEffectLevel[options.logLevel];
|
|
124
|
+
const structured = Logger.formatStructured.log(options);
|
|
125
|
+
const { msg, fields: messageFields } = extractMessage(
|
|
126
|
+
structured.message,
|
|
127
|
+
);
|
|
128
|
+
const fields: Record<string, unknown> = {
|
|
129
|
+
...messageFields,
|
|
130
|
+
...structured.annotations,
|
|
131
|
+
fiberId: structured.fiberId,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
if (!EffectRecord.isEmptyRecord(structured.spans)) {
|
|
135
|
+
fields.spans = structured.spans;
|
|
136
|
+
}
|
|
137
|
+
if (structured.cause !== undefined) {
|
|
138
|
+
fields.cause = structured.cause;
|
|
139
|
+
}
|
|
138
140
|
|
|
139
|
-
|
|
141
|
+
const logger = baseLogger[rivetkitLevel];
|
|
142
|
+
if (msg === undefined) {
|
|
143
|
+
logger.call(baseLogger, fields);
|
|
144
|
+
} else {
|
|
145
|
+
logger.call(baseLogger, fields, msg);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
140
148
|
}
|
|
141
149
|
|
|
142
|
-
function
|
|
150
|
+
function extractMessage(message: unknown): {
|
|
143
151
|
readonly msg: string | undefined;
|
|
144
152
|
readonly fields: Record<string, unknown>;
|
|
145
153
|
} {
|
|
146
154
|
const values = Array.isArray(message) ? message : [message];
|
|
147
|
-
if (values.length === 0) {
|
|
148
|
-
return { msg: undefined, fields: {} };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const [first, ...rest] = values;
|
|
152
155
|
const fields: Record<string, unknown> = {};
|
|
156
|
+
const args: Array<unknown> = [];
|
|
153
157
|
let msg: string | undefined;
|
|
154
158
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
for (const [key, value] of Object.entries(firstFields)) {
|
|
161
|
-
if (key === "msg") {
|
|
162
|
-
if (value !== undefined) {
|
|
163
|
-
msg = String(value);
|
|
164
|
-
}
|
|
165
|
-
} else {
|
|
166
|
-
fields[key] = structuredValue(value);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
} else if (first !== undefined) {
|
|
170
|
-
msg = String(first);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const args: Array<unknown> = [];
|
|
174
|
-
for (const value of rest) {
|
|
175
|
-
if (value instanceof Error) {
|
|
159
|
+
for (const [index, value] of values.entries()) {
|
|
160
|
+
if (Predicate.isError(value)) {
|
|
161
|
+
fields.error = value;
|
|
162
|
+
if (index === 0) msg = value.message;
|
|
163
|
+
} else if (isStructuredError(value)) {
|
|
176
164
|
fields.error = value;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
fields[key] = structuredValue(fieldValue);
|
|
165
|
+
if (index === 0) msg = value.error;
|
|
166
|
+
} else if (Predicate.isObject(value)) {
|
|
167
|
+
if (index === 0) {
|
|
168
|
+
const { msg: valueMsg, ...rest } = value;
|
|
169
|
+
Object.assign(fields, rest);
|
|
170
|
+
if (valueMsg !== undefined) msg = String(valueMsg);
|
|
171
|
+
} else {
|
|
172
|
+
Object.assign(fields, value);
|
|
186
173
|
}
|
|
174
|
+
} else if (index === 0) {
|
|
175
|
+
msg = value === undefined ? undefined : String(value);
|
|
187
176
|
} else {
|
|
188
177
|
args.push(value);
|
|
189
178
|
}
|
|
@@ -196,42 +185,13 @@ function extractMessageAndFields(message: unknown): {
|
|
|
196
185
|
return { msg, fields };
|
|
197
186
|
}
|
|
198
187
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
):
|
|
202
|
-
return
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
fields[key] = structuredValue(value);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const spans: Record<string, number> = {};
|
|
212
|
-
for (const [label, startTime] of fiber.getRef(
|
|
213
|
-
References.CurrentLogSpans,
|
|
214
|
-
)) {
|
|
215
|
-
spans[label] = date.getTime() - startTime;
|
|
216
|
-
}
|
|
217
|
-
if (Object.keys(spans).length > 0) {
|
|
218
|
-
fields.spans = spans;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (cause.reasons.length > 0) {
|
|
222
|
-
fields.cause = Cause.pretty(cause);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const pinoLevel = toPinoLevel(logLevel);
|
|
226
|
-
if (pinoLevel === "silent") {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const logger = baseLogger[pinoLevel];
|
|
231
|
-
if (msg === undefined) {
|
|
232
|
-
logger.call(baseLogger, fields);
|
|
233
|
-
} else {
|
|
234
|
-
logger.call(baseLogger, fields, msg);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
188
|
+
function isStructuredError(
|
|
189
|
+
value: unknown,
|
|
190
|
+
): value is { readonly error: string; readonly name: string } {
|
|
191
|
+
return (
|
|
192
|
+
Predicate.hasProperty(value, "error") &&
|
|
193
|
+
Predicate.hasProperty(value, "name") &&
|
|
194
|
+
Predicate.isString(value.error) &&
|
|
195
|
+
Predicate.isString(value.name)
|
|
196
|
+
);
|
|
237
197
|
}
|
package/src/mod.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * as Action from "./Action.ts";
|
|
2
2
|
export * as Actor from "./Actor.ts";
|
|
3
3
|
export * as Client from "./Client.ts";
|
|
4
|
-
export * as Logger from "./Logger.ts";
|
|
5
4
|
export * as Registry from "./Registry.ts";
|
|
5
|
+
export * as RivetLogger from "./RivetLogger.ts";
|
|
6
6
|
export * as RivetError from "./RivetError.ts";
|
|
7
7
|
export * as State from "./State.ts";
|
package/dist/Logger.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Layer } from "effect";
|
|
2
|
-
import type { Logger as PinoLogger } from "rivetkit/log";
|
|
3
|
-
import { BaseLogger } from "./internal/logging.ts";
|
|
4
|
-
/**
|
|
5
|
-
* Builds a logging layer from a custom Pino-compatible logger.
|
|
6
|
-
*
|
|
7
|
-
* The layer installs the matching Effect logger and configures the underlying
|
|
8
|
-
* RivetKit TypeScript SDK logs to go through the same logger.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { Logger } from "@rivetkit/effect"
|
|
13
|
-
* import { pino } from "pino"
|
|
14
|
-
*
|
|
15
|
-
* const LoggerLive = Logger.layerPino(
|
|
16
|
-
* pino({ transport: { target: "pino-pretty" } })
|
|
17
|
-
* )
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
export declare const layerPino: (baseLogger: PinoLogger) => Layer.Layer<BaseLogger, never, never>;
|
|
21
|
-
/**
|
|
22
|
-
* Default RivetKit Effect logging layer.
|
|
23
|
-
*
|
|
24
|
-
* The layer creates a base logger from `References.MinimumLogLevel` and installs
|
|
25
|
-
* the Effect logger adapter. Applications that want custom formatting or
|
|
26
|
-
* transports should provide {@link layerPino} instead.
|
|
27
|
-
*/
|
|
28
|
-
export declare const layer: Layer.Layer<never>;
|
|
29
|
-
//# sourceMappingURL=Logger.d.ts.map
|
package/dist/Logger.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EACN,UAAU,EAGV,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,GAAI,YAAY,UAAU,0CAO9C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAEpC,CAAC"}
|