前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Go微服务,第10部分:集中式日志记录

Go微服务,第10部分:集中式日志记录

作者头像
Aaroncang
发布于 2018-07-05 02:21:30
发布于 2018-07-05 02:21:30
2.8K0
举报

在Go微服务博客系列的这一部分中,我们将介绍基于LogrusDocker Gelf日志驱动程序和“作为服务的日志记录” Loggly服务的Go微服务的日志记录策略。

简介

日志。你永远不知道你有多想念他们,直到你真的想念他们。日志为您的团队提供关于记录什么,何时记录以及如何记录的指导方针,可能是制作可维护应用程序的关键因素之一。然后,微服务产生了。

虽然处理单片应用程序的一个或几个不同日志文件通常是可管理的(尽管存在例外......),但考虑对基于微服务的应用程序执行相同的操作,每个应用程序可能产生数百甚至数千个服务容器,每个容器都生成日志。如果你没有一个解决方案来以一种结构良好的方式收集和汇总你的日志,那么就不要考虑做大的事情。

值得庆幸的是,很多聪明人已经想到了这点,以前称为ELK的堆栈可能是开源社区中最知名的一个。弹性搜索、日志隐藏和Kibana组成了弹性堆栈,我推荐它用于内部部署和云部署。但是,可能已经有数十篇有关ELK的博客文章,因此在这个特别的博客中,我们将基于四个部分探讨一个LaaS(日志记录即服务)解决方案,以满足我们的集中式日志记录需求:

内容

  1. Logrus —— Go的日志框架
  2. Docker GELF驱动程序 —— Greylog扩展日志格式的日志记录驱动程序
  3. “Gelftail” —— 我们将在此博客文章中构建的轻量级日志聚合器。当然,我们会用Go编写它。
  4. Loggly —— 一家LaaS提供商。提供类似的功能来管理和处理类似服务的日志数据

解决方案概述

源代码

完成的源代码可以从GitHub克隆:

代码语言:txt
AI代码解释
复制
> git clone https://github.com/callistaenterprise/goblog.git
> git checkout P10

1. Logrus - Go的日志API

通常,我们的Go微服务到现在为止都是使用“fmt”或“log”包进行日志记录的,无论是stdout还是stderr。我们希望给予我们更精细的日志级别和格式控制。在Java世界中,我们中的很多(大多数)都处理过诸如log4j,logback和slf4j之类的框架。Logrus是我们此博客系列的首选日志API,它大致提供了与我刚才提到的API级别、格式化、挂钩等相同类型的功能。

使用Logrus

logrus的好处之一是它实现了我们迄今为止用于登录的相同接口 —— fmtlog。这意味着我们可以或多或少地使用logrus作为替代品。在获取logrus源代码之前,首先要确保你的GOPATH是正确的,这样它就会被安装到你的GOPATH中:

代码语言:txt
AI代码解释
复制
> go get github.com/sirupsen/logrus

更新来源

我们会以古老的方式来做这件事。对于/ common/ accountservice/ vipservice 分别使用IDE或文本编辑器进行全局搜索和替换,其中fmt.*log.*logrus.*替换。现在你应该有很多的logrus.Printlnlogrus.Printf 调用。即使这样做很好,我还是建议使用logrus来支持诸如INFO、WARN、DEBUG等细节。例如:

FMT

日志

logrus

的println

的println

Infoln

printf的

printf的

Infof

错误

Errorln

有一个例外是用于产生错误实例的fmt.Error。不要替换fmt.Error

使用goimports更新导入

鉴于我们已经用logrus.Println(以及其他日志记录功能)替换了大量log.Printlnfmt.Println,现在我们有很多未使用的导入会导致编译错误。我们可以使用一个很小的工具 —— goimports,可以在命令行上下载并执行(或集成到你选择的IDE中),而不是一次一个地修复文件。

再次确保你的GOPATH是正确的。然后使用go get 来下载goimports:

代码语言:txt
AI代码解释
复制
go get golang.org/x/tools/cmd/goimports

这会将goimports安装到你的$ GOPATH / bin文件夹中。接下来,你可以转到accountservicevipservice 服务的根目录,例如:

