Compare commits
20 Commits
v8.12.8
...
sha-version
| Author | SHA1 | Date | |
|---|---|---|---|
| ee6e5a1112 | |||
| 0bb47d4dcf | |||
| ae7eee9bca | |||
| d98b84e24a | |||
| 18c87256cc | |||
| e96631930e | |||
| 76b1229341 | |||
| 440f9394d6 | |||
| ec792318e6 | |||
| 16db90b660 | |||
| eb22752b9a | |||
| 642ab45ef7 | |||
| 12fadb9348 | |||
| 1cf178e37d | |||
| 061cd0c445 | |||
| e8f796a7d6 | |||
| 78f94f1f16 | |||
| cc980361fd | |||
| 736ad8ed5b | |||
| d0dbd2051e |
@@ -35,7 +35,7 @@ pre_cmd = []
|
||||
rerun = false
|
||||
rerun_delay = 500
|
||||
send_interrupt = true
|
||||
stop_on_error = false
|
||||
stop_on_error = true
|
||||
|
||||
[color]
|
||||
app = ""
|
||||
|
||||
@@ -127,7 +127,9 @@ jobs:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
build-args: TAG=${{ steps.meta.outputs.version }}
|
||||
build-args: |
|
||||
TAG=${{ steps.meta.outputs.version }}
|
||||
SHA=${{ github.sha.substr(0,9) }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
@@ -45,7 +45,9 @@ jobs:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
build-args: TAG=${{ steps.meta.outputs.version }}
|
||||
build-args: |
|
||||
TAG=${{ steps.meta.outputs.version }}
|
||||
SHA=${{ github.sha.substr(0,9) }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
@@ -48,13 +48,14 @@ COPY --from=node /build/dist ./dist
|
||||
|
||||
# Args
|
||||
ARG TAG=dev
|
||||
ARG SHA=
|
||||
ARG TARGETOS TARGETARCH
|
||||
|
||||
# Generate protos
|
||||
RUN go generate
|
||||
|
||||
# Build binary
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/amir20/dozzle/internal/support/cli.Version=$TAG" -o dozzle
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/amir20/dozzle/internal/support/cli.Version=$TAG -X github.com/amir20/dozzle/internal/support/cli.SHA=$SHA" -o dozzle
|
||||
|
||||
RUN mkdir /data
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ PROTO_DIR := protos
|
||||
GEN_DIR := internal/agent/pb
|
||||
PROTO_FILES := $(wildcard $(PROTO_DIR)/*.proto)
|
||||
GEN_FILES := $(patsubst $(PROTO_DIR)/%.proto,$(GEN_DIR)/%.pb.go,$(PROTO_FILES))
|
||||
|
||||
SHA := $(shell git rev-parse --short HEAD)
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf dist
|
||||
@@ -26,11 +26,12 @@ test: fake_assets generate
|
||||
|
||||
.PHONY: build
|
||||
build: dist generate
|
||||
CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/amir20/dozzle/internal/support/cli.Version=local"
|
||||
echo "Building with SHA: $(SHA)"
|
||||
CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/amir20/dozzle/internal/support/cli.Version=local -X github.com/amir20/dozzle/internal/support/cli.SHA=$(SHA)"
|
||||
|
||||
.PHONY: docker
|
||||
docker: shared_key.pem shared_cert.pem
|
||||
@docker build --build-arg TAG=local -t amir20/dozzle .
|
||||
@docker build --build-arg TAG=local --build-arg SHA=$(SHA) -t amir20/dozzle .
|
||||
|
||||
generate: shared_key.pem shared_cert.pem $(GEN_FILES)
|
||||
|
||||
@@ -43,7 +44,7 @@ int:
|
||||
docker compose up --build --force-recreate --exit-code-from playwright
|
||||
|
||||
shared_key.pem:
|
||||
@openssl genpkey -algorithm RSA -out shared_key.pem -pkeyopt rsa_keygen_bits:2048
|
||||
@openssl genpkey -algorithm Ed25519 -out shared_key.pem
|
||||
|
||||
shared_cert.pem: shared_key.pem
|
||||
@openssl req -new -key shared_key.pem -out shared_request.csr -subj "/C=US/ST=California/L=San Francisco/O=Dozzle"
|
||||
|
||||
@@ -373,7 +373,7 @@ declare global {
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
// @ts-ignore
|
||||
export type { DrawerWidth } from './composable/drawer'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="dropdown dropdown-open w-full">
|
||||
<div class="dropdown dropdown-open w-full shadow-md">
|
||||
<div class="input input-xl input-primary flex w-full items-center">
|
||||
<mdi:magnify class="flex size-8" />
|
||||
<input
|
||||
|
||||
@@ -11,18 +11,26 @@
|
||||
<textarea
|
||||
v-model="query"
|
||||
class="textarea textarea-primary w-full font-mono text-lg"
|
||||
:class="{ 'textarea-error': error }"
|
||||
:class="{ 'textarea-error!': error }"
|
||||
:disabled="state === 'downloading'"
|
||||
></textarea>
|
||||
<div class="label max-h-48 overflow-y-auto pr-2">
|
||||
<span class="label-text-alt text-error" v-if="error">{{ error }}</span>
|
||||
<span class="label-text-alt" v-else>
|
||||
Total {{ results.numRows }} records
|
||||
<template v-if="results.numRows > pageLimit"> . Showing first {{ page.numRows }}. </template>
|
||||
<div class="mt-2">
|
||||
<span class="text-error" v-if="error">{{ error }}</span>
|
||||
<span v-else-if="state === 'initializing'">{{ $t("analytics.creating_table") }}</span>
|
||||
<span v-else-if="state === 'downloading'">{{
|
||||
$t("analytics.downloading", { size: formatBytes(bytes, { decimals: 1 }) })
|
||||
}}</span>
|
||||
<span v-else-if="evaluating">{{ $t("analytics.evaluating_query") }}</span>
|
||||
<span v-else>
|
||||
{{ $t("analytics.total_records", { count: results.numRows.toLocaleString() }) }}
|
||||
<template v-if="results.numRows > pageLimit">{{
|
||||
$t("analytics.showing_first", { count: page.numRows.toLocaleString() })
|
||||
}}</template>
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</section>
|
||||
<SQLTable :table="page" :loading="evaluating || !isReady" />
|
||||
<SQLTable :table="page" :loading="evaluating || state !== 'ready'" />
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
@@ -30,12 +38,15 @@
|
||||
<script setup lang="ts">
|
||||
import { Container } from "@/models/Container";
|
||||
import { type Table } from "@apache-arrow/esnext-esm";
|
||||
|
||||
const { container } = defineProps<{ container: Container }>();
|
||||
const query = ref("SELECT * FROM logs LIMIT 100");
|
||||
const error = ref<string | null>(null);
|
||||
const debouncedQuery = debouncedRef(query, 500);
|
||||
const evaluating = ref(false);
|
||||
const pageLimit = 1000;
|
||||
const state = ref<"downloading" | "ready" | "initializing">("downloading");
|
||||
const bytes = ref(0);
|
||||
|
||||
const url = withBase(
|
||||
`/api/hosts/${container.host}/containers/${container.id}/logs?stdout=1&stderr=1&everything&jsonOnly`,
|
||||
@@ -51,27 +62,49 @@ if (!response.ok) {
|
||||
const { db, conn } = await useDuckDB();
|
||||
const empty = await conn.query<Record<string, any>>(`SELECT 1 LIMIT 0`);
|
||||
|
||||
const { isReady } = useAsyncState(
|
||||
async () => {
|
||||
await db.registerFileBuffer("logs.json", new Uint8Array(await response.arrayBuffer()));
|
||||
onMounted(async () => {
|
||||
try {
|
||||
state.value = "downloading";
|
||||
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) throw new Error("No reader available from stream");
|
||||
|
||||
const chunks: Uint8Array[] = [];
|
||||
bytes.value = 0;
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
chunks.push(value);
|
||||
bytes.value += value.length;
|
||||
}
|
||||
|
||||
const arrayBuffer = new Uint8Array(bytes.value);
|
||||
let position = 0;
|
||||
for (const chunk of chunks) {
|
||||
arrayBuffer.set(chunk, position);
|
||||
position += chunk.length;
|
||||
}
|
||||
|
||||
await db.registerFileBuffer("logs.json", arrayBuffer);
|
||||
|
||||
state.value = "initializing";
|
||||
await conn.query(
|
||||
`CREATE TABLE logs AS SELECT unnest(m) FROM read_json('logs.json', ignore_errors = true, format = 'newline_delimited')`,
|
||||
);
|
||||
},
|
||||
undefined,
|
||||
{
|
||||
onError: (e) => {
|
||||
console.error(e);
|
||||
if (e instanceof Error) {
|
||||
error.value = e.message;
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
state.value = "ready";
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e instanceof Error) {
|
||||
error.value = e.message;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const results = computedAsync(
|
||||
async () => {
|
||||
if (isReady.value) {
|
||||
if (state.value === "ready") {
|
||||
return await conn.query<Record<string, any>>(debouncedQuery.value);
|
||||
} else {
|
||||
return empty;
|
||||
@@ -89,7 +122,10 @@ const results = computedAsync(
|
||||
},
|
||||
);
|
||||
|
||||
whenever(evaluating, () => (error.value = null));
|
||||
whenever(evaluating, () => {
|
||||
error.value = null;
|
||||
state.value = "ready";
|
||||
});
|
||||
const page = computed(() =>
|
||||
results.value.numRows > pageLimit ? results.value.slice(0, pageLimit) : results.value,
|
||||
) as unknown as ComputedRef<Table<Record<string, any>>>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="toast toast-end whitespace-normal max-md:m-0 max-md:w-full">
|
||||
<div class="toast toast-end whitespace-normal max-md:end-auto max-md:m-0 max-md:max-w-full">
|
||||
<div
|
||||
class="alert max-w-xl max-md:rounded-none"
|
||||
class="alert max-w-xl shadow-sm max-md:rounded-none"
|
||||
v-for="{ toast, options: { timed } } in toasts"
|
||||
:key="toast.id"
|
||||
:class="{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
<label
|
||||
class="btn btn-circle swap bg-base-content/10 swap-rotate border-base-content/20 hover:border-primary fixed bottom-4 -left-12 w-16 transition-all hover:-left-4"
|
||||
class="btn btn-circle swap bg-base-content/10 swap-rotate border-base-content/20 hover:border-primary fixed bottom-4 -left-12 w-16 shadow-sm transition-all hover:-left-4"
|
||||
:class="{ '-left-6!': collapseNav }"
|
||||
v-if="!isMobile && !forceMenuHidden"
|
||||
>
|
||||
@@ -34,7 +34,7 @@
|
||||
<mdi:chevron-left class="swap-off" />
|
||||
</label>
|
||||
</div>
|
||||
<dialog ref="modal" class="modal items-start bg-white/15 backdrop-blur-xs transition-none!" @close="open = false">
|
||||
<dialog ref="modal" class="modal bg-base-300/50! items-start backdrop-blur-md transition-none!" @close="open = false">
|
||||
<div class="modal-box max-w-2xl bg-transparent pt-20 shadow-none">
|
||||
<FuzzySearchModal @close="open = false" v-if="open" />
|
||||
</div>
|
||||
|
||||
@@ -95,7 +95,7 @@ services:
|
||||
|
||||
playwright:
|
||||
container_name: playwright
|
||||
image: mcr.microsoft.com/playwright:v1.51.1-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.52.0-jammy
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
|
||||
@@ -180,7 +180,7 @@ This will mount the `cert.pem` and `key.pem` files to the agent. The agent will
|
||||
To generate certificates, you can use the following command:
|
||||
|
||||
```sh
|
||||
$ openssl genpkey -algorithm RSA -out key.pem -pkeyopt rsa_keygen_bits:2048
|
||||
$ openssl genpkey -algorithm Ed25519 -out key.pem
|
||||
$ openssl req -new -key key.pem -out request.csr -subj "/C=US/ST=California/L=San Francisco/O=My Company"
|
||||
$ openssl x509 -req -in request.csr -signkey key.pem -out cert.pem -days 365
|
||||
```
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -4,7 +4,7 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/alexflint/go-arg v1.5.1
|
||||
github.com/beme/abide v0.0.0-20190723115211-635a09831760
|
||||
github.com/docker/docker v28.0.4+incompatible
|
||||
github.com/docker/docker v28.1.1+incompatible
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
@@ -32,7 +32,7 @@ require (
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/samber/lo v1.49.1
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
github.com/yuin/goldmark v1.7.10
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/sync v0.13.0
|
||||
google.golang.org/grpc v1.71.1
|
||||
|
||||
@@ -36,6 +36,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok=
|
||||
github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.1.0+incompatible h1:4iqpcWQCt3Txcz7iWIb1U3SZ/n9ffo4U+ryY5/3eOp0=
|
||||
github.com/docker/docker v28.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I=
|
||||
github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
@@ -196,6 +200,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark v1.7.9 h1:rVSeT+f7/lAM+bJHVm5YHGwNrnd40i1Ch2DEocEjHQ0=
|
||||
github.com/yuin/goldmark v1.7.9/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
github.com/yuin/goldmark v1.7.10 h1:S+LrtBjRmqMac2UdtB6yyCEJm+UILZ2fefI4p7o0QpI=
|
||||
github.com/yuin/goldmark v1.7.10/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
var Version = "head"
|
||||
var SHA = ""
|
||||
|
||||
type Args struct {
|
||||
Addr string `arg:"env:DOZZLE_ADDR" default:":8080" help:"sets host:port to bind for server. This is rarely needed inside a docker container."`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
@@ -111,7 +112,15 @@ func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request)
|
||||
lastSeenId = uint32(num)
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(w)
|
||||
var encoder *json.Encoder
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
writer := gzip.NewWriter(w)
|
||||
defer writer.Close()
|
||||
encoder = json.NewEncoder(writer)
|
||||
} else {
|
||||
encoder = json.NewEncoder(w)
|
||||
}
|
||||
|
||||
for {
|
||||
if buffer.Len() > minimum {
|
||||
|
||||
@@ -3,9 +3,11 @@ package web
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/amir20/dozzle/internal/support/cli"
|
||||
)
|
||||
|
||||
func (h *handler) version(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
fmt.Fprintf(w, "<pre>%v</pre>", h.config.Version)
|
||||
fmt.Fprintf(w, "<pre>%v commit: %v</pre>", h.config.Version, cli.SHA)
|
||||
}
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Kopieret
|
||||
message: Log kopieret til clipboard
|
||||
analytics:
|
||||
creating_table: Opretter midlertidig tabel...
|
||||
downloading: Henter containerlogfiler... ({size})
|
||||
evaluating_query: Evaluerer forespørgsel...
|
||||
total_records: I alt {count} poster.
|
||||
showing_first: Viser de første {count}.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Kopiert
|
||||
message: Log in Zwischenablage kopiert
|
||||
analytics:
|
||||
creating_table: Temporäre Tabelle wird erstellt...
|
||||
downloading: Container-Logs werden abgerufen... ({size})
|
||||
evaluating_query: Abfrage wird ausgewertet...
|
||||
total_records: Insgesamt {count} Datensätze.
|
||||
showing_first: Zeige die ersten {count}.
|
||||
|
||||
@@ -119,3 +119,9 @@ toasts:
|
||||
copied:
|
||||
title: Copied
|
||||
message: Log copied to clipboard
|
||||
analytics:
|
||||
creating_table: Creating temporary table...
|
||||
downloading: Fetching container logs... ({size})
|
||||
evaluating_query: Evaluating query...
|
||||
total_records: Total {count} records.
|
||||
showing_first: Showing first {count}.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Copiado
|
||||
message: Registro copiado al portapapeles
|
||||
analytics:
|
||||
creating_table: Creando tabla temporal...
|
||||
downloading: Obteniendo registros de contenedores... ({size})
|
||||
evaluating_query: Evaluando consulta...
|
||||
total_records: Total {count} registros.
|
||||
showing_first: Mostrando los primeros {count}.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Copié
|
||||
message: Journal copié dans le presse-papiers
|
||||
analytics:
|
||||
creating_table: Création d'une table temporaire...
|
||||
downloading: Récupération des journaux des conteneurs... ({size})
|
||||
evaluating_query: Évaluation de la requête...
|
||||
total_records: Total de {count} enregistrements.
|
||||
showing_first: Affichage des {count} premiers.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Copiato
|
||||
message: Log copiato nella clipboard
|
||||
analytics:
|
||||
creating_table: Creazione tabella temporanea...
|
||||
downloading: Recupero dei log dei container... ({size})
|
||||
evaluating_query: Valutazione della query...
|
||||
total_records: Totale {count} record.
|
||||
showing_first: Mostrati i primi {count}.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Skopiowany
|
||||
message: Log skopiowany do schowka
|
||||
analytics:
|
||||
creating_table: Tworzenie tymczasowej tabeli...
|
||||
downloading: Pobieranie logów kontenerów... ({size})
|
||||
evaluating_query: Przetwarzanie zapytania...
|
||||
total_records: Razem {count} rekordów.
|
||||
showing_first: Pokazywanie pierwszych {count}.
|
||||
|
||||
@@ -109,3 +109,10 @@ settings:
|
||||
start-line: Esta é uma mensagem de erro multi-linha
|
||||
middle-line: com uma segunda linha
|
||||
end-line: e finalmente uma terceira linha.
|
||||
|
||||
analytics:
|
||||
creating_table: A criar tabela temporária...
|
||||
downloading: A obter registos dos contentores... ({size})
|
||||
evaluating_query: A avaliar consulta...
|
||||
total_records: Total de {count} registos.
|
||||
showing_first: A mostrar os primeiros {count}.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Copiado
|
||||
message: Log copiado para a área de transferência
|
||||
analytics:
|
||||
creating_table: Criando tabela temporária...
|
||||
downloading: Buscando logs dos containers... ({size})
|
||||
evaluating_query: Avaliando consulta...
|
||||
total_records: Total de {count} registros.
|
||||
showing_first: Mostrando os primeiros {count}.
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: Copied
|
||||
message: Log copied to clipboard
|
||||
analytics:
|
||||
creating_table: Создание временной таблицы...
|
||||
downloading: Получение логов контейнеров... ({size})
|
||||
evaluating_query: Выполнение запроса...
|
||||
total_records: Всего {count} записей.
|
||||
showing_first: Показаны первые {count}.
|
||||
|
||||
@@ -107,3 +107,9 @@ toasts:
|
||||
copied:
|
||||
title: Kopyalandı
|
||||
message: Günlük panoya kopyalandı
|
||||
analytics:
|
||||
creating_table: Geçici tablo oluşturuluyor...
|
||||
downloading: Konteyner günlükleri alınıyor... ({size})
|
||||
evaluating_query: Sorgu değerlendiriliyor...
|
||||
total_records: Toplam {count} kayıt.
|
||||
showing_first: İlk {count} gösteriliyor.
|
||||
|
||||
@@ -116,4 +116,10 @@ log_actions:
|
||||
toasts:
|
||||
copied:
|
||||
title: 已複製
|
||||
message: 日誌已複製到剪貼簿
|
||||
message: 日誌已複製到剪貼簿
|
||||
analytics:
|
||||
creating_table: 正在建立臨時資料表...
|
||||
downloading: 正在取得容器日誌... ({size})
|
||||
evaluating_query: 正在評估查詢...
|
||||
total_records: 共計 {count} 筆記錄。
|
||||
showing_first: 顯示前 {count} 筆。
|
||||
|
||||
@@ -114,3 +114,9 @@ toasts:
|
||||
copied:
|
||||
title: 已复制
|
||||
message: 日志已复制到剪贴板
|
||||
analytics:
|
||||
creating_table: 正在创建临时表...
|
||||
downloading: 正在获取容器日志... ({size})
|
||||
evaluating_query: 正在评估查询...
|
||||
total_records: 总共 {count} 条记录。
|
||||
showing_first: 显示前 {count} 条。
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "dozzle",
|
||||
"version": "8.12.8",
|
||||
"version": "8.12.10",
|
||||
"description": "Realtime log viewer for docker containers.",
|
||||
"homepage": "https://github.com/amir20/dozzle#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/amir20/dozzle/issues"
|
||||
},
|
||||
"packageManager": "pnpm@10.8.0",
|
||||
"packageManager": "pnpm@10.8.1",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -33,7 +33,7 @@
|
||||
"@iconify-json/carbon": "^1.2.8",
|
||||
"@iconify-json/cil": "^1.2.2",
|
||||
"@iconify-json/ic": "^1.2.2",
|
||||
"@iconify-json/material-symbols": "^1.2.19",
|
||||
"@iconify-json/material-symbols": "^1.2.20",
|
||||
"@iconify-json/mdi": "^1.2.3",
|
||||
"@iconify-json/mdi-light": "^1.2.2",
|
||||
"@iconify-json/octicon": "^1.2.5",
|
||||
@@ -41,7 +41,7 @@
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.5",
|
||||
"@oddbird/css-anchor-positioning": "^0.5.1",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tailwindcss/vite": "4.1.3",
|
||||
"@tailwindcss/vite": "4.1.4",
|
||||
"@vueuse/components": "^13.1.0",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"@vueuse/integrations": "^13.1.0",
|
||||
@@ -55,7 +55,7 @@
|
||||
"d3-selection": "^3.0.0",
|
||||
"d3-shape": "^3.2.0",
|
||||
"d3-transition": "^3.0.1",
|
||||
"daisyui": "5.0.19",
|
||||
"daisyui": "5.0.27",
|
||||
"date-fns": "^4.1.0",
|
||||
"entities": "^6.0.0",
|
||||
"fuse.js": "^7.1.0",
|
||||
@@ -64,13 +64,13 @@
|
||||
"sortablejs": "^1.15.6",
|
||||
"splitpanes": "^4.0.3",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"tailwindcss": "4.1.3",
|
||||
"tailwindcss": "4.1.4",
|
||||
"unplugin-auto-import": "^19.1.2",
|
||||
"unplugin-icons": "^22.1.0",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"unplugin-vue-components": "^28.5.0",
|
||||
"unplugin-vue-macros": "^2.14.5",
|
||||
"unplugin-vue-router": "^0.12.0",
|
||||
"vite": "6.2.6",
|
||||
"vite": "6.3.2",
|
||||
"vite-plugin-compression2": "^1.3.3",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vite-svg-loader": "^5.1.0",
|
||||
@@ -81,10 +81,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apache-arrow/esnext-esm": "^19.0.1",
|
||||
"@iconify-json/material-symbols-light": "^1.2.19",
|
||||
"@iconify-json/material-symbols-light": "^1.2.20",
|
||||
"@iconify-json/ri": "^1.2.5",
|
||||
"@pinia/testing": "^1.0.1",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@types/d3-array": "^3.2.1",
|
||||
"@types/d3-ease": "^3.0.2",
|
||||
"@types/d3-scale": "^4.0.9",
|
||||
|
||||