Skip to content

Commit 500b829

Browse files
Merge pull request #22 from FireTail-io/hotfix/err-callback-nil-deref
Hotfix/err callback nil deref
2 parents a019391 + b16f55b commit 500b829

8 files changed

+116
-139
lines changed

README.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,22 @@ The latest extension version of the publically accessible Lambda Layer published
135135
arn:aws:lambda:us-east-1:247286868737:layer:firetail-extension-${ARCH}-${VERSION}:1
136136
```
137137

138-
For example, for `ARCH=arm64` and `VERSION=v1-0-0` this should yield:
138+
For example, for `ARCH=amd64` and `VERSION=v1-0-5` this should yield:
139139

140140
```
141-
arn:aws:lambda:us-east-1:247286868737:layer:firetail-extension-x86_64-v1-0-4:1
141+
arn:aws:lambda:us-east-1:247286868737:layer:firetail-extension-x86_64-v1-0-5:1
142142
```
143143

144+
Regardless of how you add the Lambda Layer to your Lambda Function, you will also need to configure at least one environment variable: `FIRETAIL_API_TOKEN`. Find below a full list of the environment variables used by the Firetail Lambda Extension:
145+
146+
| Environment Variable | Default Value | Description |
147+
| ------------------------ | ----------------------------------------------------------- | ------------------------------------------------------------ |
148+
| FIRETAIL_API_TOKEN | None | Your API token for the Firetail Logging API. If left unset, no logs will be sent to the Firetail Logging API |
149+
| FIRETAIL_API_URL | `https://api.logging.eu-west-1.prod.firetail.app/logs/bulk` | The URL of the Firetail Logging API |
150+
| FIRETAIL_EXTENSION_DEBUG | `false` | Enables debug logging from the extension if set to a value parsed as `true` by [strconv.ParseBool](https://pkg.go.dev/strconv#ParseBool) |
151+
| FIRETAIL_LOG_BUFFER_SIZE | `1000` | The maximum amount of logs the extension will hold in its buffer from which logs are batched and sent to Firetail |
152+
| FIRETAIL_MAX_BATCH_SIZE | `100` | The maximum size of a batch of logs to be sent to the Firetail logging API in one request |
153+
144154

145155

146156
#### Using The AWS CLI

logs_api_client.go

-28
This file was deleted.

logs_api_client_test.go

-100
This file was deleted.

logsapi/client.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"firetail-lambda-extension/firetail"
66
"net/http"
77
"sync"
8+
9+
"github.com/pkg/errors"
810
)
911

1012
type Client struct {
@@ -45,11 +47,22 @@ func NewClient(options Options) (*Client, error) {
4547
return client, nil
4648
}
4749

48-
func (c *Client) ListenAndServe() error {
49-
return c.httpServer.ListenAndServe()
50+
func (c *Client) Start(ctx context.Context) error {
51+
err := c.httpServer.ListenAndServe()
52+
53+
if err != http.ErrServerClosed {
54+
err = errors.WithMessage(err, "Log server closed unexpectedly")
55+
c.errCallback(err)
56+
c.Shutdown(ctx)
57+
} else if err != nil {
58+
c.errCallback(err)
59+
}
60+
61+
return err
5062
}
5163

5264
func (c *Client) Shutdown(ctx context.Context) error {
65+
err := c.httpServer.Shutdown(ctx)
5366
close(c.recordsChannel)
54-
return c.httpServer.Shutdown(ctx)
67+
return err
5568
}

logsapi/client_test.go

+48-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestNewClient(t *testing.T) {
4242
shutdownWaitgroup.Add(1)
4343
defer shutdownWaitgroup.Wait()
4444
go func() {
45-
err := client.ListenAndServe()
45+
err := client.Start(context.Background())
4646
assert.Equal(t, "http: Server closed", err.Error())
4747
shutdownWaitgroup.Done()
4848
}()
@@ -122,3 +122,50 @@ func TestNewClientSubscribeNoServer(t *testing.T) {
122122
// This may vary depending upon the runtime
123123
assert.Contains(t, err.Error(), "Err doing subscription request: Put \"http://127.0.0.1:0/2020-08-15/logs\"")
124124
}
125+
126+
func TestNewClientWithInvalidLogServerAddress(t *testing.T) {
127+
http.DefaultServeMux = new(http.ServeMux)
128+
runtimeApiServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
129+
fmt.Fprintf(w, `{"eventType": "SHUTDOWN"}`)
130+
}))
131+
defer runtimeApiServer.Close()
132+
133+
extensionID := "TEST_EXTENSION_ID"
134+
ctx := context.Background()
135+
136+
t.Setenv("AWS_LAMBDA_RUNTIME_API", strings.Join(strings.Split(runtimeApiServer.URL, ":")[1:], ":")[2:])
137+
logsApiClient, err := NewClient(
138+
Options{
139+
ExtensionID: extensionID,
140+
LogServerAddress: ":::",
141+
},
142+
)
143+
require.Nil(t, err)
144+
145+
var closeErr error
146+
errWaitgroup := sync.WaitGroup{}
147+
errWaitgroup.Add(1)
148+
go func() {
149+
closeErr = logsApiClient.Start(ctx)
150+
errWaitgroup.Done()
151+
}()
152+
153+
errWaitgroup.Wait()
154+
assert.Equal(t, "Log server closed unexpectedly: listen tcp: address :::: too many colons in address", closeErr.Error())
155+
}
156+
157+
func TestNewClientWithNoRuntimeApi(t *testing.T) {
158+
http.DefaultServeMux = new(http.ServeMux)
159+
160+
extensionID := "TEST_EXTENSION_ID"
161+
162+
t.Setenv("AWS_LAMBDA_RUNTIME_API", "127.0.0.1:0")
163+
_, err := NewClient(
164+
Options{
165+
ExtensionID: extensionID,
166+
LogServerAddress: "127.0.0.1:0",
167+
},
168+
)
169+
require.NotNil(t, err)
170+
assert.Contains(t, err.Error(), "Err doing subscription request")
171+
}

