Skip to content

Commit

Permalink
Merge pull request #274 from simulot:simulot/issue273
Browse files Browse the repository at this point in the history
Better logs
  • Loading branch information
simulot authored Jun 1, 2024
2 parents c98b3f9 + 088a117 commit ef8d972
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 40 deletions.
6 changes: 3 additions & 3 deletions browser/files/localassets.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ nextFile:
t := la.sm.TypeFromExt(ext)
switch t {
default:
la.log.Record(ctx, fileevent.DiscoveredDiscarded, nil, fileName, "reason", "unsupported file type")
la.log.Record(ctx, fileevent.DiscoveredUnsupported, nil, fileName, "reason", "unsupported file type")
continue nextFile
case immich.TypeIgnored:
la.log.Record(ctx, fileevent.DiscoveredDiscarded, nil, fileName, "reason", "useless file")
la.log.Record(ctx, fileevent.DiscoveredUnsupported, nil, fileName, "reason", "useless file")
continue nextFile
case immich.TypeSidecar:
la.log.Record(ctx, fileevent.DiscoveredSidecar, nil, fileName)
Expand Down Expand Up @@ -182,7 +182,7 @@ func (la *LocalAssetBrowser) checkSidecar(ctx context.Context, f *browser.LocalA
FileName: path.Join(dir, e.Name()),
OnFSsys: true,
}
la.log.Record(ctx, fileevent.AnalysisAssociatedMetadata, nil, f.FileName, "main", f.FileName)
la.log.Record(ctx, fileevent.AnalysisAssociatedMetadata, nil, path.Join(dir, e.Name()), "main", f.FileName)
return true
}
}
Expand Down
15 changes: 13 additions & 2 deletions cmd/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type SharedFlags struct {
TimeZone string // Override default TZ
SkipSSL bool // Skip SSL Verification
NoUI bool // Disable user interface
JSONLog bool // Enable JSON structured log

Immich immich.ImmichInterface // Immich client
Log *slog.Logger // Logger
Expand All @@ -53,6 +54,7 @@ func (app *SharedFlags) InitSharedFlags() {
app.SkipSSL = false
app.LogLevel = "INFO"
app.NoUI = false
app.JSONLog = false
}

// SetFlag add common flags to a flagset
Expand All @@ -65,6 +67,7 @@ func (app *SharedFlags) SetFlags(fs *flag.FlagSet) {
fs.BoolFunc("no-colors-log", "Disable colors on logs", myflag.BoolFlagFn(&app.NoLogColors, app.NoLogColors))
fs.StringVar(&app.LogLevel, "log-level", app.LogLevel, "Log level (DEBUG|INFO|WARN|ERROR), default INFO")
fs.StringVar(&app.LogFile, "log-file", app.LogFile, "Write log messages into the file")
fs.BoolFunc("log-json", "Output line-delimited JSON file, default FALSE", myflag.BoolFlagFn(&app.JSONLog, app.JSONLog))
fs.BoolFunc("api-trace", "enable api call traces", myflag.BoolFlagFn(&app.APITrace, app.APITrace))
fs.BoolFunc("debug", "enable debug messages", myflag.BoolFlagFn(&app.Debug, app.Debug))
fs.StringVar(&app.TimeZone, "time-zone", app.TimeZone, "Override the system time zone")
Expand Down Expand Up @@ -100,8 +103,7 @@ func (app *SharedFlags) Start(ctx context.Context) error {
if err != nil {
return err
}
app.Log = slog.New(humane.NewHandler(f, &humane.Options{Level: app.Level}))
app.Jnl.SetLogger(app.Log)
app.SetLogWriter(f)
app.LogWriterCloser = f
}
}
Expand Down Expand Up @@ -176,3 +178,12 @@ func (app *SharedFlags) Start(ctx context.Context) error {
}
return nil
}

func (app *SharedFlags) SetLogWriter(w io.Writer) {
if app.JSONLog {
app.Log = slog.New(slog.NewJSONHandler(w, &slog.HandlerOptions{}))
} else {
app.Log = slog.New(humane.NewHandler(w, &humane.Options{Level: app.Level}))
}
app.Jnl.SetLogger(app.Log)
}
5 changes: 2 additions & 3 deletions cmd/upload/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/navidys/tvxwidgets"
"github.com/rivo/tview"
"github.com/simulot/immich-go/helpers/fileevent"
"github.com/telemachus/humane"
)

