Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
maguro committed Apr 15, 2024
1 parent d06ea2e commit 113ee25
Show file tree
Hide file tree
Showing 35 changed files with 4,294 additions and 1 deletion.
25 changes: 25 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
coverage:
status:
project:
default:
informational: true
patch:
default:
informational: true
ignore:
# All 'pb.go's.
- "**/*.pb.go"
# Tests and test related files.
- "**/test"
- "**/testdata"
- "**/testutils"
- "benchmark"
- "interop"
# Other submodules.
- "cmd"
- "examples"
- "gcp"
- "security"
- "stats/opencensus"
comment:
layout: "header, diff, files"
18 changes: 18 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
- "*"
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
62 changes: 62 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Workflow for CI
on: [ push, pull_request ]
jobs:
run:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ '1.21', '1.22' ]
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0

- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: ${{ matrix.go-version }}

- name: Ensure the Go module is nice and tidy
run: |
go mod tidy && git diff --exit-code go.mod go.sum
# We set the shell explicitly, here, and in other golang test actions,
# as by default multi-line shell scripts do not error out on the first
# failed command. Since we want an error reported if any of the lines
# fail, we set the shell explicitly:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions?ref=cloudtechsimplified.com#exit-codes-and-error-action-preference
shell: bash

- name: Install Tools
run: |
pushd "$(mktemp -d)"
go mod init example.com/m # fake module
go install github.com/onsi/ginkgo/v2/[email protected]
go install honnef.co/go/tools/cmd/[email protected]
popd
shell: bash

- name: Verify Go Modules Setup
run: go mod verify
shell: bash

- name: Build
run: go build -v ./...
shell: bash

- name: Sanity Check (staticcheck)
run: staticcheck ./...
shell: bash

- name: Test
run: ginkgo -v -race -coverprofile=coverage.out -coverpkg=./... ./...
shell: bash

- name: Upload coverage to Codecov
uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: maguro/gslog
flags: smart-tests
verbose: true

81 changes: 80 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,81 @@
# gslog
An slog Handler for Google Cloud Logging

![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.21-%23007d9c)
[![Documentation](https://godoc.org/github.com/maguro/gslog?status.svg)](http://godoc.org/github.com/maguro/gslog)
[![Go Report Card](https://goreportcard.com/badge/github.com/maguro/gslog)](https://goreportcard.com/report/github.com/maguro/gslog)
[![codecov](https://codecov.io/gh/maguro/gslog/graph/badge.svg?token=3FAJJ2SIZB)](https://codecov.io/gh/maguro/gslog)
[![License](https://img.shields.io/github/license/maguro/gslog)](./LICENSE)

A Google Cloud Logging [Handler](https://pkg.go.dev/log/slog#Handler) implementation
for [slog](https://go.dev/blog/slog).

---

Critical level log records will be sent synchronously.

## Install

```sh
go get m4o.io/gslog
```

**Compatibility**: go >= 1.21

## Example Usage

First create a [Google Cloud Logging](https://pkg.go.dev/cloud.google.com/go/logging)
`logging.Client` to use throughout your application:

```go
ctx := context.Background()
client, err := logging.NewClient(ctx, "my-project")
if err != nil {
// TODO: Handle error.
}
```

Usually, you'll want to add log entries to a buffer to be periodically flushed
(automatically and asynchronously) to the Cloud Logging service. Use the
logger when creating the new `gslog.GcpHandler` which is passed to `slog.New()`
to obtain a `slog`-based logger.

```go
loggger := client.Logger("my-log")

h := gslog.NewGcpHandler(loggger)
l := slog.New(h)

l.Info("How now brown cow?")
```

Writing critical, or higher, log level entries will be sent synchronously.

```go
l.Log(context.Background(), gslog.LevelCritical, "Danger, Will Robinson!")
```

Close your client before your program exits, to flush any buffered log entries.

```go
err = client.Close()
if err != nil {
// TODO: Handle error.
}
```

## Logger Configuration Options

Creating a Google Cloud Logging [Handler](https://pkg.go.dev/log/slog#Handler) using `gslog.NewGcpHandler(logger, ...options)` accepts the
following options:

| Configuration option | Arguments | Description |
|----------------------------------------|:------------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `gslog.WithLogLeveler(leveler)` | `slog.Leveler` | Specifies the `slog.Leveler` for logging. Explicitly setting the log level here takes precedence over the other options. |
| `gslog.WithLogLevelFromEnvVar(envVar)` | `string` | Specifies the log level for logging comes from tne environmental variable specified by the key. |
| `gslog.WithDefaultLogLeveler()` | `slog.Leveler` | Specifies the default `slog.Leveler` for logging. |
| `gslog.WithSourceAdded()` | | Causes the handler to compute the source code position of the log statement and add a `slog.SourceKey` attribute to the output. |
| `gslog.WithLabels()` | | Adds any labels found in the context to the `logging.Entry`'s `Labels` field. |
| `gslog.WithReplaceAttr(mapper)` | `gslog.AttrMapper` | Specifies an attribute mapper used to rewrite each non-group attribute before it is logged. |
| `otel.WithOtelBaggage()` | | Directs that the `slog.Handler` to include [OpenTelemetry baggage](https://opentelemetry.io/docs/concepts/signals/baggage/). The `baggage.Baggage` is obtained from the context, if available, and added as attributes. |
| `otel.WithOtelTracing()` | | Directs that the `slog.Handler` to include [OpenTelemetry tracing](https://opentelemetry.io/docs/concepts/signals/traces/). Tracing information is obtained from the `trace.SpanContext` stored in the context, if provided. |
| `k8s.WithPodinfoLabels(root)` | `string` | Directs that the `slog.Handler` to include labels from the [Kubernetes Downward API](https://kubernetes.io/docs/concepts/workloads/pods/downward-api/) podinfo `labels` file. The labels file is expected to be found in the directory specified by root and MUST be named "labels", per the Kubernetes Downward API for Pods. |
44 changes: 44 additions & 0 deletions attr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2024 The original author or 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 gslog

import (
"log/slog"
)

// AttrMapper is called to rewrite each non-group attribute before it is logged.
// The attribute's value has been resolved (see [Value.Resolve]).
// If replaceAttr returns a zero Attr, the attribute is discarded.
//
// The built-in attribute with key "message" is passed to this function.
//
// The first argument is a list of currently open groups that contain the
// Attr. It must not be retained or modified. replaceAttr is never called
// for Group attributes, only their contents. For example, the attribute
// list
//
// Int("a", 1), Group("g", Int("b", 2)), Int("c", 3)
//
// results in consecutive calls to replaceAttr with the following arguments:
//
// nil, Int("a", 1)
// []string{"g"}, Int("b", 2)
// nil, Int("c", 3)
//
// AttrMapper can be used to change the default keys of the built-in
// attributes, convert types (for example, to replace a `time.Time` with the
// integer seconds since the Unix epoch), sanitize personal information, or
// remove attributes from the output.
type AttrMapper func(groups []string, a slog.Attr) slog.Attr
16 changes: 16 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2024 The original author or 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 gslog contains a GCP logging implementation of slog.Handler.
package gslog
Loading

0 comments on commit 113ee25

Please sign in to comment.