mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-03-15 17:13:46 +01:00
Add log service addon (#5507)
Co-authored-by: Robert Kaussow <xoxys@rknet.org> Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
This commit is contained in:
@@ -343,13 +343,13 @@ var flags = append([]cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_LOG_STORE"),
|
||||
Name: "log-store",
|
||||
Usage: "log store to use ('database' or 'file')",
|
||||
Usage: "log store to use ('database', 'addon' or 'file')",
|
||||
Value: "database",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_LOG_STORE_FILE_PATH"),
|
||||
Name: "log-store-file-path",
|
||||
Usage: "directory used for file based log storage",
|
||||
Usage: "directory used for file based log storage or addon executable file path",
|
||||
},
|
||||
//
|
||||
// backend options for pipeline compiler
|
||||
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/queue"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/services"
|
||||
logService "go.woodpecker-ci.org/woodpecker/v3/server/services/log"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/services/log/addon"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/services/log/file"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/services/permissions"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/store"
|
||||
@@ -125,6 +126,8 @@ func setupLogStore(c *cli.Command, s store.Store) (logService.Service, error) {
|
||||
switch c.String("log-store") {
|
||||
case "file":
|
||||
return file.NewLogStore(c.String("log-store-file-path"))
|
||||
case "addon":
|
||||
return addon.Load(c.String("log-store-file-path"))
|
||||
default:
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -1121,7 +1121,11 @@ Disable version check in admin web UI.
|
||||
- Name: `WOODPECKER_LOG_STORE`
|
||||
- Default: `database`
|
||||
|
||||
Where to store logs. Possible values: `database` or `file`.
|
||||
Where to store logs. Possible values:
|
||||
|
||||
- `database`: stores the logs in the database
|
||||
- `file`: stores logs in JSON files on the files system
|
||||
- `addon`: uses an [addon](./100-addons.md#log) to store logs
|
||||
|
||||
---
|
||||
|
||||
@@ -1130,7 +1134,10 @@ Where to store logs. Possible values: `database` or `file`.
|
||||
- Name: `WOODPECKER_LOG_STORE_FILE_PATH`
|
||||
- Default: none
|
||||
|
||||
Directory to store logs in if [`WOODPECKER_LOG_STORE`](#log_store) is `file`.
|
||||
If [`WOODPECKER_LOG_STORE`](#log_store) is:
|
||||
|
||||
- `file`: Directory to store logs in
|
||||
- `addon`: The path to the addon executable
|
||||
|
||||
---
|
||||
|
||||
|
||||
42
docs/docs/30-administration/10-configuration/100-addons.md
Normal file
42
docs/docs/30-administration/10-configuration/100-addons.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Addons
|
||||
|
||||
Addons can be used to extend the Woodpecker server. Currently, they can be used for forges and the log service.
|
||||
|
||||
:::warning
|
||||
Addon forges are still experimental. Their implementation can change and break at any time.
|
||||
:::
|
||||
|
||||
:::danger
|
||||
You must trust the author of the addon forge you are using. They may have access to authentication codes and other potentially sensitive information.
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
To use an addon forge, download the correct addon version.
|
||||
|
||||
### Forge
|
||||
|
||||
Use this in your `.env`:
|
||||
|
||||
```ini
|
||||
WOODPECKER_ADDON_FORGE=/path/to/your/addon/forge/file
|
||||
```
|
||||
|
||||
In case you run Woodpecker as container, you probably want to mount the addon binary to `/opt/addons/`.
|
||||
|
||||
#### List of addon forges
|
||||
|
||||
- [Radicle](https://radicle.xyz/): Open source, peer-to-peer code collaboration stack built on Git. Radicle addon for Woodpecker CI can be found at [this repo](https://explorer.radicle.gr/nodes/seed.radicle.gr/rad:z39Cf1XzrvCLRZZJRUZnx9D1fj5ws).
|
||||
|
||||
### Log
|
||||
|
||||
Use this in your `.env`:
|
||||
|
||||
```ini
|
||||
WOODPECKER_LOG_STORE=addon
|
||||
WOODPECKER_LOG_STORE_FILE_PATH=/path/to/your/addon/forge/file
|
||||
```
|
||||
|
||||
## Developing addon forges
|
||||
|
||||
See [Addons](../../92-development/100-addons.md).
|
||||
@@ -14,3 +14,5 @@
|
||||
| [when.path filter](../../../20-usage/20-workflow-syntax.md#path) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
|
||||
|
||||
¹ The deployment event can be triggered for all forges from Woodpecker directly. However, only GitHub can trigger them using webhooks.
|
||||
|
||||
In addition to this, Woodpecker supports [addon forges](../100-addons.md) if the forge you are using does not meet the [Woodpecker requirements](../../../92-development/02-core-ideas.md#forges) or your setup is too specific to be included in the Woodpecker core.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
## Addons and extensions
|
||||
|
||||
If you are wondering whether your contribution will be accepted to be merged in the Woodpecker core, or whether it's better to write an
|
||||
[addon forge](../30-administration/10-configuration/12-forges/100-addon.md), [extension](../30-administration/10-configuration/10-server.md#external-configuration-api) or an
|
||||
[addon](../30-administration/10-configuration/100-addons.md), [extension](../30-administration/10-configuration/10-server.md#external-configuration-api) or an
|
||||
[external custom backend](../30-administration/10-configuration/11-backends/50-custom.md), please check these points:
|
||||
|
||||
- Is your change very specific to your setup and unlikely to be used by anyone else?
|
||||
|
||||
@@ -1,34 +1,16 @@
|
||||
# Custom
|
||||
# Addons
|
||||
|
||||
If the forge you are using does not meet the [Woodpecker requirements](../../../92-development/02-core-ideas.md#forges) or your setup is too specific to be included in the Woodpecker core, you can write an addon forge.
|
||||
The Woodpecker server supports addons for forges and the log store.
|
||||
|
||||
:::warning
|
||||
Addon forges are still experimental. Their implementation can change and break at any time.
|
||||
Addons are still experimental. Their implementation can change and break at any time.
|
||||
:::
|
||||
|
||||
:::danger
|
||||
You must trust the author of the addon forge you are using. They may have access to authentication codes and other potentially sensitive information.
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
To use an addon forge, download the correct addon version. Then, you can add the following to your configuration:
|
||||
|
||||
```ini
|
||||
WOODPECKER_ADDON_FORGE=/path/to/your/addon/forge/file
|
||||
```
|
||||
|
||||
In case you run Woodpecker as container, you probably want to mount the addon binary to `/opt/addons/`.
|
||||
|
||||
### Bug reports
|
||||
## Bug reports
|
||||
|
||||
If you experience bugs, please check which component has the issue. If it's the addon, **do not raise an issue in the main repository**, but rather use the separate addon repositories. To check which component is responsible for the bug, look at the logs. Logs from addons are marked with a special field `addon` containing their addon file name.
|
||||
|
||||
## List of addon forges
|
||||
|
||||
- [Radicle](https://radicle.xyz/): Open source, peer-to-peer code collaboration stack built on Git. Radicle addon for Woodpecker CI can be found at [this repo](https://explorer.radicle.gr/nodes/seed.radicle.gr/rad:z39Cf1XzrvCLRZZJRUZnx9D1fj5ws).
|
||||
|
||||
## Creating addon forges
|
||||
## Creating addons
|
||||
|
||||
Addons use RPC to communicate to the server and are implemented using the [`go-plugin` library](https://github.com/hashicorp/go-plugin).
|
||||
|
||||
@@ -38,7 +20,7 @@ This example will use the Go language.
|
||||
|
||||
Directly import Woodpecker's Go packages (`go.woodpecker-ci.org/woodpecker/v3`) and use the interfaces and types defined there.
|
||||
|
||||
In the `main` function, just call `"go.woodpecker-ci.org/woodpecker/v3/server/forge/addon".Serve` with a `"go.woodpecker-ci.org/woodpecker/v3/server/forge".Forge` as argument.
|
||||
In the `main` function, just call the `Serve` method in the corresponding [addon package](#addon-types) with the service as argument.
|
||||
This will take care of connecting the addon forge to the server.
|
||||
|
||||
:::note
|
||||
@@ -47,6 +29,8 @@ It is not possible to access global variables from Woodpecker, for example the s
|
||||
|
||||
### Example structure
|
||||
|
||||
This is an example for a forge addon.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
@@ -68,3 +52,10 @@ type config struct {
|
||||
|
||||
// `config` must implement `"go.woodpecker-ci.org/woodpecker/v3/server/forge".Forge`. You must directly use Woodpecker's packages - see imports above.
|
||||
```
|
||||
|
||||
### Addon types
|
||||
|
||||
| Type | Addon package | Service interface |
|
||||
| --------- | ------------------------------------------------------------- | ----------------------------------------------------------------- |
|
||||
| Forge | `go.woodpecker-ci.org/woodpecker/v3/server/forge/addon` | `"go.woodpecker-ci.org/woodpecker/v3/server/forge".Forge` |
|
||||
| Log store | `go.woodpecker-ci.org/woodpecker/v3/server/service/log/addon` | `"go.woodpecker-ci.org/woodpecker/v3/server/service/log".Service` |
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/forge"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/forge/types"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/model"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/shared/logger"
|
||||
)
|
||||
|
||||
// make sure RPC implements forge.Forge.
|
||||
@@ -40,8 +41,8 @@ func Load(file string) (forge.Forge, error) {
|
||||
pluginKey: &Plugin{},
|
||||
},
|
||||
Cmd: exec.Command(file),
|
||||
Logger: &clientLogger{
|
||||
logger: log.With().Str("addon", file).Logger(),
|
||||
Logger: &logger.AddonClientLogger{
|
||||
Logger: log.With().Str("addon", file).Logger(),
|
||||
},
|
||||
})
|
||||
// TODO: defer client.Kill()
|
||||
|
||||
116
server/services/log/addon/client.go
Normal file
116
server/services/log/addon/client.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2025 Woodpecker Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package addon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/rpc"
|
||||
"os/exec"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/model"
|
||||
logService "go.woodpecker-ci.org/woodpecker/v3/server/services/log"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/shared/logger"
|
||||
)
|
||||
|
||||
// make sure RPC implements logService.Service.
|
||||
var _ logService.Service = new(RPC)
|
||||
|
||||
func Load(file string) (logService.Service, error) {
|
||||
client := plugin.NewClient(&plugin.ClientConfig{
|
||||
HandshakeConfig: HandshakeConfig,
|
||||
Plugins: map[string]plugin.Plugin{
|
||||
pluginKey: &Plugin{},
|
||||
},
|
||||
Cmd: exec.Command(file),
|
||||
Logger: &logger.AddonClientLogger{
|
||||
Logger: log.With().Str("addon", file).Logger(),
|
||||
},
|
||||
})
|
||||
// TODO: defer client.Kill()
|
||||
|
||||
rpcClient, err := client.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw, err := rpcClient.Dispense(pluginKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extension, _ := raw.(logService.Service)
|
||||
return extension, nil
|
||||
}
|
||||
|
||||
type RPC struct {
|
||||
client *rpc.Client
|
||||
}
|
||||
|
||||
func (g *RPC) LogFind(step *model.Step) ([]*model.LogEntry, error) {
|
||||
args, err := json.Marshal(step)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var jsonResp []byte
|
||||
err = g.client.Call("Plugin.LogFind", args, &jsonResp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []*model.LogEntry
|
||||
err = json.Unmarshal(jsonResp, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (g *RPC) LogAppend(step *model.Step, logEntries []*model.LogEntry) error {
|
||||
args, err := json.Marshal(&argumentsAppend{
|
||||
Step: step,
|
||||
LogEntries: logEntries,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var jsonResp []byte
|
||||
return g.client.Call("Plugin.LogAppend", args, &jsonResp)
|
||||
}
|
||||
|
||||
func (g *RPC) LogDelete(step *model.Step) error {
|
||||
args, err := json.Marshal(step)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var jsonResp []byte
|
||||
return g.client.Call("Plugin.LogDelete", args, &jsonResp)
|
||||
}
|
||||
|
||||
func (g *RPC) StepFinished(step *model.Step) {
|
||||
args, err := json.Marshal(step)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not marshal json for log addon")
|
||||
return
|
||||
}
|
||||
var jsonResp []byte
|
||||
err = g.client.Call("Plugin.StepFinished", args, &jsonResp)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("StepFinished via addon failed")
|
||||
}
|
||||
}
|
||||
43
server/services/log/addon/plugin.go
Normal file
43
server/services/log/addon/plugin.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2025 Woodpecker Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package addon
|
||||
|
||||
import (
|
||||
"net/rpc"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/services/log"
|
||||
)
|
||||
|
||||
const pluginKey = "log"
|
||||
|
||||
var HandshakeConfig = plugin.HandshakeConfig{
|
||||
ProtocolVersion: 1,
|
||||
MagicCookieKey: "WOODPECKER_LOG_ADDON_PLUGIN",
|
||||
MagicCookieValue: "woodpecker-plugin-magic-cookie-value",
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
Impl log.Service
|
||||
}
|
||||
|
||||
func (p *Plugin) Server(*plugin.MuxBroker) (any, error) {
|
||||
return &RPCServer{Impl: p.Impl}, nil
|
||||
}
|
||||
|
||||
func (*Plugin) Client(_ *plugin.MuxBroker, c *rpc.Client) (any, error) {
|
||||
return &RPC{client: c}, nil
|
||||
}
|
||||
87
server/services/log/addon/server.go
Normal file
87
server/services/log/addon/server.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2025 Woodpecker Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package addon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/model"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/services/log"
|
||||
)
|
||||
|
||||
func Serve(impl log.Service) {
|
||||
plugin.Serve(&plugin.ServeConfig{
|
||||
HandshakeConfig: HandshakeConfig,
|
||||
Plugins: map[string]plugin.Plugin{
|
||||
pluginKey: &Plugin{Impl: impl},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type RPCServer struct {
|
||||
Impl log.Service
|
||||
}
|
||||
|
||||
type argumentsAppend struct {
|
||||
Step *model.Step `json:"step"`
|
||||
LogEntries []*model.LogEntry `json:"log_entries"`
|
||||
}
|
||||
|
||||
func (s *RPCServer) LogFind(args []byte, resp *[]byte) error {
|
||||
var a model.Step
|
||||
err := json.Unmarshal(args, &a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log, err := s.Impl.LogFind(&a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*resp, err = json.Marshal(log)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *RPCServer) LogAppend(args []byte, resp *[]byte) error {
|
||||
var a argumentsAppend
|
||||
err := json.Unmarshal(args, &a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*resp = []byte{}
|
||||
return s.Impl.LogAppend(a.Step, a.LogEntries)
|
||||
}
|
||||
|
||||
func (s *RPCServer) LogDelete(args []byte, resp *[]byte) error {
|
||||
var a model.Step
|
||||
err := json.Unmarshal(args, &a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*resp = []byte{}
|
||||
return s.Impl.LogDelete(&a)
|
||||
}
|
||||
|
||||
func (s *RPCServer) StepFinished(args []byte, resp *[]byte) error {
|
||||
var a model.Step
|
||||
err := json.Unmarshal(args, &a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*resp = []byte{}
|
||||
s.Impl.StepFinished(&a)
|
||||
return nil
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package addon
|
||||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type clientLogger struct {
|
||||
logger zerolog.Logger
|
||||
type AddonClientLogger struct {
|
||||
Logger zerolog.Logger
|
||||
name string
|
||||
withArgs []any
|
||||
}
|
||||
@@ -48,9 +48,9 @@ func convertLvl(level hclog.Level) zerolog.Level {
|
||||
return zerolog.NoLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) applyArgs(args []any) *zerolog.Logger {
|
||||
func (c *AddonClientLogger) applyArgs(args []any) *zerolog.Logger {
|
||||
var key string
|
||||
logger := c.logger.With()
|
||||
logger := c.Logger.With()
|
||||
args = append(args, c.withArgs)
|
||||
for i, arg := range args {
|
||||
switch {
|
||||
@@ -68,67 +68,67 @@ func (c *clientLogger) applyArgs(args []any) *zerolog.Logger {
|
||||
return &l
|
||||
}
|
||||
|
||||
func (c *clientLogger) Log(level hclog.Level, msg string, args ...any) {
|
||||
func (c *AddonClientLogger) Log(level hclog.Level, msg string, args ...any) {
|
||||
c.applyArgs(args).WithLevel(convertLvl(level)).Msg(msg)
|
||||
}
|
||||
|
||||
func (c *clientLogger) Trace(msg string, args ...any) {
|
||||
func (c *AddonClientLogger) Trace(msg string, args ...any) {
|
||||
c.applyArgs(args).Trace().Msg(msg)
|
||||
}
|
||||
|
||||
func (c *clientLogger) Debug(msg string, args ...any) {
|
||||
func (c *AddonClientLogger) Debug(msg string, args ...any) {
|
||||
c.applyArgs(args).Debug().Msg(msg)
|
||||
}
|
||||
|
||||
func (c *clientLogger) Info(msg string, args ...any) {
|
||||
func (c *AddonClientLogger) Info(msg string, args ...any) {
|
||||
c.applyArgs(args).Info().Msg(msg)
|
||||
}
|
||||
|
||||
func (c *clientLogger) Warn(msg string, args ...any) {
|
||||
func (c *AddonClientLogger) Warn(msg string, args ...any) {
|
||||
c.applyArgs(args).Warn().Msg(msg)
|
||||
}
|
||||
|
||||
func (c *clientLogger) Error(msg string, args ...any) {
|
||||
func (c *AddonClientLogger) Error(msg string, args ...any) {
|
||||
c.applyArgs(args).Error().Msg(msg)
|
||||
}
|
||||
|
||||
func (c *clientLogger) IsTrace() bool {
|
||||
func (c *AddonClientLogger) IsTrace() bool {
|
||||
return log.Logger.GetLevel() >= zerolog.TraceLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) IsDebug() bool {
|
||||
func (c *AddonClientLogger) IsDebug() bool {
|
||||
return log.Logger.GetLevel() >= zerolog.DebugLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) IsInfo() bool {
|
||||
func (c *AddonClientLogger) IsInfo() bool {
|
||||
return log.Logger.GetLevel() >= zerolog.InfoLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) IsWarn() bool {
|
||||
func (c *AddonClientLogger) IsWarn() bool {
|
||||
return log.Logger.GetLevel() >= zerolog.WarnLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) IsError() bool {
|
||||
func (c *AddonClientLogger) IsError() bool {
|
||||
return log.Logger.GetLevel() >= zerolog.ErrorLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) ImpliedArgs() []any {
|
||||
func (c *AddonClientLogger) ImpliedArgs() []any {
|
||||
return c.withArgs
|
||||
}
|
||||
|
||||
func (c *clientLogger) With(args ...any) hclog.Logger {
|
||||
return &clientLogger{
|
||||
logger: c.logger,
|
||||
func (c *AddonClientLogger) With(args ...any) hclog.Logger {
|
||||
return &AddonClientLogger{
|
||||
Logger: c.Logger,
|
||||
name: c.name,
|
||||
withArgs: args,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *clientLogger) Name() string {
|
||||
func (c *AddonClientLogger) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c *clientLogger) Named(name string) hclog.Logger {
|
||||
func (c *AddonClientLogger) Named(name string) hclog.Logger {
|
||||
curr := c.name
|
||||
if curr != "" {
|
||||
curr = c.name + "."
|
||||
@@ -136,20 +136,20 @@ func (c *clientLogger) Named(name string) hclog.Logger {
|
||||
return c.ResetNamed(curr + name)
|
||||
}
|
||||
|
||||
func (c *clientLogger) ResetNamed(name string) hclog.Logger {
|
||||
return &clientLogger{
|
||||
logger: c.logger,
|
||||
func (c *AddonClientLogger) ResetNamed(name string) hclog.Logger {
|
||||
return &AddonClientLogger{
|
||||
Logger: c.Logger,
|
||||
name: name,
|
||||
withArgs: c.withArgs,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *clientLogger) SetLevel(level hclog.Level) {
|
||||
c.logger = c.logger.Level(convertLvl(level))
|
||||
func (c *AddonClientLogger) SetLevel(level hclog.Level) {
|
||||
c.Logger = c.Logger.Level(convertLvl(level))
|
||||
}
|
||||
|
||||
func (c *clientLogger) GetLevel() hclog.Level {
|
||||
switch c.logger.GetLevel() {
|
||||
func (c *AddonClientLogger) GetLevel() hclog.Level {
|
||||
switch c.Logger.GetLevel() {
|
||||
case zerolog.ErrorLevel:
|
||||
return hclog.Error
|
||||
case zerolog.WarnLevel:
|
||||
@@ -164,12 +164,12 @@ func (c *clientLogger) GetLevel() hclog.Level {
|
||||
return hclog.NoLevel
|
||||
}
|
||||
|
||||
func (c *clientLogger) StandardLogger(opts *hclog.StandardLoggerOptions) *std_log.Logger {
|
||||
func (c *AddonClientLogger) StandardLogger(opts *hclog.StandardLoggerOptions) *std_log.Logger {
|
||||
return std_log.New(c.StandardWriter(opts), "", 0)
|
||||
}
|
||||
|
||||
func (c *clientLogger) StandardWriter(*hclog.StandardLoggerOptions) io.Writer {
|
||||
return ioAdapter{logger: c.logger}
|
||||
func (c *AddonClientLogger) StandardWriter(*hclog.StandardLoggerOptions) io.Writer {
|
||||
return ioAdapter{logger: c.Logger}
|
||||
}
|
||||
|
||||
type ioAdapter struct {
|
||||
Reference in New Issue
Block a user