type page struct {
Expand Down Expand Up @@ -88,9 +87,9 @@ func (p *page) Page() *tview.Application {

if p.app.SharedFlags.LogWriterCloser != nil {
w := io.MultiWriter(p.app.SharedFlags.LogWriterCloser, p.logView)
p.app.SharedFlags.Log = slog.New(humane.NewHandler(w, &humane.Options{Level: p.app.SharedFlags.Level}))
p.app.SetLogWriter(w)
} else {
p.app.SharedFlags.Log = slog.New(humane.NewHandler(p.logView, &humane.Options{Level: p.app.SharedFlags.Level}))
p.app.SetLogWriter(p.logView)
}
p.app.SharedFlags.Jnl.SetLogger(p.app.SharedFlags.Log)
p.logView.SetBorder(true).SetTitle("Log")
Expand Down
24 changes: 17 additions & 7 deletions cmd/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,22 +245,28 @@ func (app *UpCmd) runNoUI(ctx context.Context) error {
if maxImmich > 0 {
immichPct = 100 * currImmich / maxImmich
}
ScannedAssets := counts[fileevent.DiscoveredImage] + counts[fileevent.DiscoveredVideo]
ProcessedAssets := counts[fileevent.UploadNotSelected] +
counts[fileevent.UploadUpgraded] +
counts[fileevent.UploadServerDuplicate] +
counts[fileevent.UploadServerBetter] +
counts[fileevent.Uploaded] +
counts[fileevent.AnalysisLocalDuplicate] + counts[fileevent.AnalysisMissingAssociatedMetadata]
if app.GooglePhotos {
gpPct := 0
upPct := 0
if counts[fileevent.DiscoveredImage]+counts[fileevent.DiscoveredVideo] > 0 {
gpPct = int(100 * counts[fileevent.AnalysisAssociatedMetadata] / (counts[fileevent.DiscoveredImage] + counts[fileevent.DiscoveredVideo]))
if ScannedAssets > 0 {
gpPct = int(100 * counts[fileevent.AnalysisAssociatedMetadata] / ScannedAssets)
upPct = int(100 * (counts[fileevent.UploadNotSelected] +
counts[fileevent.UploadUpgraded] +
counts[fileevent.UploadServerDuplicate] +
counts[fileevent.UploadServerBetter] +
counts[fileevent.Uploaded] +
counts[fileevent.AnalysisLocalDuplicate]) /
(counts[fileevent.DiscoveredImage] + counts[fileevent.DiscoveredVideo]))
counts[fileevent.AnalysisLocalDuplicate]) / ScannedAssets)
}
s = fmt.Sprintf("\rImmich read %d%%, Google Photos Analysis: %d%%, Uploaded %d%% %s", immichPct, gpPct, upPct, string(spinner[spinIdx]))
s = fmt.Sprintf("\rImmich read %d%%, Google Photos Analysis: %d%%, Upload errors: %d, Uploaded %d%% %s", immichPct, gpPct, counts[fileevent.UploadServerError], upPct, string(spinner[spinIdx]))
} else {
s = fmt.Sprintf("\rImmich read %d%%, Uploaded %d %s", immichPct, counts[fileevent.Uploaded], string(spinner[spinIdx]))
s = fmt.Sprintf("\rImmich read %d%%, Processed %d, Upload errors: %d, Uploaded %d %s", immichPct, ProcessedAssets, counts[fileevent.UploadServerError], counts[fileevent.Uploaded], string(spinner[spinIdx]))
}
spinIdx++
if spinIdx == len(spinner) {
Expand Down Expand Up @@ -382,6 +388,9 @@ func (app *UpCmd) getImmichAssets(ctx context.Context, updateFn progressUpdate)
if err != nil {
return err
}
if updateFn != nil {
updateFn(totalOnImmich, totalOnImmich)
}
app.AssetIndex = &AssetIndex{
assets: list,
}
Expand Down Expand Up @@ -596,6 +605,7 @@ func (app *UpCmd) handleAsset(ctx context.Context, a *browser.LocalAssetFile) er
}

if err != nil {
app.Jnl.Record(ctx, fileevent.UploadServerError, a, a.FileName, "error", err.Error())
return nil
}

Expand Down Expand Up @@ -649,8 +659,8 @@ func (app *UpCmd) handleAsset(ctx context.Context, a *browser.LocalAssetFile) er
if err != nil {
app.Jnl.Record(ctx, fileevent.UploadServerError, a, a.FileName, "error", err.Error())
}
time.Sleep(2 * time.Millisecond)
}
time.Sleep(2 * time.Millisecond)
return nil
}

