11import fetch from 'node-fetch' ;
22import { FunctionLogEvent } from '~/aws/events' ;
3- import { function as F , array as A } from 'fp-ts' ;
3+ import { function as F , array as A , either as E } from 'fp-ts' ;
4+ import { z } from 'zod' ;
5+
6+ // @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/logger/#standard-structured-keys
7+ export const powertoolsLogSchema = z
8+ . object ( {
9+ level : z . string ( ) , // Logging level set for the Lambda function's invocation
10+ message : z . string ( ) , // A descriptive, human-readable representation of this log item
11+ timestamp : z . string ( ) , // Timestamp string in simplified extended ISO format (ISO 8601)
12+ service : z . string ( ) , // A unique name identifier of the service this Lambda function belongs to, by default service_undefined
13+ xray_trace_id : z . string ( ) . optional ( ) , // X-Ray Trace ID. Always present in Lambda environment, but not sent locally.
14+ sampling_rate : z . number ( ) . optional ( ) , // When enabled, it prints all the logs of a percentage of invocations, e.g. 10%
15+ error : z . string ( ) . optional ( ) , // Optional - An object containing information about the Error passed to the logger
16+ } )
17+ . passthrough ( ) ;
18+
19+ export type PowertoolsLogRecord = z . infer < typeof powertoolsLogSchema > ;
20+
21+ export const parseMessageWithPowertoolsLogFormat = ( message : string ) : E . Either < Error , PowertoolsLogRecord > =>
22+ F . pipe (
23+ E . tryCatch (
24+ ( ) : unknown => JSON . parse ( message ) ,
25+ ( reason ) => new Error ( `String is not JSON: ${ reason } ` ) ,
26+ ) ,
27+ E . chain ( ( entry ) => {
28+ const result = powertoolsLogSchema . safeParse ( entry ) ;
29+
30+ if ( result . success ) {
31+ return E . right ( result . data ) ;
32+ } else {
33+ return E . left ( new Error ( `Message is not in lambda powertools format` ) ) ;
34+ }
35+ } ) ,
36+ ) ;
437
538export const logtailLogForwarder =
639 ( token : string , ingestionUrl : string , listener : { logsQueue : FunctionLogEvent [ ] } ) => ( ) : Promise < void > => {
@@ -15,10 +48,23 @@ export const logtailLogForwarder =
1548 body : JSON . stringify (
1649 F . pipe (
1750 logs ,
18- A . map ( ( log ) => ( {
19- dt : log . time ,
20- message : log . record ,
21- } ) ) ,
51+ A . map ( ( log ) =>
52+ F . pipe (
53+ log . record ,
54+ parseMessageWithPowertoolsLogFormat ,
55+ E . fold (
56+ ( ) => ( {
57+ dt : log . time ,
58+ message : log . record ,
59+ } ) ,
60+ ( { message, ...data } ) => ( {
61+ dt : log . time ,
62+ message,
63+ data,
64+ } ) ,
65+ ) ,
66+ ) ,
67+ ) ,
2268 ) ,
2369 ) ,
2470 headers : {
0 commit comments