代码语言:txt
AI代码解释
复制
cd $GOPATH/src/github.com/callistaenterprise/goblog/accountservice

然后,运行goimports,使用“-w”标志递归修复导入,该标志直接将更改应用于源文件。

代码语言:txt
AI代码解释
复制
$GOPATH/bin/goimports -w **/*.go

重复我们所有的微服务代码,包括/ common文件夹。

运行去构建 以确保服务编译。

代码语言:txt
AI代码解释
复制
go build

配置Logrus

如果我们完全不配置Logrus,它将以纯文本形式输出日志语句。例如:

代码语言:txt
AI代码解释
复制
logrus.Infof("Starting our service...")

它会输出:

代码语言:txt
AI代码解释
复制
INFO[0000] Starting our service...

其中0000 是服务启动后的秒数。这不是我想要的,我想要一个日期时间,所以我们必须提供一个格式化程序。

init()函数是那种设置的好方法:

代码语言:txt
AI代码解释
复制
func init() {
logrus.SetFormatter(&logrus.TextFormatter{
TimestampFormat: "2006-01-02T15:04:05.000",
FullTimestamp: true,
})
}

新的输出:

代码语言:txt
AI代码解释
复制
INFO[2017-07-17T13:22:49.164] Starting our service...

好多了。但是,在我们的微服务用例中,我们希望日志语句易于解析,以便我们最终可以将它们发送到我们选择的LaaS中,并对日志语句进行索引、排序、分组、聚合等。因此,我们希望只要我们没有以独立模式(即-profile = dev)运行微服务,就改用JSON格式化程序。

让我们稍微改变一下init()代码,以便它会使用JSON格式化程序,除非传递“-profile = dev”标志。

代码语言:txt
AI代码解释
复制
func init() {
    profile := flag.String("profile", "test", "Environment profile")
if *profile == "dev" {
logrus.SetFormatter(&logrus.TextFormatter{
TimestampFormat: "2006-01-02T15:04:05.000",
FullTimestamp: true,
})
} else {
logrus.SetFormatter(&logrus.JSONFormatter{})
}
}

输出:

代码语言:txt
AI代码解释
复制
{"level":"info","msg":"Starting our service...","time":"2017-07-17T16:03:35+02:00"}

就是这样。请随时阅读Logrus 文档以获取更全面的示例。

应该清楚的是,标准Logrus记录器不提供你可能从其他平台使用的细粒度控制 —— 例如,通过配置将输出从给定的更改为DEBUG。但是,可以创建范围记录器实例,这可以实现更细粒度的配置,例如:

代码语言:txt
AI代码解释
复制
var LOGGER = logrus.Logger{}   // <-- Create logger instance
func init() {
// Some other init code...
// Example 1 - using global logrus API
logrus.Infof("Successfully initialized")
// Example 2 - using logger instance
LOGGER.Infof("Successfully initialized")
}

(示例代码,不再回购)

通过使用LOGGER实例,可以更精细地配置应用程序级日志记录。但是,我已经选择使用logrus.*来进行博客系列的这部分内容的“全局”日志记录。

2. Docker Gelf驱动程序

什么是GELF?它是Greylog扩展日志格式的缩写,是logstash的标准格式。实际上,它将日志数据构造为JSON。在Docker的上下文中,我们可以配置一个Docker集群模式服务来使用各种驱动程序进行日志记录,这实际上意味着在一个容器中写入stdout或stderr的所有内容都是由Docker引擎“接收”的,并由已配置的日志驱动程序处理。这种处理包括添加许多关于容器、群集节点、服务等特定于Docker的元数据。示例消息可能如下所示:

代码语言:txt
AI代码解释
复制
{
      "version":"1.1",
      "host":"swarm-manager-0",
      "short_message":"Starting HTTP service at 6868",
      "timestamp":1.487625824614e+09,
      "level":6,
      "_command":"./vipservice-linux-amd64 -profile=test",
      "_container_id":"894edfe2faed131d417eebf77306a0386b43027e0bdf75269e7f9dcca0ac5608",
      "_container_name":"vipservice.1.jgaludcy21iriskcu1fx9nx2p",
      "_created":"2017-02-20T21:23:38.877748337Z",
      "_image_id":"sha256:1df84e91e0931ec14c6fb4e559b5aca5afff7abd63f0dc8445a4e1dc9e31cfe1",
      "_image_name":"someprefix/vipservice:latest",
      "_tag":"894edfe2faed"
}

让我们来看看如何在copyall.sh中更改我们的“ docker service create”命令来使用GELF驱动程序:

代码语言:txt
AI代码解释
复制
docker service create \
--log-driver=gelf \
--log-opt gelf-address=udp://192.168.99.100:12202 \
--log-opt gelf-compression-type=none \
--name=accountservice --replicas=1 --network=my_network -p=6767:6767 someprefix/accountservice
  • -log-driver = gelf告诉Docker使用gelf驱动程序
  • -log-opt gelf-address告诉Docker发送所有日志语句的位置。在gelf的情况下,我们将使用UDP协议并告诉Docker将日志语句发送到定义的IP:端口上的服务。该服务通常是诸如logstash之类的东西,但在我们的案例中,我们将在下一部分中构建自己的小日志聚合服务。
  • -log-opt gelf-compression-type告诉Docker在发送日志语句之前是否使用压缩。为了简单起见,在博客里这部分没有压缩。

这些不多也不少!任何由accountservice类型创建的微服务实例现在都会将写入stdout / stderr的所有内容发送到配置的端点。请注意,这意味着我们不能再使用docker日志的containerid命令来检查给定服务的日志,因为(默认)日志记录驱动程序不再被使用。

我们应该将这些gelf日志驱动程序配置语句添加到我们的shell脚本中的所有docker服务创建命令中,例如copyall.sh

不过,这种设置有一个不完善的问题——对群集管理器使用硬编码的ip地址。令人遗憾的是,即使我们将“gelftail”服务部署为Docker集群模式服务,我们也不能在声明服务时使用它的逻辑名称来解决此问题。我们或许可以用DNS或类似的方式解决这个缺点,如果你知道怎么做的话,请在评论中告诉我们。

使用Gelf与Logrus挂钩

如果你确实需要使你的日志记录不受容器和协调器更多的限制,那么可以选择使用Logrus 的gelf插件来使用hook执行GELF日志记录。在该设置中,Logrus将自行格式化日志语句为GELF格式,也可以通过配置将它们传输到UDP地址,就像使用Docker GELF驱动程序时一样。然而,默认情况下Logrus没有关于在容器中运行的概念,所以我们基本上必须弄清楚如何自己填充那些丰富的元数据,可能使用对Docker Remote API或操作系统函数的调用。

强烈建议使用Docker GELF驱动程序。尽管它将您的日志记录与Docker群集模式联系在一起,但其他容器编排器可能也支持从容器中收集stdout/stderr日志,并将其转发到中央日志记录服务。

3.使用“Gelftail”收集和聚合日志记录

发送所有日志语句的UDP服务器通常是Logstash或类似的,它提供了对日志语句的转换、聚合、过滤等功能的强大控制,然后将它们存储在后端,如弹性搜索或将它们推送到LaaS。

然而,Logstash并不完全是轻量级的,为了让事情变得简单(而且很有趣),我们将编写我们自己的小日志聚合器,我称它为“gelftail”。这个名字来源于一个事实:一旦我为我的所有服务配置了Docker GELF驱动程序,我就无法再看到记录的内容了!我决定编写一个简单的UDP服务器来接收发送给它的所有数据并转储到stdout,然后我可以使用docker日志来查看。例如,来自所有服务的所有日志语句的流。不是很实用,但至少比没有看到任何日志要好。

接下来,下一步自然就是将这个“gelftail”程序附加到LaaS后端,应用一些转换、语句批处理等,这正是我们马上要开发的内容!

Gelftail

在root / goblog文件夹中,创建一个名为gelftail的新目录。按照下面的说明创建必要的文件和文件夹。

代码语言:txt
AI代码解释
复制
mdkir $GOPATH/src/github.com/callistaenterprise/goblog/gelftail
mdkir $GOPATH/src/github.com/callistaenterprise/goblog/gelftail/transformer
mdkir $GOPATH/src/github.com/callistaenterprise/goblog/gelftail/aggregator
cd $GOPATH/src/github.com/callistaenterprise/goblog/gelftail
touch gelftail.go
touch transformer/transform.go
touch aggregator/aggregator.go

Gelftail按照这些方式工作:

  1. 启动UDP服务器(Docker GELF驱动程序将日志输出发送到的服务器)。
  2. 对于每个UDP数据包,我们假定它是来自Logrus的JSON格式的输出。我们将做一些解析来提取实际的级别short_message属性,并稍微转换 原始日志消息,以便它包含这些属性作为根级别元素。
  3. 接下来,我们将使用缓冲的go通道作为逻辑“发送队列”,也就是我们的聚合器 goroutine正在读取的 。对于每个收到的日志消息,它都会检查当前缓冲区是否大于1 kb。
  4. 如果缓冲区足够大,它将使用聚合语句对Loggly HTTP上载端点执行HTTP POST ,清除缓冲区并开始构建新的批处理。

使用经典的企业集成模式(以某种非惯用的方式)表达,它看起来像这样:

源代码

该程序将被分成三个文件。从一个 包和一些导入的gelftail.go开始:

代码语言:txt
AI代码解释
复制
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"net"
"net/http"
"os"
    "io/ioutil"
"github.com/Sirupsen/logrus"
)

在注册Loggly(本博客系列的首选LaaS)时,我们会得到一个身份验证令牌,你必须将其视为机密。任何访问您的令牌的人至少都可以将日志语句发送到您的帐户中。所以,请确保你使用 .gitignore token.txt 或你为文件选的任何名称。当然,可以使用第7部分中的配置服务器并将身份验证令牌存储为加密属性。就目前而言,我尽可能简单地保存成文本文件。

因此,让我们为我们的LaaS令牌添加一个占位符,并尝试从磁盘加载该令牌的init()函数。如果不成功,我们也可以记录日志和问题。

代码语言:txt
AI代码解释
复制
var authToken = ""
var port *string
func init() {
data, err := ioutil.ReadFile("token.txt")
    if err != nil {
        msg := "Cannot find token.txt that should contain our Loggly token"
        logrus.Errorln(msg)
        panic(msg)
    }
    authToken = string(data)
    port = flag.String("port", "12202", "UDP port for the gelftail")
    flag.Parse()
}

我们还使用一个标志为UDP服务器提供一个可选的端口号。接下来,我们需要声明main()函数来开始。

代码语言:txt
AI代码解释
复制
func main() {
logrus.Println("Starting Gelf-tail server...")
ServerConn := startUDPServer(*port)   // Remember to dereference the pointer for our "port" flag
defer ServerConn.Close()
var bulkQueue = make(chan []byte, 1)  // Buffered channel to put log statements ready for LaaS upload into
go aggregator.Start(bulkQueue, authToken)          // Start goroutine that'll collect and then upload batches of log statements
go listenForLogStatements(ServerConn, bulkQueue)   // Start listening for UDP traffic
logrus.Infoln("Started Gelf-tail server")
wg := sync.WaitGroup{}
wg.Add(1)
wg.Wait()              // Block indefinitely
}

非常简单,启动UDP服务器,声明用于传递处理过的消息的通道,并启动“聚合器”。startUDPServer(* port)函数不是很有趣,因此我们将跳过listenForLogStatements(..)

代码语言:txt
AI代码解释
复制
func listenForLogStatements(ServerConn *net.UDPConn, bulkQueue chan[]byte) {
buf := make([]byte, 8192)                        // Buffer to store UDP payload into. 8kb should be enough for everyone, right Bill? :D
var item map[string]interface{}                  // Map to put unmarshalled GELF json log message into
for {
            n, _, err := ServerConn.ReadFromUDP(buf)     // Blocks until data becomes available, which is put into the buffer.
            if err != nil {
                logrus.Errorf("Problem reading UDP message into buffer: %v\n", err.Error())
                continue                                 // Log and continue if there are problms
            }
            err = json.Unmarshal(buf[0:n], &item)        // Try to unmarshal the GELF JSON log statement into the map
            if err != nil {                              // If unmarshalling fails, log and continue. (E.g. filter)
                logrus.Errorln("Problem unmarshalling log message into JSON: " + err.Error())
                item = nil
                continue
            }
            // Send the map into the transform function
            processedLogMessage, err := transformer.ProcessLogStatement(item)    
            if err != nil {
                logrus.Printf("Problem parsing message: %v", string(buf[0:n]))
            } else {
                bulkQueue <- processedLogMessage          // If processing went well, send on channel to aggregator
            }
            item = nil
    }
}

依据代码中的注释,该transformer.go文件也不是那么令人兴奋,它只是从一个JSON属性中读取一些东西,并将其转移到“根”GELF消息上。所以让我们跳过这个。

最后,深入了解/ goblog / gelftail / aggregator / aggregator.go中的“聚合器”代码,该代码处理来自bulkQueue通道的最终日志消息,汇总并上传到Loggly:

代码语言:txt
AI代码解释
复制
var client = &http.Client{}
var logglyBaseUrl = "https://logs-01.loggly.com/inputs/%s/tag/http/"
var url string
func Start(bulkQueue chan []byte, authToken string) {
        url = fmt.Sprintf(logglyBaseUrl, authToken) // Assemble the final loggly bulk upload URL using the authToken  
        buf := new(bytes.Buffer)
        for {
                msg := <-bulkQueue                 // Blocks here until a message arrives on the channel.
                buf.Write(msg)
                buf.WriteString("\n")              // Loggly needs newline to separate log statements properly.
                size := buf.Len()
                if size > 1024 {                   // If buffer has more than 1024 bytes of data...
                        sendBulk(*buf)  // Upload!
                        buf.Reset()
                }
        }
}

我只是喜欢Go代码的简单性!使用bytes.Buffer,我们只需输入一个永恒循环,在msg:= <-bulkQueue处阻塞,直到接收到一个消息(未缓冲的)通道。我们将内容+换行符写入缓冲区,然后检查缓冲区是否大于我们预先确定的1kb阈值。如果是,我们调用sendBulk函数并清除缓冲区。sendBulk只是对Loggly执行一个标准的HTTP POST。

生成,Dockerfile,部署

当然,我们将“gelftail”部署为Docker群模式服务,就像其他服务一样。为此,我们需要一个Dockerfile:

代码语言:txt
AI代码解释
复制
FROM iron/base
EXPOSE 12202/udp
ADD gelftail-linux-amd64 /
ADD token.txt /
ENTRYPOINT ["./gelftail-linux-amd64", "-port=12202"]

token.txt是一个带有Loggly授权令牌的简单文本文件,更多信息请参阅本文的第4部分。

构建和部署应该很简单。我们将在root / goblog目录中添加一个新的.sh脚本:

代码语言:txt
AI代码解释
复制
#!/bin/bash
export GOOS=linux
export CGO_ENABLED=0
cd gelftail;go get;go build -o gelftail-linux-amd64;echo built `pwd`;cd ..
export GOOS=darwin
docker build -t someprefix/gelftail gelftail/
docker service rm gelftail
docker service create --name=gelftail -p=12202:12202/udp --replicas=1 --network=my_network someprefix/gelftail

这应该会运行几秒钟。通过跟踪自己的stdout日志来验证gelftail是否已成功启动。使用docker ps查找它的容器ID ,然后使用docker logs 检查日志

代码语言:txt
AI代码解释
复制
> docker logs -f e69dff960cec
time="2017-08-01T20:33:00Z" level=info msg="Starting Gelf-tail server..." 
time="2017-08-01T20:33:00Z" level=info msg="Started Gelf-tail server"

如果你在使用另一个记录日志的服务执行某些操作,则该服务的日志输出现在应该显示在上面的尾部。我们将accountservice扩展为两个实例:

代码语言:txt
AI代码解释
复制
> docker service scale accountservice=2

上面的尾部docker日志现在应该输出如下内容:

代码语言:txt
AI代码解释
复制
time="2017-08-01T20:36:08Z" level=info msg="Starting accountservice" 
time="2017-08-01T20:36:08Z" level=info msg="Loading config from http://configserver:8888/accountservice/test/P10\n" 
time="2017-08-01T20:36:08Z" level=info msg="Getting config from http://configserver:8888/accountservice/test/P10\n"

这完全是为了“gelftail”。让我们通过快速浏览Loggly来结束这篇博文。

4. Loggly

有很多“Logging as a Service”服务提供商,我大概选择了一个(例如Loggly),它好像有一个适合演示目的的免费层,一个漂亮的GUI和一组丰富的用于上传日志语句的选项。

关于如何将日志导入Loggly的选项有很多(参见链接页面左侧的列表)。我决定使用HTTP / S事件API,它允许我们通过换行分隔小批量发送多个日志语句。

入门

我建议遵循他们的入门指南,这可以归结为:

  1. 创建一个帐户(免费套餐适用于演示/试用目的)。
  2. 获取授权令牌。将其保存在安全的地方并复制粘贴到/goblog/gelftail/token.txt中
  3. 决定如何“上传”你的日志。如上所述,我选择使用HTTP / S POST API。
  4. 配置你的服务/日志记录驱动程序/ logstash / gelftail等,并使用你选择的上传模式。

利用Loggly的所有功能已经超出了这个博客的范围。我只修改了它们的仪表板和过滤功能,我认为这是LaaS提供商的标准功能。

几个例子

在第一个屏幕截图中,我放大了35分钟的时间,在这段时间里,我明确地过滤了“accountservice”和“info”消息:

正如所见,可以非常容易地自定义列、过滤值、时间段等。

在下一个示例中,我查看的是相同的时间段,但只查看“error”日志语句:

虽然这些示例用例非常简单,但是当你拥有数十个运行1-n个实例的微服务时,真正的实用性就显现出来了。这时,LaaS强大的索引、过滤和其他功能就真正成为了微服务操作模型的基本部分。

总结

在本系列博文的第10部分中,我们介绍了集中式日志记录:为什么它很重要,如何在Go服务中执行结构化日志记录,如何从您的容器协调器中使用日志驱动程序,最后在将它们上传到日志即服务提供者之前对日志语句进行预处理。

在下一部分,我们将使用Netflix Hystrix为我们的微服务增加断路器和弹性。

评论
登录后参与评论
暂无评论
推荐阅读
SPSS用K均值聚类KMEANS、决策树、逻辑回归和T检验研究通勤出行交通方式选择的影响因素调查数据分析|附代码数据
某交通工程专业博士生想要研究不同因素对通勤交通方式选择的影响,对成都两个大型小区(高端和普通)居民分别进行了出行调查,各调查了300人
拓端
2023/04/28
3630
SQL SERVER ANALYSIS SERVICES决策树、聚类、关联规则挖掘分析电商购物网站的用户行为数据
假如你有一个购物类的网站,那么你如何给你的客户来推荐产品呢?这个功能在很多电商类网站都有,那么,通过SQL Server Analysis Services的数据挖掘功能,你也可以轻松的来构建类似的功能。
拓端
2023/04/12
2310
位置大数据之《北京交通等时圈选房指南》
距离北京“3·17”最严房产调控启动已有近三个月时间,在调控影响下,本应是购房黄金期的楼市“红五月”爽约,房地产市场正在迅速降温,新房成交量低迷,二手房成交量更是已经降至冰点。随之而来的是,楼市观望情绪日趋浓厚,买卖双方博弈关系出现逆转,楼市隐现买方市场。 一方面是政策收紧,很多购房者暂缓买房脚步,另一方面不得不承认北京房地产刚需仍在。一直以来,好位置、低总价、好配套,是购房者选房时最看重的三大因素。那么~ 在现时的北京,哪里还有这样的房子?想买均价5万以下的房子,哪里的性价比最高?工作在中关村,希望通勤
腾讯位置服务
2018/11/07
2.1K0
位置大数据之《北京交通等时圈选房指南》
SQL SERVER ANALYSIS SERVICES决策树、聚类、关联规则挖掘分析电商购物网站的用户行为数据|附代码数据
最近我们被客户要求撰写关于电商购物网站的用户行为的研究报告,包括一些图形和统计输出。
拓端
2023/07/21
3320
太酷炫了!万科最新大数据市场研究手段曝光!
近期,由上海万科与多家高校及城市数据团合作搭建的专属于万科的大数据分析平台正式上线了。这是万科在推动房地产行业的大数据化、引领地产行业转型潮流上踏出的重要一步。
IT派
2018/07/30
1.3K0
太酷炫了!万科最新大数据市场研究手段曝光!
【钱塘号专栏】太酷炫了!万科最新大数据市场研究手段曝光!
作者:郁亮 如何研究房地产市场?归根结底需要解决的问题无非是地、房、人三大内容。 然而,传统的研究方法却耗时耗力 看不全的土地——总会遗忘疏漏 想不尽的产品——依旧经验为先 读不透的客户——往往以偏概
钱塘数据
2018/03/05
1K0
【钱塘号专栏】太酷炫了!万科最新大数据市场研究手段曝光!
Weka数据挖掘Apriori关联规则算法分析用户网购数据
随着大数据时代的来临,如何从海量的存储数据中发现有价值的信息或知识帮助用户更好决策是一项非常艰巨的任务。数据挖掘正是为了满足此种需求而迅速发展起来的,它是从大量的、不完全的、有噪声的、模糊的、随机的数据中,提取隐含在其中的、人们事先不知道的、但又是潜在的有用信息和知识的过程。由于大数据技术的发展,零售企业可以利用互联网收集大量的销售数据,这些数据是一条条的购买事务信息,每条信息存储了销售事务的处理时间,顾客所购买的商品、各种商品的数量以及价格等。如果对这些历史数据进行分析,则可以对理解分析顾客的购买行为提供有价值的信息。
拓端
2023/04/14
8340
手握460亿笔数据!北京市政交通IC卡能玩出什么花样?
从今天开始,小编开始精编部分嘉宾的现场演讲内容,结合PPT,给小伙伴们奉上干货。 本期精编版嘉宾演讲为北京市政交通一卡通公司数据运营总监张翔带来的分享,看了他讲的内容才知道,我们每天都在用的公交卡真
CDA数据分析师
2018/02/24
1.4K0
手握460亿笔数据!北京市政交通IC卡能玩出什么花样?
R语言对综合社会调查GSS数据进行自举法bootstrap统计推断、假设检验、探索性数据分析可视化
综合社会调查(GSS)是由国家舆论研究中心开展的一项观察性研究。 自 1972 年以来,GSS 一直通过收集当代社会的数据来监测社会学和态度趋势。其目的是解释态度、行为和属性的趋势和常量。从 1972 年到 2004 年,GSS 的目标人群是居住在家庭中的成年人(18 岁以上)。
拓端
2023/08/29
3790
数据与城市正义:回龙观居民“身体被掏空”问题如何解决
本文授权转自一席(yixiclub) 作者&演讲者 | 茅明睿:“城市象限”创始人 我们自发地在开展一些寻求城市正义的实践,但是仅靠我们自己,是没有力量跟公权力、跟开发商、跟市场的资本去博弈的,因为我们缺乏盟友。这些盟友是谁?就是在座的各位,是我们的市民。 视频长约30分钟,请您在wifi条件下观看 我叫茅明睿,是一名北京的规划师。我今天说的是一个比较严肃的话题,是关于数据和城市的正义。乍一看这两个事物是不相干的,那我们就一个一个来看。 城市的正义 :一个人的城市观 ▼ 首先来说一下城市的正义。从我自己的理
大数据文摘
2018/05/21
1.5K0
【案例】SPSS商业应用系列第2篇: 线性回归模型
商业保险公司希望通过分析以往的固定资产保险理赔案例,能够预测理赔金额,借以提高其服务中心处理保险理赔业务的速度和服务质量,并降低公司运营风险。业界领先的预测分析软件 IBM SPSS Statistics 提供了强大的线性回归分析功能,能够有效地解决此类问题。本文结合该商业实例介绍了线性回归模型的基本概念,以及使用 Statistics 进行线性回归分析,解决该商业问题的基本步骤和方法。 Statistics 和 Modeler 作为 IBMSPSS 软件家族中重要的成员,是专业的科
机器学习AI算法工程
2018/03/09
2.5K0
【案例】SPSS商业应用系列第2篇: 线性回归模型
北京四环堵车引发的智能交通大构想
‍‍‍‍‍这是作者关于智能交通协议(Intelligent Transport Protocol)的构想,欢迎留言讨论。
AI科技大本营
2020/04/15
1.4K0
北京四环堵车引发的智能交通大构想
【推荐阅读】如何用大数据构建精准用户画像?
什么是用户画像? 用户画像(User Profile),作为大数据的根基,它完美地抽象出一个用户的信息全貌,为进一步精准、快速地分析用户行为习惯、消费习惯等重要信息,提供了足够的数据基础,奠定了大数
钱塘数据
2018/03/05
3.9K0
【推荐阅读】如何用大数据构建精准用户画像?
风控数据体系-简介
早期传统金融的风控主要利用了信用属性强大的金融数据,一般采用20个维度左右的数据,利用评分来识别客户的还款能力和还款意愿。信用相关程度强的数据维度大概在十个左右,包含年龄、职业、收入、学历、工作单位、借贷情况、房产,汽车、单位、还贷记录等;而互联网金融公司在利用大数据进行风控的同时,会根据需求利用多维度数据来识别借款人风险,维度包括不限于:社交类数据、消费类数据、行为类数据、多源银行账户数据等。
数字悠客
2020/06/29
4.3K0
@文旅人,扩大内需怎么干?中央发文定任务——
近日,中共中央、国务院印发《扩大内需战略规划纲要(2022-2035年)》。关于文化和旅游,《纲要》明确 ↓ 更好满足中高端消费品消费需求。促进免税业健康有序发展。促进民族品牌加强同国际标准接轨,充分衔接国内消费需求,增加中高端消费品国内供应。培育建设国际消费中心城市,打造一批区域消费中心。深入推进海南国际旅游消费中心建设。 扩大文化和旅游消费。完善现代文化产业体系和文化市场体系,推进优质文化资源开发,推动中华优秀传统文化创造性转化、创新性发展。鼓励文化文物单位依托馆藏文化资源,开发各类文化创意产品,扩大
腾讯文旅
2022/12/20
2810
@文旅人,扩大内需怎么干?中央发文定任务——
UCB Data100:数据科学的原理和技巧:第六章到第十章
上一堂课,我们了解了定量和定性变量类型之间的区别。后者包括字符串数据——第 6 讲的主要焦点。在本笔记中,我们将讨论操纵文本所需的工具:python字符串操作和正则表达式。
ApacheCN_飞龙
2024/01/13
6570
UCB Data100:数据科学的原理和技巧:第六章到第十章
金融市场中的人工智能:新算法和解决方案(全)
金融市场可能是少数真正可以被描述为复杂系统的人类成就之一。复杂系统是物理学中的结构,它们:(a) 从组件之间的相互作用中获得其动态的很大一部分,(b) 相互作用高度非线性,并且往往根据其自身的动态(反馈)而变化,© 系统的行为不能直接归因于个体相互作用的纯和:整体远大于个体部分的总和,(d) 并由此产生两个非常重要的后果:对初始条件的非常强烈的依赖(从相似的情况开始,我们观察到完全不同的最终状态)(一个典型的例子是天气预报)。
ApacheCN_飞龙
2024/05/16
5070
金融市场中的人工智能:新算法和解决方案(全)
Python 无监督学习实用指南:1~5
在本章中,我们将介绍基本的机器学习概念,即 ,前提是您具有一些统计学习和概率论的基本知识 。 您将了解机器学习技术的使用以及逻辑过程,这些逻辑过程将增进我们对数据集的性质和属性的了解。 整个过程的目的是建立可支持业务决策的描述性和预测性模型。
ApacheCN_飞龙
2023/04/24
1.3K0
Python 无监督学习实用指南:1~5
推荐阅读
相关推荐
SPSS用K均值聚类KMEANS、决策树、逻辑回归和T检验研究通勤出行交通方式选择的影响因素调查数据分析|附代码数据
更多 >
LV.9
拓端数据
目录
  • 简介
    • 内容
    • 解决方案概述
    • 源代码
  • 1. Logrus - Go的日志API
    • 使用Logrus
    • 更新来源
    • 使用goimports更新导入
  • 配置Logrus
  • 2. Docker Gelf驱动程序
    • 使用Gelf与Logrus挂钩
  • 3.使用“Gelftail”收集和聚合日志记录
  • Gelftail
    • 源代码
    • 生成,Dockerfile,部署
  • 4. Loggly
    • 入门
    • 几个例子
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档