Expand Down
29 changes: 17 additions & 12 deletions helpers/fileevent/fileevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log/slog"
"strings"
"sync"
"sync/atomic"
)
Expand Down Expand Up @@ -58,10 +59,10 @@ var _code = map[Code]string{
UploadNotSelected: "file not selected",
UploadUpgraded: "server's asset upgraded with the input",
UploadAddToAlbum: "added to an album",
UploadServerDuplicate: "server has same photo",
UploadServerDuplicate: "server has same asset",
UploadServerBetter: "server has a better asset",
UploadAlbumCreated: "album created/updated",
UploadServerError: "server error",
UploadServerError: "upload error",
Uploaded: "uploaded",

Error: "error",
Expand Down Expand Up @@ -124,9 +125,11 @@ func (r *Recorder) SetLogger(l *slog.Logger) {
}

func (r *Recorder) Report() {
r.log.Info("\nInput analysis:\n----------------------")
fmt.Println("\nInput analysis:")
fmt.Println("----------------------")
sb := strings.Builder{}

sb.WriteString("\n")
sb.WriteString("Input analysis:\n")
sb.WriteString("---------------\n")
for _, c := range []Code{
DiscoveredImage,
DiscoveredVideo,
Expand All @@ -137,12 +140,12 @@ func (r *Recorder) Report() {
AnalysisAssociatedMetadata,
AnalysisMissingAssociatedMetadata,
} {
r.log.Info(fmt.Sprintf("%-40s: %7d", c.String(), r.counts[c]))
fmt.Printf("%-40s: %7d\n", c.String(), r.counts[c])
sb.WriteString(fmt.Sprintf("%-40s: %7d\n", c.String(), r.counts[c]))
}
r.log.Info("\nUploading:\n----------")
fmt.Println("\nUploading:")
fmt.Println("----------")

sb.WriteString("\n")
sb.WriteString("Uploading:\n")
sb.WriteString("----------\n")
for _, c := range []Code{
Uploaded,
UploadServerError,
Expand All @@ -151,9 +154,11 @@ func (r *Recorder) Report() {
UploadServerDuplicate,
UploadServerBetter,
} {
r.log.Info(fmt.Sprintf("%-40s: %7d", c.String(), r.counts[c]))
fmt.Printf("%-40s: %7d\n", c.String(), r.counts[c])
sb.WriteString(fmt.Sprintf("%-40s: %7d\n", c.String(), r.counts[c]))
}

r.log.Info(sb.String())
fmt.Println(sb.String())
}

func (r *Recorder) GetCounts() []int64 {
Expand Down
27 changes: 14 additions & 13 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,20 @@ immich-go -server URL -key KEY -general_options COMMAND -command_options... {fil


| **Parameter** | **Description** | **Default value** |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `-use-configuration=path/to/config/file` | Specifies the configuration file to use. <br>Server URL and the API key are stored into the immich-go configuration file. They can be omitted for the next runs. | Linux `$HOME/.config/immich-go/immich-go.json`<br>Windows `%AppData%\immich-go\immich-go.json`<br>Apple `$HOME/Library/Application Support/immich-go/immich-go.json` |
| `-server=URL` | URL of the Immich service, example http://<your-ip>:2283 or https://your-domain | |
| `-api=URL` | URL of the Immich api endpoint (http://container_ip:3301) | |
| `-device-uuid=VALUE` | Force the device identification | `$HOSTNAME` |
| `-skip-verify-ssl` | Skip SSL verification for use with self-signed certificates | `false` |
| `-key=KEY` | A key generated by the user. Uploaded photos will belong to the key's owner. | |
| `-no-colors-log` | Remove color codes from logs. | `TRUE` on Windows, `FALSE` otherwise |
| `-log-level=LEVEL` | Adjust the log verbosity as follows: <br> - `ERROR`: Display only errors <br> - `WARNING`: Same as previous one plus non blocking error <br> - `INFO`: Information messages | `INFO` |
| `-log-file=/path/to/log/file` | Write all messages to a file | Linux `$HOME/.cache/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log` <br>Windows `%LocalAppData%\immich-go\immich-go_YYYY-MM-DD_HH-MI-SS.log` <br>Apple `$HOME/Library/Caches/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log`|
| `-time-zone=time_zone_name` | Set the time zone for dates without time zone information | the system's time zone |
| `-no-ui` | Disable the user interface | 'false' |
| **Parameter** | **Description** | **Default value** |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-use-configuration=path/to/config/file` | Specifies the configuration file to use. <br>Server URL and the API key are stored into the immich-go configuration file. They can be omitted for the next runs. | Linux `$HOME/.config/immich-go/immich-go.json`<br>Windows `%AppData%\immich-go\immich-go.json`<br>Apple `$HOME/Library/Application Support/immich-go/immich-go.json` |
| `-server=URL` | URL of the Immich service, example http://<your-ip>:2283 or https://your-domain | |
| `-api=URL` | URL of the Immich api endpoint (http://container_ip:3301) | |
| `-device-uuid=VALUE` | Force the device identification | `$HOSTNAME` |
| `-skip-verify-ssl` | Skip SSL verification for use with self-signed certificates | `false` |
| `-key=KEY` | A key generated by the user. Uploaded photos will belong to the key's owner. | |
| `-no-colors-log` | Remove color codes from logs. | `TRUE` on Windows, `FALSE` otherwise |
| `-log-level=LEVEL` | Adjust the log verbosity as follows: <br> - `ERROR`: Display only errors <br> - `WARNING`: Same as previous one plus non blocking error <br> - `INFO`: Information messages | `INFO` |
| `-log-file=/path/to/log/file` | Write all messages to a file | Linux `$HOME/.cache/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log` <br>Windows `%LocalAppData%\immich-go\immich-go_YYYY-MM-DD_HH-MI-SS.log` <br>Apple `$HOME/Library/Caches/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log` |
| `-log-json` | Output the log as line-delimited JSON file | `false` |
| `-time-zone=time_zone_name` | Set the time zone for dates without time zone information | the system's time zone |
| `-no-ui` | Disable the user interface | 'false' |


## Command `upload`
Expand Down

0 comments on commit ef8d972

Please sign in to comment.