ben.jones
(Ben Jones)
May 17, 2020, 11:23pm
1
Hi,
I have a number of sub-domains being served by Caddy v2 and each one has the following code at the top to define a separate log file;
nextcloud.domain.tld {
log {
output file /var/log/caddy/nextcloud.domain.tld.access.log
}
...
}
I was hoping to simplify this and pull the log
code out into a reusable snippet, something like;
(logging) {
log {
output file /var/log/caddy/{host}.access.log
}
}
So by adding import logging
I would get a separate log (access) file for each site/sub-domain.
But when Caddy starts up I get the following error;
May 18 11:21:17 web01 caddy[11992]: run: loading initial config: loading new config: setting up custom log 'log0': loading log writer module: loading module 'file': provision caddy.logging.writers.file: invalid filename for log file: unrecognized placeholder {http.request.host}
Is this something that should be possible? I couldnāt find anything in the docs which suggests I canāt use http
placeholders in a log filename.
Thanks,
Ben
Logging is initialized at the time that the server starts up, not during requests. Log files are opened once and kept open until the server shuts down. Much more efficient that way.
So the answer is no, you canāt use request placeholders for defining the log filename.
ben.jones
(Ben Jones)
May 17, 2020, 11:29pm
3
Thanks @francislavoie , that makes sense. So there is no way to simplify the logging config? No placeholder for the configured site name/address I could use instead?
Unfortunately, no, not currently.
But your question gave me a thought, it might be possible to implement support for arguments to be passed to snippets on import. Iāll need to spend more time thinking it through though, Iāll reply here if Iāve come up with it.
2 Likes
ben.jones
(Ben Jones)
May 17, 2020, 11:48pm
5
That was the other thought I had also, passing arguments to snippets, but assumed it was not possible. I will leave you to percolateā¦
2 Likes
I would appreciate a way to have one log per host, which I do right now with multiple Ėlog` directives.
If I understand correctly, arguments could be a way to reproduce that setup with just one directive ?
My current thought is to have something like this:
(log_common) {
log {
output file /var/log/caddy/{args.0}.access.log
}
}
a.example.com {
import log_common a.example.com
}
b.example.com {
import log_common b.example.com
}
No promises though.
It would work great for me.
Alright, wrote the proposal:
caddyserver:master
ā francislavoie:import-args
opened 07:04AM - 18 May 20 UTC
Stems from the discussion in https://caddy.community/t/logging-snippet-using-hosā¦ t-placeholder-for-log-filename/8218
The idea here is that it's common for users to want to have one element of an imported snippet or file be replaced with a context-specific value.
This PR adds support for `{args.*}` placeholders at Caddyfile-parse time when importing tokens from either a snippet or file, where `*` is the positional argument number.
The `import` syntax becomes:
```
import <pattern> <args...>
```
---
For example, consider this Caddyfile, where a user wants to enable logging using a common config for each of their sites. You'll see that the log filename is expanded to `/var/log/caddy/a.example.com.access.log`:
```
(logging) {
log {
output file /var/log/caddy/{args.0}.access.log
}
}
a.example.com {
import logging a.example.com
}
b.example.com {
import logging b.example.com
}
```
Adapted JSON output:
```json
{
"logging": {
"logs": {
"default": {
"exclude": [
"http.log.access.log0",
"http.log.access.log1"
]
},
"log0": {
"writer": {
"filename": "/var/log/caddy/a.example.com.access.log",
"output": "file"
},
"include": [
"http.log.access.log0"
]
},
"log1": {
"writer": {
"filename": "/var/log/caddy/b.example.com.access.log",
"output": "file"
},
"include": [
"http.log.access.log1"
]
}
}
},
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"a.example.com"
]
}
],
"terminal": true
},
{
"match": [
{
"host": [
"b.example.com"
]
}
],
"terminal": true
}
],
"logs": {
"logger_names": {
"a.example.com": "log0",
"b.example.com": "log1"
}
}
}
}
}
}
}
```
---
This also supports an arbitrary number of arguments, and supports imported files.
The file `respond.txt`
```
respond "I am {args.0}, hears {args.1}"
```
Caddyfile:
```
example.com
import respond.txt Groot Rocket
import respond.txt you "the confused man"
```
Adapted JSON:
```json
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"example.com"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "I am groot, hears rocket",
"handler": "static_response"
},
{
"body": "I am you, hears the confused man",
"handler": "static_response"
}
]
}
]
}
],
"terminal": true
}
]
}
}
}
}
}
```
3 Likes
ben.jones
(Ben Jones)
May 18, 2020, 7:57am
10
That is incredible @francislavoie - 9 hours from asking the question to a completed PR! Thank you very much! Hopefully others get plenty of use/benefit from this also.
1 Like
I never wrote an update here, but this is now available in Caddy v2.1
1 Like
system
(system)
Closed
October 26, 2020, 6:37pm
12
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.