1
0
mirror of https://github.com/amir20/dozzle.git synced 2026-01-02 02:57:27 +01:00

Fixes tail size parameter (#22)

This commit is contained in:
Amir Raminfar
2019-05-14 10:57:27 -07:00
committed by GitHub
parent 512b03c098
commit 87dd7c3d3b
5 changed files with 27 additions and 26 deletions

View File

@@ -39,24 +39,24 @@ will bind to `localhost` on port `1224`. You can then use a reverse proxy to con
#### Changing base URL
dozzle by default mounts to "/". If you want to control the base path you can use the `--base` option. For example, if you want to mount at "/foobar",
then you can override by using `--base /foobar`. See env variables below for using `DOZZLE_BASE` to change this.
then you can override by using `--base /foobar`. See env variables below for using `DOZZLE_BASE` to change this.
$ docker run --volume=/var/run/docker.sock:/var/run/docker.sock -p 8080:8080 amir20/dozzle:latest --base /foobar
dozzle will be available at [http://localhost:8080/foobar/](http://localhost:8080/foobar/).
#### Environment variables and configuration
#### Environment variables and configuration
Dozzle follows the [12-factor](https://12factor.net/) model. Configurations can use the CLI flags or enviroment variables. The table below outlines all supported options and their respective env vars.
Dozzle follows the [12-factor](https://12factor.net/) model. Configurations can use the CLI flags or enviroment variables. The table below outlines all supported options and their respective env vars.
| Flag | Env Variable | Default |
| --- | --- | --- |
| Flag | Env Variable | Default |
| --- | --- | --- |
| `--addr` | `DOZZLE_ADDR` | `:8080` |
| `--base` | `DOZZLE_BASE` | `/` |
| `--level` | `DOZZLE_LEVEL` | `info` |
| n/a | `DOCKER_API_VERSION` | `1.38` |
| n/a | `TAIL_SIZE` | `300` |
| `--tailSize` | `DOZZLE_TAILSIZE` | `300` |
## License

View File

@@ -1,6 +1,7 @@
package docker
import (
"strconv"
"bytes"
"context"
"encoding/binary"
@@ -9,7 +10,6 @@ import (
"github.com/docker/docker/client"
"io"
"log"
"os"
"sort"
"strings"
)
@@ -27,8 +27,8 @@ type dockerProxy interface {
// Client is a proxy around the docker client
type Client interface {
ListContainers() ([]Container, error)
ContainerLogs(ctx context.Context, id string) (<-chan string, <-chan error)
Events(ctx context.Context) (<-chan events.Message, <-chan error)
ContainerLogs(context.Context, string, int) (<-chan string, <-chan error)
Events(context.Context) (<-chan events.Message, <-chan error)
}
// NewClient creates a new instance of Client
@@ -74,12 +74,8 @@ func (d *dockerClient) ListContainers() ([]Container, error) {
return containers, nil
}
func (d *dockerClient) ContainerLogs(ctx context.Context, id string) (<-chan string, <-chan error) {
tail := "300"
if value, ok := os.LookupEnv("TAIL_SIZE"); ok {
tail = value
}
options := types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: true, Tail: tail, Timestamps: true}
func (d *dockerClient) ContainerLogs(ctx context.Context, id string, tailSize int) (<-chan string, <-chan error) {
options := types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: true, Tail: strconv.Itoa(tailSize), Timestamps: true}
reader, err := d.cli.ContainerLogs(ctx, id, options)
errChannel := make(chan error, 1)

View File

@@ -30,7 +30,7 @@ func (m *mockedProxy) ContainerList(context.Context, types.ContainerListOptions)
}
func (m *mockedProxy) ContainerLogs(ctx context.Context, id string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
args := m.Called(ctx, id)
args := m.Called(ctx, id, options)
reader, ok := args.Get(0).(io.ReadCloser)
if !ok && args.Get(0) != nil {
panic("reader is not of type io.ReadCloser")
@@ -109,10 +109,11 @@ func Test_dockerClient_ContainerLogs_happy(t *testing.T) {
var reader io.ReadCloser
reader = ioutil.NopCloser(bytes.NewReader(b))
proxy.On("ContainerLogs", mock.Anything, id, mock.Anything).Return(reader, nil)
options := types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: true, Tail: "300", Timestamps: true}
proxy.On("ContainerLogs", mock.Anything, id, options).Return(reader, nil)
client := &dockerClient{proxy}
messages, _ := client.ContainerLogs(context.Background(), id)
messages, _ := client.ContainerLogs(context.Background(), id, 300)
actual, _ := <-messages
assert.Equal(t, expected, actual, "message doesn't match expected")
@@ -125,10 +126,12 @@ func Test_dockerClient_ContainerLogs_happy(t *testing.T) {
func Test_dockerClient_ContainerLogs_error(t *testing.T) {
id := "123456"
proxy := new(mockedProxy)
proxy.On("ContainerLogs", mock.Anything, id, mock.Anything).Return(nil, errors.New("test"))
client := &dockerClient{proxy}
messages, err := client.ContainerLogs(context.Background(), id)
messages, err := client.ContainerLogs(context.Background(), id, 300)
assert.Nil(t, messages, "messages should be nil")

View File

@@ -23,6 +23,7 @@ var (
addr = ""
base = ""
level = ""
tailSize = 300
version = "dev"
commit = "none"
date = "unknown"
@@ -37,6 +38,7 @@ func init() {
pflag.String("addr", ":8080", "http service address")
pflag.String("base", "/", "base address of the application to mount")
pflag.String("level", "info", "logging level")
pflag.Int("tailSize", 300, "Tail size to use for initial container logs")
pflag.Parse()
viper.AutomaticEnv()
@@ -46,6 +48,7 @@ func init() {
addr = viper.GetString("addr")
base = viper.GetString("base")
level = viper.GetString("level")
tailSize = viper.GetInt("tailSize")
l, _ := log.ParseLevel(level)
log.SetLevel(l)
@@ -153,8 +156,7 @@ func (h *handler) streamLogs(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}
messages, err := h.client.ContainerLogs(r.Context(), id)
messages, err := h.client.ContainerLogs(r.Context(), id, tailSize)
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")

View File

@@ -31,8 +31,8 @@ func (m *MockedClient) ListContainers() ([]docker.Container, error) {
return containers, args.Error(1)
}
func (m *MockedClient) ContainerLogs(ctx context.Context, id string) (<-chan string, <-chan error) {
args := m.Called(ctx, id)
func (m *MockedClient) ContainerLogs(ctx context.Context, id string, tailSize int) (<-chan string, <-chan error) {
args := m.Called(ctx, id, tailSize)
channel, ok := args.Get(0).(chan string)
if !ok {
panic("channel is not of type chan string")
@@ -91,7 +91,7 @@ func Test_handler_streamLogs_happy(t *testing.T) {
id := "123456"
req, err := http.NewRequest("GET", "/api/logs/stream", nil)
q := req.URL.Query()
q.Add("id", "123456")
q.Add("id", id)
req.URL.RawQuery = q.Encode()
require.NoError(t, err, "NewRequest should not return an error.")
@@ -101,7 +101,7 @@ func Test_handler_streamLogs_happy(t *testing.T) {
messages := make(chan string)
errChannel := make(chan error)
mockedClient.On("ContainerLogs", mock.Anything, id).Return(messages, errChannel)
mockedClient.On("ContainerLogs", mock.Anything, id, 300).Return(messages, errChannel)
go func() {
messages <- "INFO Testing logs..."
close(messages)
@@ -126,7 +126,7 @@ func Test_handler_streamLogs_error_reading(t *testing.T) {
mockedClient := new(MockedClient)
messages := make(chan string)
errChannel := make(chan error)
mockedClient.On("ContainerLogs", mock.Anything, id).Return(messages, errChannel)
mockedClient.On("ContainerLogs", mock.Anything, id, 300).Return(messages, errChannel)
go func() {
errChannel <- errors.New("test error")