logsapi/record_receiver_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestRecordReceiverBatchCallbackFail(t *testing.T) {
4949
shutdownWaitgroup.Add(1)
5050
defer shutdownWaitgroup.Wait()
5151
go func() {
52-
err := client.ListenAndServe()
52+
err := client.Start(context.Background())
5353
assert.Equal(t, "http: Server closed", err.Error())
5454
shutdownWaitgroup.Done()
5555
}()
@@ -122,7 +122,7 @@ func TestRecordReceiverMaxBatchSize(t *testing.T) {
122122
shutdownWaitgroup.Add(1)
123123
defer shutdownWaitgroup.Wait()
124124
go func() {
125-
err := client.ListenAndServe()
125+
err := client.Start(context.Background())
126126
assert.Equal(t, "http: Server closed", err.Error())
127127
shutdownWaitgroup.Done()
128128
}()

main.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ func main() {
3535
}
3636
log.Println("Registered extension, ID:", extensionClient.ExtensionID)
3737

38-
// Create a logsApiClient & remember to shut it down when we're done
39-
logsApiClient, err := initLogsApiClient(logsapi.Options{
38+
// Create a logsApiClient, start it & remember to shut it down when we're done
39+
logsApiClient, err := logsapi.NewClient(logsapi.Options{
4040
ExtensionID: extensionClient.ExtensionID,
4141
LogServerAddress: "sandbox:1234",
42-
}, ctx)
42+
})
4343
if err != nil {
4444
panic(err)
4545
}
46+
go logsApiClient.Start(ctx)
4647
defer logsApiClient.Shutdown(ctx)
4748

4849
// awaitShutdown will block until a shutdown event is received, or the context is cancelled

main_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/http/httptest"
7+
"strings"
8+
"testing"
9+
)
10+
11+
func TestMain(t *testing.T) {
12+
http.DefaultServeMux = new(http.ServeMux)
13+
mockExtensionsApi := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14+
fmt.Fprintf(w, `{"eventType": "SHUTDOWN"}`)
15+
}))
16+
defer mockExtensionsApi.Close()
17+
18+
t.Setenv("AWS_LAMBDA_RUNTIME_API", strings.Join(strings.Split(mockExtensionsApi.URL, ":")[1:], ":")[2:])
19+
20+
main()
21+
}
22+
23+
func TestMainDebug(t *testing.T) {
24+
http.DefaultServeMux = new(http.ServeMux)
25+
mockExtensionsApi := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
26+
fmt.Fprintf(w, `{"eventType": "SHUTDOWN"}`)
27+
}))
28+
defer mockExtensionsApi.Close()
29+
30+
t.Setenv("AWS_LAMBDA_RUNTIME_API", strings.Join(strings.Split(mockExtensionsApi.URL, ":")[1:], ":")[2:])
31+
t.Setenv("FIRETAIL_EXTENSION_DEBUG", "true")
32+
33+
main()
34+
}

0 commit comments

Comments
 (0)