surrealpatch/log/stackdriver.go
2019-11-29 23:43:29 +00:00

134 lines
2.9 KiB
Go

// Copyright © 2016 Abcum Ltd
//
// 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 log
import (
"context"
"fmt"
"net/http"
"os"
"time"
"github.com/abcum/fibre"
"github.com/sirupsen/logrus"
"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/logging"
)
type StackdriverLogger struct {
name string
levels []logrus.Level
client *logging.Client
logger *logging.Logger
}
func NewStackDriver() *StackdriverLogger {
var err error
ctx := context.Background()
proj := os.Getenv("PROJECT")
hook := new(StackdriverLogger)
// If no project id has been set
// then attempt to pull this from
// machine metadata if on GCE.
if len(proj) == 0 {
if proj, err = metadata.ProjectID(); err != nil {
log.Fatalf("Failed to connect to Stackdriver: %v", err)
}
}
// Connect to Stackdriver using a
// credentials file if one has been
// specified, or metadata if not.
hook.client, err = logging.NewClient(ctx, proj)
if err != nil {
log.Fatalf("Failed to connect to Stackdriver: %v", err)
}
err = hook.client.Ping(ctx)
if err != nil {
log.Fatalf("Failed to connect to Stackdriver: %v", err)
}
hook.logger = hook.client.Logger(name)
return hook
}
func (h *StackdriverLogger) Levels() []logrus.Level {
switch log.GetLevel() {
case TraceLevel:
return TraceLevels
case DebugLevel:
return DebugLevels
case InfoLevel:
return InfoLevels
case WarnLevel:
return WarnLevels
case ErrorLevel:
return ErrorLevels
case FatalLevel:
return FatalLevels
case PanicLevel:
return PanicLevels
default:
return DebugLevels
}
}
func (h *StackdriverLogger) Fire(entry *logrus.Entry) error {
e := logging.Entry{
Timestamp: entry.Time,
Labels: make(map[string]string, len(entry.Data)),
Payload: entry.Message,
Severity: logging.ParseSeverity(entry.Level.String()),
}
for k, v := range entry.Data {
switch i := v.(type) {
default:
e.Labels[k] = fmt.Sprintf("%v", i)
case *http.Request:
e.HTTPRequest = &logging.HTTPRequest{
Request: i,
RemoteIP: i.RemoteAddr,
}
case *fibre.Context:
e.HTTPRequest = &logging.HTTPRequest{
RemoteIP: i.IP().String(),
Request: i.Request().Request,
Status: i.Response().Status(),
RequestSize: i.Request().Size(),
ResponseSize: i.Response().Size(),
Latency: time.Since(i.Request().Start()),
}
}
}
h.logger.Log(e)
return nil
}